Visitar URL original
feat: add RubyGems (rubygems.org) as a package registry type by koic · Pull Request #1859 · modelcontextprotocol/registry · GitHub
Skip to content

feat: add RubyGems (rubygems.org) as a package registry type - #1859

Open
koic wants to merge 1 commit into
modelcontextprotocol:mainfrom
koic:add-rubygems-package-registry
Open

koic wants to merge 1 commit into
modelcontextprotocol:mainfrom
koic:add-rubygems-package-registry

Conversation

@koic

@koic koic commented Nov 14, 2026 •

Copy link
Copy Markdown
Member

Motivation and Context

Ruby MCP servers published to rubygems.org cannot be registered through their native package registry today; the only options are an OCI image or an MCPB download. This adds registryType "rubygems", following docs/contributing/add-package-registry.md and mirroring the cargo work (#1207).

Design decisions:

  • Ownership verification reads the gemspec metadata key "mcp_name" from the version-specific rubygems.org API (/api/v2/rubygems/{name}/versions/{version}.json), which covers existence, version, and ownership in a single call. This mirrors the npm validator's manifest-field approach (mcpName in package.json) rather than the README-token approach used for PyPI/NuGet/cargo: rubygems.org has no README API, and gemspec metadata is a first-class, author-controlled field.
  • The platform is left unspecified in that call so that versions published only as platform-specific builds can be registered. rubygems.org then chooses which build to return, so authors must set mcp_name in every platform build.
  • A 404 from the version endpoint is disambiguated with a HEAD probe of /api/v1/versions/{name}.json (gem missing vs version missing vs transient), following the npm validator. Yanked versions 404 on the version endpoint (verified against mimemagic 0.3.0); a 200 carrying yanked=true is still rejected defensively.
  • The documented client invocation is gem exec --silent --conservative --gem NAME -v VERSION COMMAND: --silent keeps install progress off stdout (required for the stdio transport), and --conservative runs offline when the version is already installed. gem exec ships with RubyGems 3.4.8+ (Ruby 3.2.2+), so runtimeHint "gem" is set, unlike cargo which has no single-shot runner.

Closes #1582.

How Has This Been Tested?

  • Validator tests are hermetic httptest mocks, including the positive path, plus live anchors against rubygems.org negative paths (missing mcp_name, missing gem, yanked version).
  • make validate, make test-unit, and make test-integration pass, and golangci-lint v2.14.0 reports 0 issues.
  • The documented invocation was run on RubyGems 4.0.3 from an empty GEM_HOME against an existing MCP server gem (debug-mcp 0.4.0): the first line on stdout is the JSON-RPC initialize response. Without --silent the first line is install output instead. With --conservative an installed version starts with the network blocked; without it the start fails. A -- before COMMAND makes gem exec fail, so the documentation tells clients not to insert one.
  • Not tested: a publish against a real gem carrying mcp_name. I know of no such gem yet (none among the latest versions of 489 MCP-related gems on rubygems.org), so a live positive-path anchor will be added once one is published.

Breaking Changes

None. The change is additive: existing registry types and their validation are untouched.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

## Motivation and Context

Ruby MCP servers published to rubygems.org cannot be registered through their native package registry today;
the only options are an OCI image or an MCPB download. This adds registryType "rubygems",
following docs/contributing/add-package-registry.md and mirroring the cargo work (modelcontextprotocol#1207).

Design decisions:

- Ownership verification reads the gemspec metadata key "mcp_name" from the version-specific rubygems.org API
  (/api/v2/rubygems/{name}/versions/{version}.json), which covers existence, version, and ownership in a single call.
  This mirrors the npm validator's manifest-field approach (mcpName in package.json) rather than the README-token approach
  used for PyPI/NuGet/cargo: rubygems.org has no README API, and gemspec metadata is a first-class, author-controlled field.
- The platform is left unspecified in that call so that versions published only as platform-specific builds can be
  registered. rubygems.org then chooses which build to return, so authors must set mcp_name in every platform build.
- A 404 from the version endpoint is disambiguated with a HEAD probe of /api/v1/versions/{name}.json
  (gem missing vs version missing vs transient), following the npm validator. Yanked versions 404 on the version endpoint
  (verified against mimemagic 0.3.0); a 200 carrying yanked=true is still rejected defensively.
- The documented client invocation is `gem exec --silent --conservative --gem NAME -v VERSION COMMAND`:
  `--silent` keeps install progress off stdout (required for the stdio transport), and `--conservative` runs offline
  when the version is already installed. gem exec ships with RubyGems 3.4.8+ (Ruby 3.2.2+), so runtimeHint "gem" is set,
  unlike cargo which has no single-shot runner.

Closes modelcontextprotocol#1582.

## How Has This Been Tested?

- Validator tests are hermetic httptest mocks, including the positive path, plus live anchors against rubygems.org
  negative paths (missing mcp_name, missing gem, yanked version).
- `make validate`, `make test-unit`, and `make test-integration` pass, and golangci-lint v2.14.0 reports 0 issues.
- The documented invocation was run on RubyGems 4.0.3 from an empty GEM_HOME against an existing MCP server gem
  (debug-mcp 0.4.0): the first line on stdout is the JSON-RPC initialize response. Without `--silent` the first line is
  install output instead. With `--conservative` an installed version starts with the network blocked; without it the start
  fails. A `--` before COMMAND makes gem exec fail, so the documentation tells clients not to insert one.
- Not tested: a publish against a real gem carrying mcp_name. I know of no such gem yet (none among the latest versions
  of 489 MCP-related gems on rubygems.org), so a live positive-path anchor will be added once one is published.

## Breaking Changes

None. The change is additive: existing registry types and their validation are untouched.
@koic
koic force-pushed the add-rubygems-package-registry branch from 7aa9bef to 12b0626 Compare November 14, 2026 16:23

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add RubyGems (rubygems.org) as a supported package registry type

1 participant