Worked MCP discovery sample
An MCP client (Claude, Cursor, a registry crawler) reads this manifest before it ever connects: it learns the hosted server’s transport URL, the MCP protocol revision it speaks, and exactly how to authenticate — then hands the user a one-click “add server” instead of asking for a URL.GET /api/v1/public/mcp/.well-known/mcp.json — public, no API key required.server.json shape, so aggregators can ingest it without a bespoke parser. Each field tells the client something actionable:
$schema/name/version— the registry identity of this server.nameis theio.devotel/orbit-cpaasnamespace the entry is published under;versiontracks the hosted tool catalog and bumps when the catalog changes shape.protocolVersion— the MCP protocol revision the server speaks (2025-06-18). A client checks this before negotiating a session, so an outdated client warns instead of failing mid-handshake.remotes— the transport the client connects to. Single entry today:streamable-httpatPOST /api/v1/mcp— no stdio subprocess, no SSE fallback to configure.documentation— the setup walkthrough (Claude and Cursor config blocks) at Connect Claude or Cursor.auth— driven off your ordinary Orbit API key, passed as eitherAuthorization: Bearer <key>orX-API-Key: <key>. Tool calls inherit the key’s scopes and tenant, so a read-scoped key gets read-scoped tools and nothing else.
Cache-Control: public, max-age=300, stale-while-revalidate=600, so aggregators can cache it at the edge and re-fetch at most every five minutes. Content is identical for every caller — the manifest describes the server, never your tenant; no tenant-specific data is exposed on this unsigned path.
Deciding errors
Unauthenticated discovery failures are rare. When a request does fail, the branch is one of these:
The retry-vs-terminal decision table lives in the error-handling guide.