{
  "markdown": "# release-notes-mcp\n\n<!-- mcp-name: io.github.vaggeliskls/release-notes-mcp -->\n\nA small, generic MCP server that combines GitHub releases from several\nrepositories into a single product release note. The server just fetches and\nbundles raw data; the LLM synthesizes the final notes.\n\nNothing is architecture-specific:\n\n- **`provider`** — which forge to read releases from: `github` (default),\n  `gitlab`, or `gitea`/Forgejo. Release fetching goes through a small adapter,\n  so adding a forge means normalizing its release JSON — a contained change.\n- **`repos`** — the repos the server is allowed to read releases from.\n- **`contextSources`** — arbitrary URLs loaded as background context (a style\n  guide, a versions file, feature names — anything). The server assigns no\n  meaning; what each source *is* is decided by what you put behind the URL.\n\n## Configuration\n\nConfig holds **no secrets** — only the repo set and context. Provider and auth\ncome from the environment.\n\n```jsonc\n// config.json — non-sensitive (required; the server errors if it's missing)\n{\n  \"repos\": [\n    \"myorg/auth-service\",\n    \"myorg/web\"\n  ],\n  \"contextSources\": [\n    {\n      \"name\": \"release-info\",\n      \"url\": \"https://example.github.io/whatever/release.json\",\n      \"description\": \"Extra context to consult when assembling release notes\"\n    }\n  ]\n}\n```\n\nEnvironment (provider-agnostic, set in `.env` or your shell):\n\n| Var | Purpose | Default |\n|-----|---------|---------|\n| `TOKEN` | Auth token for the provider — **never in config** | _(empty; ok for public repos)_ |\n| `PROVIDER` | `github` \\| `gitlab` \\| `gitea` (overrides config) | `github` |\n| `BASE_URL` | API base — only for self-hosted GitLab / Gitea | provider default |\n\n- `format` on a context source is **optional** — auto-detected from\n  `Content-Type` / URL extension / content sniffing. Override only when wrong.\n\n### Token permissions\n\nThe server only ever **reads releases** (`GET /repos/{owner}/{repo}/releases…`),\nso give `TOKEN` the minimum read scope — never write access.\n\n| Provider | Public repos | Private repos |\n|----------|--------------|---------------|\n| **GitHub** — fine-grained PAT | no token needed | **Contents: Read-only** (releases live under Contents), for each repo you list |\n| **GitHub** — classic PAT | no token needed (or `public_repo`) | `repo` scope |\n| **GitLab** | no token needed | `read_api` scope |\n| **Gitea / Forgejo** | no token needed | `read:repository` scope |\n\nFor GitHub, a fine-grained PAT scoped to just the repos in `config.json` with\n**Contents → Read-only** is the tightest setup and is all this server requires.\n\n**The config (repos + contextSources) must come from one of two places** — the\nserver errors on startup if neither is set:\n\n| Source | Use it for |\n|--------|-----------|\n| `RELEASE_MCP_CONFIG_JSON` | The config as **inline JSON**. No file needed — ideal for `uvx` / MCP hubs where everything is an env var. |\n| `RELEASE_MCP_CONFIG` | Path to a `config.json` **file** (default `./config.json`). Used by the container, which mounts a real file. |\n\nInline JSON wins when both are set. Copy `config.example.json` to get started\nwith the file approach.\n\n## Tools\n\n| Tool | Purpose |\n|------|---------|\n| `list_repos()` | The configured repos |\n| `list_releases(repo, limit)` | Recent releases for one repo |\n| `get_latest_version(repo)` | Newest release for one repo |\n| `get_release(repo, tag)` | Full notes for one tag |\n| `compare_releases(repo, from_tag, to_tag)` | All releases between two versions |\n| `gather_release_notes(selections[])` | Bundle raw notes from N `(repo, tag)` pairs (concurrent) |\n| `get_context(name?)` | Load configured context URLs (auto-detected format) |\n\nSelection is **dynamic** — you (or Claude) pass the `(repo, tag)` pairs to\ncombine. The server's `instructions` tell Claude to call `get_context()` first.\n\n## Run\n\nThe server runs in a container over **HTTP transport** on `localhost:8000`.\nFirst create the config and env files (both runs need them):\n\n```bash\ncp config.example.json config.json   # edit repos + contextSources (no secrets)\ncp .env.example .env                  # set TOKEN (+ PROVIDER / BASE_URL if needed)\n```\n\n### Normal run\n\n```bash\ndocker compose up -d\n```\n\n### Local development — `docker compose watch`\n\nFor local dev, `docker compose watch` keeps the server live while you edit:\n\n```bash\ndocker compose watch\n```\n\n| Change | Action |\n|--------|--------|\n| `server.py` | **sync + restart** — copied into the container, process restarts |\n| `requirements.txt`, `Dockerfile` | **rebuild** — image is rebuilt automatically |\n| `config.json` | bind-mounted (live); run `docker compose restart` to reload it |\n\n### Run with `uvx` (no clone, no container)\n\nThe server is published to PyPI, so a client can launch it on demand with\n[`uvx`](https://docs.astral.sh/uv/) — no checkout and no Docker:\n\n```bash\nuvx release-notes-mcp\n```\n\n`uvx` talks to the server over **stdio** (the default transport). Since there's\nno file to mount, pass the config **inline** as JSON via `RELEASE_MCP_CONFIG_JSON`\n(everything is env-only — ideal for MCP hubs):\n\n```bash\nRELEASE_MCP_CONFIG_JSON='{\"repos\":[\"myorg/web\"],\"contextSources\":[]}' \\\n  TOKEN=ghp_... uvx release-notes-mcp\n```\n\nPrefer a file? Point `RELEASE_MCP_CONFIG` at an **absolute** path instead\n(`uvx` runs from an unknown working directory, so a relative path won't resolve):\n\n```bash\nRELEASE_MCP_CONFIG=/abs/path/config.json TOKEN=ghp_... uvx release-notes-mcp\n```\n\n## Register with Claude Code\n\n**HTTP (container)** — point Claude Code at the running server by its URL:\n\n```bash\nclaude mcp add --transport http release-notes http://localhost:8000/mcp\n```\n\n**stdio (`uvx`)** — let Claude Code launch the server as a subprocess:\n\n```bash\nclaude mcp add release-notes \\\n  --env RELEASE_MCP_CONFIG=/abs/path/config.json \\\n  --env TOKEN=ghp_... \\\n  -- uvx release-notes-mcp\n```\n\nThen ask Claude: *\"Combine the latest releases of auth-service and web into a\nproduct release note.\"*\n",
  "bytes": 5989,
  "sha": "f3b8e4a017eb716980e373b2165f8db739a529f4ad305faa410a39ae617ed715",
  "repo_slug": "vaggeliskls/release-notes-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_vaggeliskls_release_notes_mcp_03b0b2ab/readme"
}