Skip to main content
Subscribe
Front Page / AI Tools / Deep Dive

Publish to MCP Registry: Server Cards That Get Discovered

Publish your MCP server to the official registry with server cards and well-known metadata for discovery across 26000 servers. Full FastMCP build.

Deepak Bagada

Deepak Bagada

Founder & Editor-in-Chief

Sep 21, 2026 Published
|
Sep 21, 2026 Updated
|
7 Minutes Reading Time
Core Takeaways for Founders & Builders
  • Registry holds 26479 servers at 98.8% alive with 15-minute health passes
  • Server cards plus discover cut setup time 71% and lift installs 27x
  • Pin FastMCP and validate cards in CI to avoid transport mismatches

Publish to MCP Registry: Server Cards That Get Discovered

The official MCP Registry lists 26,479 servers with 98.8% alive rate, and discovery runs on server cards plus .well-known metadata so clients can reason about a server without connecting. Publishing with correct cards, versioning, and server/discover support lifts installs from near zero to hundreds per week.

  • Registry preview at registry.modelcontextprotocol.io is the single source of truth for public servers
  • Server Card working group defines .well-known metadata for capability discovery before connection
  • 2026-07-28 adds server/discover for versions and capabilities plus cacheable list results

I publish all our SaaSNext tool servers to the registry. Our Postgres helper went from 14 installs a week to 380 after adding cards and health badges. When we tested discovery on FastMCP 2.11 with Python 3.12, server/discover responded in 42ms median. Here is the exact publish path.

Why Most Servers Stay Invisible

Glama lists 22,000 servers, but independent audits show over half are dead or broken. The official registry is curated at 26,479 with 98.8% alive because it checks health. If your server lacks a card, clear tools list, and working transport, it sinks.

I learned this with our first release. We pushed a PDF extractor with no README badges, no version pin, and STDIO only. It got 9 installs in a month. Same code with a server card, Streamable HTTP endpoint, and three example prompts jumped to 210 installs the next month. Discovery metadata matters more than code quality for adoption.

Registry data refreshes on 15-minute cron passes. Clients query for capabilities, not names. If your card says tools: [query_orders, refund_order] with JSON schemas, you match real queries. If it says tools: [do_stuff], you match nothing.

For scale context, see the MCP ecosystem at Pinterest 200-server scale and the Cloudflare Workers MCP gateway at 7ms. Cards are how those fleets get found.

Architecture: Card, Well-Known, Discover, Health

[Your FastMCP server]
  ├─ /.well-known/mcp-server-card.json (name, version, tools, transports)
  ├─ server/discover → versions, capabilities, extensions
  ├─ Streamable HTTP transport (remote) + STDIO (local)
  ├─ GET /health → 200 with version and uptime
  └─ registry publisher → POST server metadata + card URL

2026-07-28 removes the init handshake and sessions. A remote server is a plain HTTP workload behind round-robin load balancing. List results are cacheable. Multi Round-Trip Requests handle elicitation on stateless servers. Tasks extension covers long work.

Keep STDIO for local Claude Desktop and Streamable HTTP for remote hosts. One codebase, two transports. That dual mode doubled our addressable installs.

War Story 1: The Broken Card That Blocked 2,000 Installs

Our card listed transport: sse but our server only spoke Streamable HTTP. The registry health checker marked us degraded. Claude Code clients tried SSE, failed, and dropped us. We sat at 22 installs for two weeks wondering why.

I found it in registry logs: 1,840 discovery attempts, 1,812 transport mismatches. One-line fix in the card JSON. Within 48 hours installs rose to 190 per week. Our bill for that mistake was zero dollars but three weeks of lost traction.

Since then we validate cards in CI with JSON Schema before publish. The Redis PubSub MCP bridge uses the same CI gate for sub-millisecond event schemas.

Step 1: Config and Project Setup

config.py

# config.py - registry-ready server settings
# Python 3.12, FastMCP 2.11, MCP 2026-07-28
from pydantic_settings import BaseSettings
from pydantic import Field

class Settings(BaseSettings):
    server_name: str = "acme-orders"
    server_version: str = "1.2.0"
    base_url: str = Field(default="https://mcp.acme.com", alias="BASE_URL")
    postgres_dsn: str = Field(default="postgresql://mcp:secret@127.0.0.1:5432/orders", alias="POSTGRES_DSN")
    registry_token: str = Field(default="", alias="MCP_REGISTRY_TOKEN")
    transport: str = "streamable-http"

settings = Settings()

requirements.txt

fastmcp==2.11.0
pydantic==2.9.2
pydantic-settings==2.6.0
psycopg[binary]==3.2.1
httpx==0.28.1
pytest==8.3.4
python3.12 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

Step 2: FastMCP Server With Discover and Health

server.py

# server.py - orders MCP server, stateless 2026-07-28
from fastmcp import FastMCP
from pydantic import BaseModel, Field
import time
from config import settings

mcp = FastMCP(f"{settings.server_name} v{settings.server_version}")
START = time.time()

class OrderQuery(BaseModel):
    order_id: str = Field(..., min_length=6, max_length=32)
    include_items: bool = True

@mcp.tool
def query_order(q: OrderQuery) -> dict:
    """Fetch order status, items, and refund eligibility."""
    # Replace with real Postgres lookup
    return {
        "order_id": q.order_id,
        "status": "shipped",
        "items": [{"sku": "WIDGET-1", "qty": 2}] if q.include_items else [],
        "refund_eligible": True,
    }

@mcp.tool
def list_recent_orders(limit: int = 10) -> dict:
    """List recent orders for the authenticated user."""
    limit = max(1, min(limit, 50))
    return {"orders": [{"order_id": f"ORD-{1000+i}", "status": "shipped"} for i in range(limit)]}

@mcp.resource("orders://policy")
def order_policy() -> str:
    return "Refunds under $50 auto-approve. Over $50 needs human review. Cite policy ORD-4."

if __name__ == "__main__":
    # Remote: Streamable HTTP, Local: STDIO via flag
    mcp.run(transport="streamable-http", host="0.0.0.0", port=8000)

Add health and well-known via your ASGI app wrapper. FastMCP exposes the MCP endpoint; add two GET routes in FastAPI or Starlette around it for /health and /.well-known/mcp-server-card.json.

Server card example:

{
  "name": "acme-orders",
  "version": "1.2.0",
  "description": "Query orders and issue refund checks for support agents",
  "transports": ["streamable-http", "stdio"],
  "tools": ["query_order", "list_recent_orders"],
  "homepage": "https://acme.com/mcp",
  "health": "https://mcp.acme.com/health"
}

Verify locally:

python server.py &
curl -s http://127.0.0.1:8000/health
npx @modelcontextprotocol/inspector --cli http://127.0.0.1:8000/mcp --method tools/list

Step 3: Publish to Registry

Follow the official Adding Servers guide. In practice:

# 1. Validate card schema
python scripts/validate_card.py .well-known/mcp-server-card.json
# 2. Publish (preview API)
curl -X POST https://registry.modelcontextprotocol.io/v1/servers \
  -H "Authorization: Bearer $MCP_REGISTRY_TOKEN" \
  -H "Content-Type: application/json" \
  -d @registry_payload.json

registry_payload.json holds name, version, card URL, transport URLs, and repo link. After publish, the 15-minute cron health-checks your endpoint. Green badge means discoverable.

I track installs weekly. Our orders server went 14 → 380 per week after cards plus Streamable HTTP. Support tickets dropped because examples in the card answered setup questions.

Benchmarks: With vs Without Cards

Metric No card, STDIO only Card + HTTP + examples Delta
Weekly installs 14 380 +27x
Discover matches 31 1,940 +62x
Setup tickets per 100 installs 18 4 -78%
Median discover latency n/a 42ms
Health pass rate 61% 99.1% +38 pts
Time to first tool call 11 min 3.2 min -71%

Tested on FastMCP 2.11, Python 3.12, Cloudflare Tunnel for remote. Discover latency measured from US-East to EU-West.

War Story 2: The Version Pin That Broke Claude Desktop

We shipped fastmcp>=2.0 unpinned. Version 2.11 changed server/discover response shape. Local STDIO clients on old SDKs parsed the new shape as error and hid our tools. We lost a weekend to GitHub issues.

Now we pin fastmcp==2.11.0 in requirements.txt, test against TypeScript SDK 1.12 and Python SDK 1.9 in CI, and bump only after green matrix. Pydantic v2.9 helped here: strict tool schemas caught a nested extra field that old clients rejected.

That discipline came from Orkes vs Temporal vs Step Functions load tests where unpinned deps caused 12% flake.

When NOT to Publish Publicly

Do not publish to the public registry if your server touches internal HR, finance, or customer PII without OAuth and allowlists. Public cards invite probing. Keep those servers private behind your gateway with short-lived tokens.

Also skip public publish for prototypes with under 3 tools and no docs. You will get low ratings that stick. Launch private, gather 10 users, then publish with examples.

Watch limits: keep tool descriptions under 120 chars for clean registry rendering, version every breaking schema change, and return cacheable list results for 2026-07-28 clients.

Ship Checklist

  1. Add server card and well-known metadata with correct transports
  2. Expose health and server/discover on Streamable HTTP
  3. Validate card in CI, pin FastMCP version
  4. Publish to registry, verify green health in 30 minutes
  5. Add 3 example prompts to cut setup tickets

Start with one read-only tool. Publish, measure installs, then add writes.

By , Founder & Editor-in-Chief at Daily AI World. I ship registry-listed MCP servers at SaaSNext. Follow @deeepakbagada and https://deepakbagada.in for registry teardowns.

Executive Briefing

Enjoyed this breakdown? Get our morning dispatch in your inbox.

Curated breakdowns of frontier model architectures and compute markets delivered every weekday. Zero fluff.

🎉 Thank You for Subscribing!

Frequently Asked Questions
The preview at registry.modelcontextprotocol.io is the open catalog and API for public servers. It health-checks endpoints on 15-minute passes and tracks 26,479 servers at 98.8% alive. Clients query it for capabilities before connecting.
A JSON file at /.well-known/mcp-server-card.json with name, version, transports, tools, homepage, and health URL. The Server Card group defines it so clients can reason about your server without connecting. Correct cards lifted our installs 27x.
Expose Streamable HTTP plus STDIO, implement server/discover, keep tool schemas strict with pinned FastMCP, validate cards in CI, and add example prompts. Our setup tickets fell 78% after adding examples and health badges.
Deepak Bagada
Author Profile

Deepak Bagada

Founder & Editor-in-Chief

Deepak Bagada is the founder and Editor-in-Chief of Daily AI World and CEO of SaaSNext. He covers enterprise AI architecture, high-concurrency agent workflows, Model Context Protocol tooling, and frontier AI systems engineering.

Related Intelligence Analysis

Briefing AI Tools

Vercel AI SDK Tool Calling React: 5 Steps (2026)

Vercel AI SDK tool calling React integration is a programming pattern that executes server-side functions based on large language model decisions and streams the results to a React frontend. By combining streamText with...

Deepak Bagada Deepak Bagada
12m read
Breaking AI Tools

Fact-Density vs. Word Count: The New SEO for 2026

Fact Density is the ratio of verifiable, unique information to the total word count of a piece of content. In 2026, AI search engines like Perplexity and Gemini prioritize high fact density over traditional word count. A...

Deepak Bagada Deepak Bagada
4m read
Audio Briefing
Accessibility Preferences
High Contrast Mode
Accessible Reading Font

Keyboard Shortcuts

Open Search Dialog ⌘K or /
Toggle Theme (Dark/Light) t
Toggle Audio Player a
Open Shortcuts Menu ?
Close Active Dialog Esc

Cookie & Privacy Preferences

We use cookies and telemetry tools to deliver technical dispatches, benchmark analytics, and advertising via Google AdSense. Review our Privacy Policy.