# A pre-flight checklist for shipping a Claude connector

> Source: <https://dev.to/akashdas/a-pre-flight-checklist-for-shipping-a-claude-connector-56oc>
> Published: 2026-08-22 18:46:58+00:00

Writing an MCP server is the easy part. Shipping one as a Claude connector means passing four gates that have nothing to do with your business logic: Anthropic's network can reach you, Claude can get an OAuth client identity, a human reviewer approves your tool design, and your server does not waste the user's context window.

Here is the checklist I wish I had had, in the order the failures actually happen.

Claude connects from Anthropic's servers, not from your laptop. So the tests you run at your desk prove almost nothing. Run these from a network that is not yours:

```
# Every returned address must be globally routable.
# Any 10.x, 172.16–31.x, 192.168.x, 100.64.x, loopback or link-local
# address in the answer kills the connection before an HTTP request is sent.
dig +short your-server.example.com

# Connectors are IPv4-only. Empty first line + populated second line = the bug.
dig +short A    your-server.example.com
dig +short AAAA your-server.example.com

# A 301/302/307/308 to a different host strips the Authorization header
# (RFC 9110 §15.4). The target answers 401 and Claude reports an auth failure.
curl -sSI https://your-server.example.com/mcp | grep -i '^location:'
```

**Checks:**

If your access log is empty while Claude says *Couldn't reach the MCP server*, one of those three is why. Full teardown of all four documented causes: [Claude cannot reach your MCP server, but curl can](https://www.nihardaily.com/posts/claude-cannot-reach-your-mcp-server-but-curl-can).

For local development, tunnel instead of fighting this: `cloudflared tunnel --url http://localhost:3000`

or `ngrok http 3000`

.

```
Incompatible auth server: does not support dynamic client registration
```

The obvious fix is the wrong one for most public connectors. Dynamic Client Registration mints a fresh OAuth client on **every new connection** — that is a row per connection, not per customer, so a busy connector slowly fills your identity provider with junk clients.

Claude accepts three ways of getting an identity:

| Method | What you host | Good fit for |
|---|---|---|
`oauth_dcr` (RFC 7591) |
a `POST /register` endpoint |
internal servers, few users |
`oauth_cimd` |
a static JSON document at an HTTPS URL | public connectors, high traffic |
`oauth_anthropic_creds` |
nothing new — you mail Anthropic a client ID and secret | teams who cannot change their IdP |

The CIMD trap is worth memorising, because it fails silently. Claude picks CIMD only when your metadata says **both** of these:

```
{
  "client_id_metadata_document_supported": true,
  "token_endpoint_auth_methods_supported": ["none"]
}
```

Miss the second and Claude falls back to dynamic registration, and then fails with the error above even though your CIMD is fine.

**Checks:**

`registration_endpoint`

is `null`

— `null`

fails schema validation rather than being ignoredComparison of the three methods and when each one is right: [Claude cannot register with your OAuth server. Now what?](https://www.nihardaily.com/posts/claude-cannot-register-with-your-oauth-server-now-what).

This one has an automatic-fail that a lot of servers ship on day one:

```
// Rejected. One tool, safe and unsafe methods in the same surface.
{
  "name": "api_request",
  "inputSchema": {
    "properties": { "method": { "enum": ["GET", "POST", "DELETE"] } }
  }
}
```

Read and write must be separate tools, and writes should be split further by action where you can — create, update, delete. No description text saves the combined version.

**Checks:**

`readOnlyHint: true`

or `destructiveHint: true`

Those hints are not paperwork. They drive auto-permissions, so read-only tools can run without prompting each time. Skip them and your connector is both non-compliant and slower to use. The rest of the rejection triggers: [What gets a Claude connector rejected from the directory](https://www.nihardaily.com/posts/what-gets-a-claude-connector-rejected-from-the-directory).

Stop splitting servers to save context. Tool search ships on by default in Claude Code: only tool names and server instructions load at session start, and full schemas arrive on demand. Anthropic's reference says adding more servers has minimal impact on the window, with no fixed per-server tool cap.

What still costs you:

`MAX_MCP_OUTPUT_TOKENS`

)`ANTHROPIC_BASE_URL`

on a non-first-party host — so a team gateway silently restores the old up-front costYou can also opt one server out on purpose:

```
{
  "mcpServers": {
    "core-tools": {
      "type": "http",
      "url": "https://mcp.example.com/mcp",
      "alwaysLoad": true
    }
  }
}
```

**Checks:**

The full table of conditions that keep tools loading up front: [Your MCP connector spends context before you type](https://www.nihardaily.com/posts/your-mcp-connector-spends-context-before-you-type).

MCP Apps is the first official MCP extension: your server returns interactive HTML, the client renders it in a sandboxed iframe, and the page talks back over JSON-RPC on `postMessage`

. Claude, ChatGPT, VS Code and Goose all render it, so it is portable rather than a single-vendor bet.

Worth it when the result is genuinely visual — a brushable scatter chart, a map, compiled shader output. Not worth it when your tool returns three fields. Directory submission for an MCP App also wants 3 to 5 PNG screenshots at 1000px or wider, and any link destination missing from your allowed link URIs makes the user confirm every click.

Run an example server locally first; it takes about five minutes:

```
{
  "mcpServers": {
    "qr": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/qr-server", "--stdio"]
    }
  }
}
```

The build-vs-skip trade-off in full: [Should your Claude connector draw its own UI?](https://www.nihardaily.com/posts/should-your-claude-connector-draw-its-own-ui).

Four of the five ways a connector fails are environmental, not logical — network reachability, client identity, review criteria, and client-side budget. Your code being correct is exactly what makes them hard to find. Run the `dig`

checks from outside your network, choose CIMD if you expect volume, split read from write before you submit, and stop hand-optimising a context cost the client already handles.

What has bitten you shipping an MCP server? The redirect-strips-the-token one cost me the most time.
