Connect Claude
An ordered procedure against a real deployment.
No public endpoint exists, and this has never been run end to end
Nothing is deployed. There is no public MCP host you can point a client at today, so you cannot follow this procedure to a working connection right now.
Every fact below is taken from source: the transport, the route, the discovery documents and the authentication configuration. None of it has been proved by connecting a real client to a real public host, because there is no such host. Treat the steps as correct in their detail and unproven as a whole.
The host below is written as <MCP-HOST-PLACEHOLDER> everywhere it appears. It
is not a real address. When a deployment exists, its operator replaces that one
value.
What you are connecting to
| Path | /mcp |
| Methods | GET, POST, DELETE |
| Transport | Streamable HTTP |
| Sessions | Stateful, so a session is established and reused |
| Credential | An OAuth 2.0 bearer token, in the Authorization header |
Source: services/runtime/src/runtime/mcp/asgi.py:38-39 for the path and
methods, services/runtime/src/runtime/mcp/asgi.py:74-87 for the transport, the
session manager and the authentication chain.
The procedure
1. Get the server URL from the operator
It is the deployment's public base URL with /mcp on the end:
https://<MCP-HOST-PLACEHOLDER>/mcpThat base is whatever the operator set as MCP_PUBLIC_BASE_URL. The discovery
documents publish the same value, built from configuration rather than from the
request, so the two cannot disagree.
Source: services/runtime/src/runtime/mcp/well_known.py:35-40 and
services/runtime/src/runtime/config.py:553-559.
2. Add the server to your client
In Claude, add a remote MCP server and give it that URL. Any client that speaks Streamable HTTP and OAuth works the same way. The steps below are what a spec-compliant client does for you; they are written out so you can tell where it stopped if it fails.
3. The client discovers where to authenticate
An unauthenticated request to /mcp is answered with a 401 whose
WWW-Authenticate header names the resource metadata document. The client
fetches it:
https://<MCP-HOST-PLACEHOLDER>/.well-known/oauth-protected-resource/mcpThe same document is also published at the bare path
/.well-known/oauth-protected-resource, for clients that have not adopted the
resource-scoped one. Both are public, which they have to be: a client has to
read them before it holds any credential.
Source: services/runtime/src/runtime/mcp/well_known.py:1-21 and
services/runtime/src/runtime/mcp/well_known.py:62-68.
4. The client reads which scope to ask for
The metadata document carries scopes_supported, holding the one scope this
server requires. That field is the only signal a client has to request the
scope on its first attempt, instead of discovering it from a refusal.
Source: services/runtime/src/runtime/mcp/well_known.py:43-56.
5. The client registers itself and authenticates
MCP clients register themselves with the authorization server through Dynamic Client Registration, then run an authorization code flow with PKCE. You sign in as yourself in a browser window. The client must include the scope from step 4 in its authorization request, otherwise the token it gets back will be refused at every call.
Source: services/runtime/src/runtime/mcp/verifier.py:13-30.
6. Confirm with a tool call
Ask the client to list tickets. That drives list_tickets, which needs only the
viewer role and no arguments at all.
If you belong to more than one workspace, the first call is refused and asks you
to name one. Ask again naming the workspace, which the client passes as
workspace_id.
Source: services/runtime/src/runtime/mcp/tools.py:423-455 and
services/runtime/src/runtime/mcp/tools.py:249-285.
If a step fails
Each of the common failures has a distinct symptom. Troubleshooting lists them with what to do about each.