modelcontextprotocol / modelcontextprotocol/ext-server-card

Reference implementation showcase: GitHub MCP Server card + AI/MCP catalog (live wire formats & routes)

Open
#34 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
8
Forks
5
PR merge metrics
No merged PRs in 30d

Description

Reference implementation showcase — GitHub MCP Server

A working reference implementation of SEP-2127 (Server Card) + AI Catalog discovery for the GitHub MCP Server is now wired end-to-end across three documents. This issue captures the live wire formats and routes so the WG can sanity-check the shape against the spec. Values below were captured from a running build with dev hostnames substituted for production (github.com, api.githubcopilot.com); icon data: URIs are elided for readability.

Discovery flow
flowchart LR
  C[Client] -->|GET /.well-known/ai-catalog.json| A[github.com]
  A -->|entry.url| SC[api.githubcopilot.com/mcp/server-card]
  C -->|GET server-card| SC
  SC -->|remotes0.url| M[api.githubcopilot.com/mcp/]
  C -->|connect streamable-http| M
Routes
Document Route Served by Media type
AI Catalog GET https://github.com/.well-known/ai-catalog.json github.com application/ai-catalog+json
MCP Catalog (transitional) GET https://github.com/.well-known/mcp/catalog.json github.com application/json
Server Card GET https://api.githubcopilot.com/mcp/server-card hosted GitHub MCP Server application/mcp-server-card+json

Per-environment hosts (same shapes, host varies):

Env Catalog host Card host
github.com (dotcom) github.com api.githubcopilot.com
Proxima / data-residency {tenant}.ghe.com copilot-api.{tenant}.ghe.com
GHES not served not served

The card host is derived per-request (e.g. from X-Forwarded-Host) so a single implementation serves every tenant; GHES is deliberately excluded.

Shared HTTP behavior (all three endpoints)
  • CORS (read-only): Access-Control-Allow-Origin: *, Access-Control-Allow-Methods: GET, Access-Control-Allow-Headers: Content-Type
  • Caching: Cache-Control: public, max-age=3600
  • Conditional requests: strong/weak ETag + If-None-Match304 Not Modified (this is exactly the SHOULD proposed in #33)
  • Content negotiation on Accept
  • No authentication — all three are public metadata

1. Server Card — application/mcp-server-card+json

GET https://api.githubcopilot.com/mcp/server-card

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/v1/server-card.schema.json",
  "name": "io.github.github/github-mcp-server",
  "version": "1.4.0",
  "description": "Connect AI assistants to GitHub - manage repos, issues, PRs, and workflows through natural language.",
  "title": "GitHub",
  "websiteUrl": "https://github.com/github/github-mcp-server",
  "repository": {
    "url": "https://github.com/github/github-mcp-server",
    "source": "github",
    "id": "942771284"
  },
  "icons": [
    { "src": "data:image/png;base64,iVBORw0KGgoAAAANSUh…(GitHub mark, light)", "mimeType": "image/png", "sizes": ["24x24"], "theme": "light" },
    { "src": "data:image/png;base64,iVBORw0KGgoAAAANSUh…(GitHub mark, dark)",  "mimeType": "image/png", "sizes": ["24x24"], "theme": "dark" }
  ],
  "remotes": [
    {
      "type": "streamable-http",
      "url": "https://api.githubcopilot.com/mcp/",
      "headers": [
        {
          "description": "Authorization header with authentication token (PAT or App token)",
          "isRequired": true,
          "isSecret": true,
          "name": "Authorization"
        }
      ],
      "supportedProtocolVersions": ["2025-11-25", "2025-06-18", "2025-03-26", "2024-11-05"]
    }
  ]
}

Notes:

  • Remote-only: no packages, no enumerated primitives (tools/resources/prompts) — those stay in the MCP Registry server.json and runtime listing, per the card/remote-only shape.
  • name, title, description, repository are kept identical to the Registry document so the card and registry entry describe the same server.
  • version mirrors the runtime serverInfo.version.
  • Icons are embedded as self-contained data: URIs (no external image dependency) and emitted in a fixed order so the body — and therefore the ETag — is deterministic.
  • For Proxima the single remote url becomes https://copilot-api.{tenant}.ghe.com/mcp/.
2. AI Catalog — application/ai-catalog+json (spec_version 1.0)

GET https://github.com/.well-known/ai-catalog.json

{
  "spec_version": "1.0",
  "entries": [
    {
      "identifier": "urn:air:github.github.io:github-mcp-server",
      "display_name": "GitHub MCP Server",
      "media_type": "application/mcp-server-card+json",
      "url": "https://api.githubcopilot.com/mcp/server-card",
      "description": "Connect AI assistants to GitHub - manage repos, issues, PRs, and workflows through natural language."
    }
  ]
}
  • identifier is the AIR URN derived deterministically from the canonical card name io.github.github/github-mcp-server → reverse namespace io.github.githubgithub.github.iourn:air:github.github.io:github-mcp-server.
  • url equals the Server Card URL above (the integration contract), and media_type advertises what the client will receive there.
3. MCP Catalog (transitional subset) — application/json (specVersion draft)

GET https://github.com/.well-known/mcp/catalog.json

{
  "specVersion": "draft",
  "entries": [
    {
      "identifier": "urn:air:github.github.io:github-mcp-server",
      "displayName": "GitHub MCP Server",
      "mediaType": "application/mcp-server-card+json",
      "url": "https://api.githubcopilot.com/mcp/server-card",
      "description": "Connect AI assistants to GitHub - manage repos, issues, PRs, and workflows through natural language."
    }
  ]
}
  • This is a structural subset of the AI Catalog entry (camelCase, displayName instead of display_name), served alongside the forward ai-catalog.json for present-day clients. The forward application/ai-catalog+json document is the primary; the MCP Catalog is transitional — relevant to the direction in #26.

Relation to open WG threads
  • #11 (slash path): the card is reachable at the slash form …/mcp/server-card.
  • #16 (reference implementation): complements the python-sdk reference; a go-sdk convenience helper ports the same build_server_card / mount_server_card API.
  • #33 (ETag SHOULD): implemented on all three endpoints (strong ETag, weak If-None-Match comparison, 304).
  • #14 (optional displayName): entries currently set display_name/displayName; happy to drop to track the AI Catalog upstream decision.

Happy to expose a live endpoint or share the full (un-elided) bodies if useful for conformance testing.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the three described discovery endpoints and comparing their live wire formats, routes, headers, caching, and host behavior with the referenced SEP-2127 and AI Catalog expectations. The issue names no source files or tests, so completion is a WG sanity check or conformance finding rather than a defined code change.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, python, typescript
Domain
api, documentation
Issue type
Documentation
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.