from line 1
1# Testing your connector
1# Test your connector
22
3> Test your MCP server against Claude before submitting to the directory
3> Test your MCP server against Claude as a custom connector before you submit it to the directory, including a local server exposed through a tunnel.
44
5Test your server against the real Claude client before submitting. There is no separate staging environment—you test in production using a custom connector.
5You test an MCP server against the real Claude client by adding it to Claude as a custom connector. There is no separate staging environment, so you test in production. Custom connectors use the exact same runtime as directory connectors, and what works as a custom connector will work after publication.
66
7## Test as a custom connector
7This page is for developers with a running server, whether it's deployed or still on your machine. It covers adding the server to Claude, validating it with MCP Inspector, detecting Claude as the client, and preparing test credentials for directory review. If a connection fails while you test, [Troubleshoot your connector](/docs/connectors/building/troubleshooting) walks through each error message.
88
9Any Claude account (Free, Pro, Max, Team, or Enterprise) can add a custom connector. Go to **Customize > Connectors**, select **Add custom connector**, and enter your server's URL. Custom connectors use the exact same runtime as directory connectors, so what works here will work after publication.
9## Test in Claude as a custom connector
1010
11## Test a local server
11To test your server the way users will reach it, add it to your own Claude account as a custom connector by its URL. Any Claude account can do this, on Free, Pro, Max, Team, or Enterprise; [Add a connector that isn't in the directory](/docs/connectors/custom/add-unlisted#add-a-connector-by-url) has the steps for each plan, starting from [**Customize > Connectors**](https://claude.ai/customize/connectors).
1212
13To test a server running on your machine, expose it as a public URL with a tunnel such as [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) or `ngrok`, then add the tunnel URL as a custom connector. This is the recommended pattern for iterating on MCP Apps as well.
13Once the connector is added, check these:
1414
15* **The connection**: the connector shows **Connected** under **Your connectors**. If it shows **Connect** or **Reconnect** instead, sign-in didn't finish, and [Debug connection failures](#debug-connection-failures) covers the usual causes
16* **Your tools**: open the connector's page and look under **Tool permissions**. Every tool your server advertises should be listed with the name and description you gave it, because those are what Claude reads when it decides to call a tool
17* **A real call**: in a chat, turn the connector on from **+ > Connectors**, ask for something that needs one of your tools, and approve the call when Claude asks. Confirm on your server that the request arrived with the arguments you expected, and in Claude that the result reads well. [Use the connector in a conversation](/docs/connectors/getting-started#use-the-connector-in-a-conversation) shows what the user sees at each point
18
19### Test a local server
20
21Claude reaches your server from Anthropic's infrastructure, so a server running on your machine needs a public URL. Expose it with a tunnel such as [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) or `ngrok`, then add the tunnel URL as a custom connector. This is the recommended pattern for iterating on MCP Apps as well.
22
23If your server uses the TypeScript SDK's `createMcpExpressApp()`, as the [quickstart server](/docs/connectors/building/quickstart) does, its DNS rebinding protection accepts only `localhost`, `127.0.0.1`, and `[::1]` in the `Host` header. A request that arrives with the tunnel's hostname in that header gets `403` with `Invalid Host: <hostname>`, and the connection fails. While you test through the tunnel, pass the tunnel's hostname in `allowedHosts`, replacing `abc123.example.com` with your tunnel's hostname:
24
25```js theme={null}
26const app = createMcpExpressApp({ allowedHosts: ['localhost', '127.0.0.1', 'abc123.example.com'] });
27```
28
1529<Warning>
1630 A tunnel exposes your local server to the public internet. Keep authentication enabled on your server while tunneling, and shut the tunnel down when you're done testing.
1731</Warning>
1832
19## Validate with MCP Inspector
33### Validate with MCP Inspector
2034
21Use the [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) to verify protocol compliance, exercise your auth flow, and inspect tool schemas before connecting to Claude.
35Before connecting to Claude, use the [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) to verify protocol compliance, exercise your auth flow, and inspect tool schemas. With your server running, run the Inspector's command-line mode from a terminal against your server's URL, replacing `http://localhost:3000/mcp` with your own:
2236
37```bash theme={null}
38npx @modelcontextprotocol/inspector --cli http://localhost:3000/mcp --transport http --method tools/list
39```
40
41The command lists the tools your server advertises. Change `--method` to `tools/call` with `--tool-name` and `--tool-arg` options to call one.
42
2343## Detect Claude as the client
2444
25Claude identifies itself in the MCP `initialize` handshake via `clientInfo`, but the exact value depends on the surface and the request path. You may see `"name": "claude-ai"`, `"name": "Anthropic"` (sometimes with a service suffix), or `"name": "claude-code"`:
45Claude identifies itself in the MCP `initialize` handshake through `clientInfo`, but the exact value depends on the surface and the request path. You may see `"name": "claude-ai"`, `"name": "Anthropic"`, sometimes with a service suffix, or `"name": "claude-code"`. One handshake looks like this:
2646
2747```json theme={null}
2848{ "clientInfo": { "name": "Anthropic", "version": "1.0.0" } }
2949```
3050
31Don't gate behavior on an exact `name` or `version` string — both vary across surfaces, request paths, and releases. Use `clientInfo` for telemetry and coarse feature detection only, and remember it's unauthenticated: any client can claim any name, so it must never feed an authorization decision.
51Don't gate behavior on an exact `name` or `version` string, because both vary across surfaces, request paths, and releases. Use `clientInfo` for telemetry and coarse feature detection only. It's also unauthenticated: any client can claim any name, so it must never feed an authorization decision.
3252
3353## Prepare test credentials for review
3454
35Directory submission requires test credentials. Provide a **fully populated account**—not an empty shell—so reviewers can exercise real functionality (list real records, search real data, exercise write tools on real resources). Include step-by-step setup instructions for someone unfamiliar with your service.
55Directory submission requires test credentials. Provide a fully populated account rather than an empty shell, so reviewers can exercise real functionality: list real records, search real data, and exercise write tools on real resources. Include step-by-step setup instructions for someone unfamiliar with your service.
3656
37## Debugging
57## Debug connection failures
3858
39Partner-visible error logs are in development. In the meantime, use server-side logging on your end and the MCP Inspector to diagnose connection failures. Common causes of `initialize` timeouts include slow OAuth endpoints (keep discovery, registration, and token responses under ten seconds; see [endpoint latency](/docs/connectors/building/authentication#endpoint-latency)), overly strict `Origin`-header validation rejecting Anthropic's requests, and firewalls dropping Anthropic's egress traffic.
59Use server-side logging on your end and the MCP Inspector to diagnose connection failures. An `initialize` timeout commonly has one of these causes:
4060
41If your infrastructure logs show `403 Forbidden` responses your application didn't generate, your CDN or WAF is likely blocking Anthropic's traffic. See [firewall or WAF blocks Anthropic's traffic](/docs/connectors/building/troubleshooting#2-firewall-or-waf-blocks-anthropic%E2%80%99s-traffic) for the fix.
61* **Slow OAuth endpoints**: keep discovery, registration, and token responses under ten seconds, as described in [endpoint latency](/docs/connectors/building/authentication#endpoint-latency)
62* **Strict `Origin`-header validation**: an overly strict check rejects Anthropic's requests
63* **Firewalls**: a firewall drops Anthropic's egress traffic
4264
43For a structured walkthrough of "Couldn't reach the MCP server" and "Authorization failed" errors, including DNS resolution checks, OAuth discovery diagnostics, and how to find the `ofid_` reference ID to include in a support request, see [troubleshooting connectors](/docs/connectors/building/troubleshooting).
65If your infrastructure logs show `403 Forbidden` responses your application didn't generate, your CDN or WAF is likely blocking Anthropic's traffic. See [firewall or WAF blocks traffic from Anthropic](/docs/connectors/building/troubleshooting#firewall-or-waf-blocks-traffic-from-anthropic) for the fix.
66
67For a structured walkthrough of the "Couldn't reach the MCP server" and "Authorization failed" errors, see [Troubleshoot your connector](/docs/connectors/building/troubleshooting). It includes DNS resolution checks, OAuth discovery diagnostics, and how to find the `ofid_` reference ID to include in a support request.
68
69## Next steps
70
71* [Troubleshoot your connector](/docs/connectors/building/troubleshooting): diagnose each error message Claude shows for a failed connection or tool call
72* [Plugin structure and testing](/docs/plugins/build): bundle your tested connector with skills so people install both together
73* [Publish to the directory](/docs/directory/publish): submit your connector for review and listing
4474
No line in this hunk matches that.