← Guides

Connect a custom MCP server to Claude Desktop (step by step)

Claude Desktop supports both local STDIO servers and remote servers over Streamable HTTP. Remote is the version that survives a laptop change — here is the exact setup, including what the OAuth consent screen is doing.

Updated July 2026

Local vs. remote — pick remote unless you have a reason

Most MCP tutorials wire up a local STDIO server: Claude Desktop spawns a process on your machine and talks to it over stdin/stdout. That works, but it is per-machine — every teammate repeats the setup, secrets live in local config files, and nothing works from a second device. A remote server over Streamable HTTP is one URL that every installation shares, with auth handled by OAuth instead of plaintext keys in a JSON file.

the difference in config terms
# Local (STDIO) — runs on your machine, per-machine setup
"command": "npx", "args": ["-y", "@your/mcp-server"]

# Remote (Streamable HTTP) — hosted, one URL for every machine
"url": "https://my-tools-a1.mcp.buildmymcpserver.com/mcp"

Step 1 — get a server URL

You need a live MCP endpoint. If you already run one, use its URL. If not, you can generate one from a prompt or fork a working one from the template gallery — either way you end up with an OAuth-protected URL like https://my-tools-a1.mcp.buildmymcpserver.com/mcp.

Step 2 — add the server to Claude Desktop

  1. Open Claude Desktop settings and go to the connectors/MCP section (on recent versions: Settings → Connectors → Add custom connector), or edit claude_desktop_config.json directly.
  2. Add the server entry:
claude_desktop_config.json
{
  "mcpServers": {
    "my-tools": {
      "url": "https://my-tools-a1.mcp.buildmymcpserver.com/mcp",
      "auth": "oauth2"
    }
  }
}
  1. Restart Claude Desktop. Config is read at startup, not live.
Claude Desktop's settings UI changes between releases; the JSON config path is the stable fallback. On macOS it lives at ~/Library/Application Support/Claude/claude_desktop_config.json, on Windows at %APPDATA%\Claude\claude_desktop_config.json.

Step 3 — the OAuth flow on first use

The first time Claude touches the server it will receive a 401 — that is correct behavior, not an error. The client then discovers the authorization server, registers itself via Dynamic Client Registration, and opens a browser window for consent. You approve once; the client stores the token and refreshes it silently afterwards.

Under the hood this is the OAuth 2.1 handshake the MCP spec requires for remote servers: PKCE so the code exchange cannot be intercepted, and Resource Indicators (RFC 8707) so a token issued for this server cannot be replayed against another. Details in the OAuth documentation.

Step 4 — verify the tools are there

  • Open a new conversation and check the tools/connectors icon — your server should be listed with its tools.
  • Ask Claude directly: “Use the search_pages tool to find X.” Naming the tool forces Claude to attempt the call instead of answering from memory.
  • Watch your server's dashboard logs — you should see the tool call arrive with latency and status.

Troubleshooting

SymptomLikely causeFix
Server never appears in the clientConfig JSON is invalid, or Claude was not restartedValidate the JSON (trailing commas are the classic), restart Claude Desktop fully (quit, not close window).
Endless 401 loop, consent screen never opensURL points at the server root instead of the /mcp endpointUse the full endpoint URL ending in /mcp, exactly as the install snippet shows.
Consent worked, tools still missingServer is deployed but tool listing failed on connectCheck the server's live logs for an initialize/list_tools error; redeploy if the container restarted with a bad secret.
Tool listed, every call errorsUpstream credential (e.g. your API key) is wrong or expiredUpdate the secret in the dashboard — secrets are injected at runtime, so a redeploy picks up the new value. They are never shown back, so re-enter rather than inspect.
Worked yesterday, 401 todayToken expired and silent refresh failedRemove and re-add the connector to force a fresh OAuth flow.

One server, every client

The same URL works in Cursor, VS Code Copilot, Continue.dev and ChatGPT custom connectors — the point of hosting a remote MCP server is that the client config is the only per-client step left. If you hit a case this guide does not cover, the docs FAQ collects the rarer ones.

Skip the boilerplate — describe your tool, get a hosted MCP server.

BuildMyMCPServer generates the TypeScript server, wraps it in OAuth 2.1 and deploys it to a public Streamable HTTP URL for Claude, Cursor and ChatGPT. Free tier, source export, no lock-in.

Start building →