Skip to main content

Publishing & Claiming MCP Servers

The MCPBundles public directory at mcpbundles.com/skills is open: anyone can publish a remote MCP server URL, and the verified maintainer can claim it. This guide covers both flows end to end.

The two flows are separated on purpose:

  • Publishing creates the listing. It does not grant edit or scoring rights. Anyone can publish any reachable MCP server URL, which is how the directory grows quickly.
  • Claiming proves you control the server. It grants the right to edit listing metadata (name, description, category, logo, website, contact email, skill content) and to run quality scoring on the listing.

The split exists because if publishing granted maintenance rights, anyone could publish someone else's server URL and quietly inherit them. The OTP claim flow closes that gap, including for self-publishers.

Before You Publish

You will need:

  • A reachable MCP server URL. HTTPS, public internet, responding to tools/list. Streamable HTTP and SSE transports are both supported. Local servers (localhost, 127.0.0.1, private network ranges) are rejected, since the directory is for servers other agents can actually reach.
  • A name and short description for the listing. The name appears as the bundle title; the description is what shows up in the directory grid.
  • (Optional) A logo URL, website URL, and contact email. All editable later by the verified claimer.
  • (For OAuth servers, optional) A pre-acquired access token. Without one, the listing is created with tools=[] and tools are discovered after a maintainer claims and binds a credential. With one, tool discovery runs during publish so the listing is fully populated immediately.

You do not need to be a superuser. Publishing is open to any signed-in MCPBundles account.

Publishing a Server

From the UI

  1. Sign in and open the workspace dropdown menu in the top-right of the dashboard.
  2. Click Publish an MCP server. This routes to the publish wizard.
  3. Paste the server URL and run Analyze. The analyzer probes the URL, detects the transport, identifies the auth requirements, and previews the tool list.
  4. Fill in the listing metadata (name, description, optional logo / website / contact email).
  5. If the server is OAuth-gated and you have a token, the wizard offers an optional advanced section to attach OAuth credentials (oauth_access_token plus refresh, expires, scope, client_id, client_secret as available) so tool discovery runs during publish.
  6. Click Publish. The listing appears at /skills/<slug> immediately.

From the CLI

The same flow is available via the publish_mcp_server Hub tool:

mcpbundles call publish_mcp_server --as mcpbundles_prod -- \
server_url="https://api.example.com/mcp" \
name="Example MCP" \
description="Read-only access to Example's public docs" \
category="documentation" \
logo_url="https://example.com/logo.png" \
contact_email="hello@example.com"

For OAuth servers with a pre-acquired token:

mcpbundles call publish_mcp_server --as mcpbundles_prod -- \
server_url="https://api.example.com/mcp" \
name="Example MCP" \
description="Full Example workspace integration" \
oauth_access_token="$EXAMPLE_OAUTH_TOKEN" \
oauth_refresh_token="$EXAMPLE_REFRESH_TOKEN" \
oauth_expires_in=3600 \
oauth_scope="read write" \
oauth_client_id="$EXAMPLE_CLIENT_ID" \
oauth_client_secret="$EXAMPLE_CLIENT_SECRET"

The response includes the new bundle slug and the public URL. The listing is unclaimed.

What "Unclaimed" Means

An unclaimed listing is fully visible in the directory and discoverable by agents. The only thing missing is editing rights: nobody can change the listing's name, description, or other metadata, and nobody can run the quality score on it. The "Claim this server" CTA is shown on the public skill page and on the workspace bundle page.

If nobody ever claims the listing, it stays in the directory as a community submission. Platform admins can still make corrections.

Claiming a Listing

Claiming is a two-step ownership-of-control proof: the platform reads contact addresses from a /.well-known/ file your server publishes, sends a 6-digit code to one of those addresses, and you enter the code back in the UI.

Step 1 — Publish a Well-Known File on Your Server

The platform looks for two files at the origin of your MCP server URL. For https://api.example.com/mcp, it probes https://api.example.com/.well-known/.... Either file is sufficient.

This is the file purpose-built for the claim flow. Smallest possible shape:

{
"maintainers": [
{ "email": "owner@example.com" },
{ "email": "ops@example.com", "name": "Ops Team" }
]
}

The name field is optional. List your preferred contact first; within the same source group, file order influences the order shown in the claim dialog.

Option B — /.well-known/security.txt (RFC 9116)

If your server already publishes a security.txt for vulnerability reporting, the claim flow will reuse it. Any Contact: line that parses as mailto: is accepted:

# https://example.com/.well-known/security.txt
Contact: mailto:security@example.com
Contact: mailto:owner@example.com
Contact: https://example.com/security
Expires: 2027-01-01T00:00:00.000Z

URL-form contacts are skipped (they don't work for an OTP flow). Unsigned files are accepted; many smaller projects never sign their security.txt and excluding them on that basis would shut out a lot of legitimate maintainers.

If both files are present, addresses found in both are listed first in the claim dialog, then JSON-only addresses, then security.txt-only addresses.

Step 2 — Email Privacy Rules

Two things happen to every email before it's surfaced:

  • Normalization for dedup. Addresses are lowercased, +tag aliases are stripped from the local part, and Gmail dot variations (first.last@gmail.comfirstlast@gmail.com) are collapsed. Multiple addresses that route to the same inbox cannot be used to bypass per-bundle rate limits.
  • Length-preserving masking for display. The claim dialog only ever shows you s*******@e******.***: the first character of the local part and the first character of every dotted domain component, with everything else replaced by *. The full address is never exposed in the UI to anyone, including the claimer. You pick the address by recognizing its shape; the platform sends the code to the un-masked form on the server side.

If the masked option doesn't match what you expect, that's the signal that someone else controls the well-known file. Stop and investigate before continuing.

Step 3 — Run the Claim Flow

From the public skill page (/skills/<slug>), click Claim this server:

  • If you're not signed in, you're sent through /register?callbackUrl=... and dropped on the workspace bundle detail page (/w/<workspace>/bundles/<slug>) with the claim dialog auto-opened.
  • If you're already signed in, you go straight to the same workspace bundle page with the dialog open.

The dialog walks three states:

  1. Eligibility check. The platform fetches the well-known files and shows you the masked candidate addresses. If no candidates are found, it lists the URLs it tried so you know exactly which file to publish (or fix).
  2. Choose an address and send the code. The platform sends a 6-digit numeric code with a 10-minute TTL to the address you select. Resend is rate-limited per bundle to prevent enumeration attacks.
  3. Enter the code. On a correct match, the bundle's claimed_by_user_id and claimed_at are written, an audit row is recorded in mcp_server_claims, and the maintainer panel becomes available.

If the code expires or is wrong three times, the flow restarts from step 2. The only email this flow ever sends is the OTP itself.

What Claiming Grants

A successful claim grants two rights on the listing:

  • Edit listing metadata. Name, description, category, website URL, logo URL, contact email, and the bundle's SKILL_CONTENT.
  • Run quality scoring. Re-run the LLM judge against the server's tool definitions and skill content. The score appears on the public listing page.

It does not grant publishing rights for new versions of the server (the listing always points at the live URL), the ability to suspend or unpublish the listing (still platform-admin only), or visibility into per-workspace credentials (those stay private to the workspaces that bound them).

After You Claim

The bundle detail page (/w/<workspace>/bundles/<slug>) gains a listing maintainer panel above the AI Skill section. From there:

Edit Listing Metadata

Inline form covering name, description, category, website, logo URL, contact email, and skill content. Saves run through the editPublishedMcpServer mutation. Changes are visible on the public skill page on the next page load.

Re-Score the Listing

A Run scoring button triggers the quality rubric. The scorer needs the canonical credential bound on the bundle to discover the live tool list. For OAuth servers, that means completing the OAuth flow at least once after claiming. NONE-auth servers can be scored straight away.

The response carries an actionable_suggestions list ranked by priority:

  1. Server smells. Repeated display_name values across tools.
  2. Bundle deficiencies. Skill content missing or labeled Bad.
  3. Tool issues. Individual tools labeled Bad, sorted by lowest score.

Fix the highest-priority items and hit re-score; the new verdict replaces the old one in the public directory.

Hand Off Maintenance

There is no first-class transfer flow yet. To move a claim to a different maintainer, email hello@mcpbundles.com; a platform admin can release the claim (sets claimed_by_user_id back to NULL) so the new maintainer can re-run the OTP flow themselves.

Common Failure Modes

"No verifiable contact addresses found." The server URL responded but neither /.well-known/security.txt nor /.well-known/mcpbundles.json returned a parseable contact email. The dialog lists the URLs that were probed; publish one of those files with a valid mailto: contact (security.txt) or a valid maintainers[].email entry (mcpbundles.json) and retry.

"This listing isn't open to claims." A platform admin set a claim_disabled_reason on the bundle (typically: the server is operated directly by a vendor who has chosen not to participate in the claim flow). The reason is shown in the UI. Email hello@mcpbundles.com if you believe this is wrong.

"This server URL is already in the public directory." The publish flow deduplicates by base_url. If the existing listing is unclaimed and is yours to maintain, claim it instead of publishing a duplicate. The error message links directly to the existing listing.

OAuth listing has no tools after publish. Expected. Without an oauth_access_token at publish time, tools are discovered after a credential is bound. Either supply token material at publish (CLI) or claim the listing and complete the OAuth flow on the bundle detail page; tools are discovered on credential save.

Code arrived but verification fails. The OTP TTL is 10 minutes. If the code expired, request a new one. If you're certain you typed the correct code, the address you picked may have masked the same way as a different address that routes to a different inbox; go back and inspect every masked option carefully before sending.

See Also