diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ba42d7b809..4bd8116ed3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -193,8 +193,108 @@ jobs: env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + publish-registry-npm: + needs: [update-packages, create-metadata, publish-npm] + # Run on partial matrix failures so successful npm publishes still get + # registered. Per-package mcp-publisher will fail if the npm version + # doesn't exist, which surfaces the upstream failure naturally. + if: ${{ !cancelled() && (needs.publish-npm.result == 'success' || needs.publish-npm.result == 'failure') }} + strategy: + fail-fast: false + matrix: + package: ${{ fromJson(needs.create-metadata.outputs.npm_packages) }} + name: Registry ${{ matrix.package }} + runs-on: ubuntu-latest + environment: release + permissions: + id-token: write # Required for GitHub OIDC + contents: read + env: + MCP_PUBLISHER_VERSION: v1.7.9 + MCP_PUBLISHER_SHA256: ab128162b0616090b47cf245afe0a23f3ef08936fdce19074f5ba0a4469281ac + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ needs.create-metadata.outputs.version }} + + - name: Check for server.json + id: check + run: | + if [ -f "src/${{ matrix.package }}/server.json" ]; then + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "exists=false" >> $GITHUB_OUTPUT + fi + + - name: Install mcp-publisher + if: steps.check.outputs.exists == 'true' + run: | + curl -fL "https://github.com/modelcontextprotocol/registry/releases/download/${MCP_PUBLISHER_VERSION}/mcp-publisher_linux_amd64.tar.gz" -o mcp-publisher.tar.gz + echo "${MCP_PUBLISHER_SHA256} mcp-publisher.tar.gz" | sha256sum -c - + tar xzf mcp-publisher.tar.gz mcp-publisher + rm mcp-publisher.tar.gz + + - name: Authenticate to MCP Registry + if: steps.check.outputs.exists == 'true' + run: ./mcp-publisher login github-oidc + + - name: Publish to MCP Registry + if: steps.check.outputs.exists == 'true' + working-directory: src/${{ matrix.package }} + run: ../../mcp-publisher publish + + publish-registry-pypi: + needs: [update-packages, create-metadata, publish-pypi] + # Run on partial matrix failures so successful PyPI publishes still get + # registered. Per-package mcp-publisher will fail if the PyPI version + # doesn't exist, which surfaces the upstream failure naturally. + if: ${{ !cancelled() && (needs.publish-pypi.result == 'success' || needs.publish-pypi.result == 'failure') }} + strategy: + fail-fast: false + matrix: + package: ${{ fromJson(needs.create-metadata.outputs.pypi_packages) }} + name: Registry ${{ matrix.package }} + runs-on: ubuntu-latest + environment: release + permissions: + id-token: write # Required for GitHub OIDC + contents: read + env: + MCP_PUBLISHER_VERSION: v1.7.9 + MCP_PUBLISHER_SHA256: ab128162b0616090b47cf245afe0a23f3ef08936fdce19074f5ba0a4469281ac + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ needs.create-metadata.outputs.version }} + + - name: Check for server.json + id: check + run: | + if [ -f "src/${{ matrix.package }}/server.json" ]; then + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "exists=false" >> $GITHUB_OUTPUT + fi + + - name: Install mcp-publisher + if: steps.check.outputs.exists == 'true' + run: | + curl -fL "https://github.com/modelcontextprotocol/registry/releases/download/${MCP_PUBLISHER_VERSION}/mcp-publisher_linux_amd64.tar.gz" -o mcp-publisher.tar.gz + echo "${MCP_PUBLISHER_SHA256} mcp-publisher.tar.gz" | sha256sum -c - + tar xzf mcp-publisher.tar.gz mcp-publisher + rm mcp-publisher.tar.gz + + - name: Authenticate to MCP Registry + if: steps.check.outputs.exists == 'true' + run: ./mcp-publisher login github-oidc + + - name: Publish to MCP Registry + if: steps.check.outputs.exists == 'true' + working-directory: src/${{ matrix.package }} + run: ../../mcp-publisher publish + create-release: - needs: [update-packages, create-metadata, publish-pypi, publish-npm] + needs: [update-packages, create-metadata, publish-pypi, publish-npm, publish-registry-npm, publish-registry-pypi] if: | always() && needs.update-packages.outputs.changes_made == 'true' && diff --git a/scripts/release.py b/scripts/release.py index e4ce1274c3..40064e3847 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -51,6 +51,23 @@ def convert( GIT_HASH = GitHashParamType() +def _update_server_json(path: Path, version: Version) -> None: + server_json_path = path / "server.json" + if not server_json_path.exists(): + return + + with open(server_json_path, "r") as f: + data = json.load(f) + + data["version"] = version + for package in data.get("packages", []): + package["version"] = version + + with open(server_json_path, "w") as f: + json.dump(data, f, indent=2) + f.write("\n") + + class Package(Protocol): path: Path @@ -58,6 +75,8 @@ def package_name(self) -> str: ... def update_version(self, version: Version) -> None: ... + def update_server_json(self, version: Version) -> None: ... + @dataclass class NpmPackage: @@ -75,6 +94,9 @@ def update_version(self, version: Version): json.dump(data, f, indent=2) f.truncate() + def update_server_json(self, version: Version): + _update_server_json(self.path, version) + @dataclass class PyPiPackage: @@ -100,6 +122,9 @@ def update_version(self, version: Version): # Regenerate uv.lock to match the updated pyproject.toml subprocess.run(["uv", "lock"], cwd=self.path, check=True) + def update_server_json(self, version: Version): + _update_server_json(self.path, version) + def has_changes(path: Path, git_hash: GitHash) -> bool: """Check if any files changed between current state and git hash""" @@ -152,6 +177,7 @@ def update_packages(directory: Path, git_hash: GitHash) -> int: for package in find_changed_packages(path, git_hash): name = package.package_name() package.update_version(version) + package.update_server_json(version) click.echo(f"{name}@{version}") diff --git a/src/everything/server.json b/src/everything/server.json new file mode 100644 index 0000000000..a667d9a91c --- /dev/null +++ b/src/everything/server.json @@ -0,0 +1,51 @@ +{ + "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", + "name": "io.github.modelcontextprotocol/server-everything", + "description": "MCP server that exercises all the features of the MCP protocol", + "version": "2.0.0", + "repository": { + "url": "https://github.com/modelcontextprotocol/servers", + "source": "github", + "subfolder": "src/everything" + }, + "packages": [ + { + "registryType": "npm", + "identifier": "@modelcontextprotocol/server-everything", + "version": "2.0.0", + "runtimeHint": "npx", + "packageArguments": [ + { + "type": "positional", + "value": "stdio", + "valueHint": "transport" + } + ], + "transport": { "type": "stdio" } + }, + { + "registryType": "npm", + "identifier": "@modelcontextprotocol/server-everything", + "version": "2.0.0", + "runtimeHint": "npx", + "packageArguments": [ + { + "type": "positional", + "value": "streamableHttp", + "valueHint": "transport" + } + ], + "environmentVariables": [ + { + "name": "PORT", + "description": "Port the local HTTP server binds to.", + "default": "3001" + } + ], + "transport": { + "type": "streamable-http", + "url": "http://localhost:{PORT}/mcp" + } + } + ] +} diff --git a/src/fetch/server.json b/src/fetch/server.json new file mode 100644 index 0000000000..a6c9c458e2 --- /dev/null +++ b/src/fetch/server.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", + "name": "io.github.modelcontextprotocol/server-fetch", + "description": "MCP server providing tools to fetch and convert web content for LLMs", + "version": "0.6.3", + "repository": { + "url": "https://github.com/modelcontextprotocol/servers", + "source": "github", + "subfolder": "src/fetch" + }, + "packages": [ + { + "registryType": "pypi", + "identifier": "mcp-server-fetch", + "version": "0.6.3", + "runtimeHint": "uvx", + "transport": { "type": "stdio" } + } + ] +} diff --git a/src/filesystem/server.json b/src/filesystem/server.json new file mode 100644 index 0000000000..21998dfd11 --- /dev/null +++ b/src/filesystem/server.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", + "name": "io.github.modelcontextprotocol/server-filesystem", + "description": "MCP server for filesystem access", + "version": "0.6.3", + "repository": { + "url": "https://github.com/modelcontextprotocol/servers", + "source": "github", + "subfolder": "src/filesystem" + }, + "packages": [ + { + "registryType": "npm", + "identifier": "@modelcontextprotocol/server-filesystem", + "version": "0.6.3", + "runtimeHint": "npx", + "packageArguments": [ + { + "type": "positional", + "valueHint": "allowed_directory", + "description": "An absolute path the server is allowed to access. Pass one or more.", + "format": "filepath", + "isRequired": true, + "isRepeated": true + } + ], + "transport": { "type": "stdio" } + } + ] +} diff --git a/src/git/server.json b/src/git/server.json new file mode 100644 index 0000000000..6e67855b59 --- /dev/null +++ b/src/git/server.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", + "name": "io.github.modelcontextprotocol/server-git", + "description": "MCP server for reading, searching, and manipulating Git repositories via LLMs", + "version": "0.6.2", + "repository": { + "url": "https://github.com/modelcontextprotocol/servers", + "source": "github", + "subfolder": "src/git" + }, + "packages": [ + { + "registryType": "pypi", + "identifier": "mcp-server-git", + "version": "0.6.2", + "runtimeHint": "uvx", + "transport": { "type": "stdio" } + } + ] +} diff --git a/src/memory/server.json b/src/memory/server.json new file mode 100644 index 0000000000..bbcb3745f4 --- /dev/null +++ b/src/memory/server.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", + "name": "io.github.modelcontextprotocol/server-memory", + "description": "MCP server for enabling memory for Claude through a knowledge graph", + "version": "0.6.3", + "repository": { + "url": "https://github.com/modelcontextprotocol/servers", + "source": "github", + "subfolder": "src/memory" + }, + "packages": [ + { + "registryType": "npm", + "identifier": "@modelcontextprotocol/server-memory", + "version": "0.6.3", + "runtimeHint": "npx", + "transport": { "type": "stdio" } + } + ] +} diff --git a/src/sequentialthinking/server.json b/src/sequentialthinking/server.json new file mode 100644 index 0000000000..f5caaab143 --- /dev/null +++ b/src/sequentialthinking/server.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", + "name": "io.github.modelcontextprotocol/server-sequential-thinking", + "description": "MCP server for sequential thinking and problem solving", + "version": "0.6.2", + "repository": { + "url": "https://github.com/modelcontextprotocol/servers", + "source": "github", + "subfolder": "src/sequentialthinking" + }, + "packages": [ + { + "registryType": "npm", + "identifier": "@modelcontextprotocol/server-sequential-thinking", + "version": "0.6.2", + "runtimeHint": "npx", + "transport": { "type": "stdio" } + } + ] +} diff --git a/src/time/server.json b/src/time/server.json new file mode 100644 index 0000000000..6993665a1f --- /dev/null +++ b/src/time/server.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", + "name": "io.github.modelcontextprotocol/server-time", + "description": "MCP server providing tools for time queries and timezone conversions for LLMs", + "version": "0.6.2", + "repository": { + "url": "https://github.com/modelcontextprotocol/servers", + "source": "github", + "subfolder": "src/time" + }, + "packages": [ + { + "registryType": "pypi", + "identifier": "mcp-server-time", + "version": "0.6.2", + "runtimeHint": "uvx", + "transport": { "type": "stdio" } + } + ] +}