Skip to main content
Glama
release-notes-mcp

release-notes-mcp

by vaggeliskls

release-notes-mcp

A small, generic MCP server that combines GitHub releases from several repositories into a single product release note. The server just fetches and bundles raw data; the LLM synthesizes the final notes.

Nothing is architecture-specific:

  • provider — which forge to read releases from: github (default), gitlab, or gitea/Forgejo. Release fetching goes through a small adapter, so adding a forge means normalizing its release JSON — a contained change.

  • repos — the repos the server is allowed to read releases from.

  • contextSources — arbitrary URLs loaded as background context (a style guide, a versions file, feature names — anything). The server assigns no meaning; what each source is is decided by what you put behind the URL.

Configuration

Config holds no secrets — only the repo set and context. Provider and auth come from the environment.

// config.json — non-sensitive (required; the server errors if it's missing)
{
  "repos": [
    "myorg/auth-service",
    "myorg/web"
  ],
  "contextSources": [
    {
      "name": "release-info",
      "url": "https://example.github.io/whatever/release.json",
      "description": "Extra context to consult when assembling release notes"
    }
  ]
}

Environment (provider-agnostic, set in .env or your shell):

Var

Purpose

Default

TOKEN

Auth token for the provider — never in config

(empty; ok for public repos)

PROVIDER

github | gitlab | gitea (overrides config)

github

BASE_URL

API base — only for self-hosted GitLab / Gitea

provider default

  • format on a context source is optional — auto-detected from Content-Type / URL extension / content sniffing. Override only when wrong.

Token permissions

The server only ever reads releases (GET /repos/{owner}/{repo}/releases…), so give TOKEN the minimum read scope — never write access.

Provider

Public repos

Private repos

GitHub — fine-grained PAT

no token needed

Contents: Read-only (releases live under Contents), for each repo you list

GitHub — classic PAT

no token needed (or public_repo)

repo scope

GitLab

no token needed

read_api scope

Gitea / Forgejo

no token needed

read:repository scope

For GitHub, a fine-grained PAT scoped to just the repos in config.json with Contents → Read-only is the tightest setup and is all this server requires.

The config (repos + contextSources) must come from one of two places — the server errors on startup if neither is set:

Source

Use it for

RELEASE_MCP_CONFIG_JSON

The config as inline JSON. No file needed — ideal for uvx / MCP hubs where everything is an env var.

RELEASE_MCP_CONFIG

Path to a config.json file (default ./config.json). Used by the container, which mounts a real file.

Inline JSON wins when both are set. Copy config.example.json to get started with the file approach.

Related MCP server: Documentation MCP Server

Tools

Tool

Purpose

list_repos()

The configured repos

list_releases(repo, limit)

Recent releases for one repo

get_latest_version(repo)

Newest release for one repo

get_release(repo, tag)

Full notes for one tag

compare_releases(repo, from_tag, to_tag)

All releases between two versions

gather_release_notes(selections[])

Bundle raw notes from N (repo, tag) pairs (concurrent)

get_context(name?)

Load configured context URLs (auto-detected format)

Selection is dynamic — you (or Claude) pass the (repo, tag) pairs to combine. The server's instructions tell Claude to call get_context() first.

Run

The server runs in a container over HTTP transport on localhost:8000. First create the config and env files (both runs need them):

cp config.example.json config.json   # edit repos + contextSources (no secrets)
cp .env.example .env                  # set TOKEN (+ PROVIDER / BASE_URL if needed)

Normal run

docker compose up -d

Local development — docker compose watch

For local dev, docker compose watch keeps the server live while you edit:

docker compose watch

Change

Action

server.py

sync + restart — copied into the container, process restarts

requirements.txt, Dockerfile

rebuild — image is rebuilt automatically

config.json

bind-mounted (live); run docker compose restart to reload it

Run with uvx (no clone, no container)

The server is published to PyPI, so a client can launch it on demand with uvx — no checkout and no Docker:

uvx release-notes-mcp

uvx talks to the server over stdio (the default transport). Since there's no file to mount, pass the config inline as JSON via RELEASE_MCP_CONFIG_JSON (everything is env-only — ideal for MCP hubs):

RELEASE_MCP_CONFIG_JSON='{"repos":["myorg/web"],"contextSources":[]}' \
  TOKEN=ghp_... uvx release-notes-mcp

Prefer a file? Point RELEASE_MCP_CONFIG at an absolute path instead (uvx runs from an unknown working directory, so a relative path won't resolve):

RELEASE_MCP_CONFIG=/abs/path/config.json TOKEN=ghp_... uvx release-notes-mcp

Register with Claude Code

HTTP (container) — point Claude Code at the running server by its URL:

claude mcp add --transport http release-notes http://localhost:8000/mcp

stdio (uvx) — let Claude Code launch the server as a subprocess:

claude mcp add release-notes \
  --env RELEASE_MCP_CONFIG=/abs/path/config.json \
  --env TOKEN=ghp_... \
  -- uvx release-notes-mcp

Then ask Claude: "Combine the latest releases of auth-service and web into a product release note."

Available Tools

7 tools
compare_releasesA

Return every release in repo published after from_tag up to and including to_tag (newest first) — useful when a service jumped several versions.

Bodies are omitted by default (pass include_body=True for the notes text).

Inputs: repo (required), to_tag (required), from_tag (required), include_body. Returns: result

gather_release_notesA

Bundle raw release notes for an explicit list of selections so they can be synthesized into a single product release.

selections is a list of {"repo": "owner/name", "tag": "v1.2.3"}. Fetches all entries concurrently.

Inputs: selections (required). Returns: result

get_contextA

Load supplementary context the user configured in contextSources.

Call this first when assembling release notes. With no argument it loads all sources; pass name to load just one. Format is auto-detected.

Inputs: name. Returns: result

get_latest_versionA

Get the latest published release for one repo.

Inputs: repo (required). Returns: object

get_releaseB

Get the full release notes for a specific tag in one repo.

Inputs: tag (required), repo (required). Returns: object

list_releasesA

List recent releases for one repo (newest first). repo is 'owner/name'.

By default the release body is omitted to keep the response small — pass include_body=True only when you need the notes text. published_after (ISO-8601, e.g. '2026-06-02' or '2026-06-02T14:18:43Z') keeps only releases published strictly after that instant. limit caps the number of releases returned; when filtering by published_after the server scans up to 100 releases of history (the same ceiling as compare_releases) before applying it, so the filter sees real history rather than just the first limit rows.

Inputs: repo (required), limit, include_body, published_after. Returns: result

list_reposA

List the repositories and provider this server is configured to read.

Inputs: no named parameters. Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.2/5.0

    Scored across 7 tools

    Disambiguation5/5

    Each tool targets a distinct resource or action: repo discovery, release listing, latest version, specific release, range comparison, bulk gathering, and context loading. No two tools appear to serve the same purpose.

    Naming Consistency5/5

    All tool names follow a consistent snake_case verb_noun pattern: list_repos, list_releases, get_latest_version, get_release, compare_releases, gather_release_notes, get_context. Naming style is uniform and predictable.

    Tool Count5/5

    Seven tools is well within the ideal 3-15 range for a focused release-notes server. Each tool earns its place with a clear role in the workflow.

    Completeness5/5

    The tool surface covers the full release-notes lifecycle: discovering repositories, listing and filtering releases, drilling into specific versions, comparing ranges, bundling multiple notes, and pulling supplementary context. No obvious operational gap remains.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers