Claude Code MCP server setup, step by step
T. Krause ·
To set up a remote MCP server in Claude Code, run claude mcp add --transport http <name> <url> in your terminal. If the server wants a key, add --header "x-api-key: <key>" after the URL. Check the result with claude mcp list, or with /mcp inside a Claude Code session. A server that signs in with OAuth needs no header: add the URL, run /mcp and finish the sign-in in your browser.
The rest of this guide covers each of those steps with a real server URL. It also shows how the three scopes decide who else gets the server, and how to share it with a team without committing the key. The examples use a Prompt TM server, which gives the agent GitHub tools, but the commands are the same for any remote MCP server that speaks streamable HTTP.
What you need
- Claude Code installed, so the
claudecommand works in your terminal. - The URL of a remote MCP server. On Prompt TM it looks like
https://www.prompt-tm.com/mcp/mcp_...and you copy it from MCP servers in the dashboard. The quickstart creates one with a GitHub account connected. - A key, if the server uses keys. Prompt TM keys start with
ptm_.
Add the server with a key
export PROMPT_TM_KEY=ptm_...
claude mcp add --transport http github \
"https://www.prompt-tm.com/mcp/mcp_...?user_id=me" \
--header "x-api-key: $PROMPT_TM_KEY"
Each part does one job:
--transport httpselects streamable HTTP, the transport for remote servers.githubis the name you give the server. You see it in/mcp, and you use it to remove or inspect the server later.- The URL goes in quotes. zsh treats
?as a wildcard, so an unquoted URL with?user_id=fails withzsh: no matches foundbefore Claude Code even runs. user_id=metells Prompt TM whose connected accounts to use. The agent acts as that user, so a teammate with a different id gets their own GitHub account.--headergoes after the URL. It accepts several values, so if you put it in front of the name, the CLI reads the name as a second header and stops witherror: missing required argument 'name'.
Your shell expands $PROMPT_TM_KEY before Claude Code sees it. The key itself ends up in ~/.claude.json, which is fine for a server only you use. For a shared config, see the project scope below.
Check that it connected
claude mcp list
claude mcp get github
claude mcp get prints the scope, the URL, the headers and a status. Inside a session, /mcp shows the same servers with their connection status. Then ask Claude something the tools can answer, for example "List my GitHub repositories updated this week." On Prompt TM, the call also appears under Logs in the dashboard.
Pick a scope
--scope decides where Claude Code stores the server and who gets it. Per the Claude Code MCP documentation:
| Scope | Available in | Shared | Stored in |
|---|---|---|---|
local (default) | The current project, for you | No | ~/.claude.json |
project | The current project, for everyone | Yes, through version control | .mcp.json in the project root |
user | All your projects | No | ~/.claude.json |
Use --scope user for a server you want in every repository, such as one with your own GitHub account. Use --scope project when the whole team should get the same tools in one repository.
Share it in .mcp.json without committing the key
Project scope writes the server to .mcp.json, and that file goes into git. Keep the key out of it with an environment variable reference. Use single quotes, so your shell passes ${PROMPT_TM_KEY} through unexpanded:
claude mcp add --transport http github \
"https://www.prompt-tm.com/mcp/mcp_..." \
--scope project \
--header 'x-api-key: ${PROMPT_TM_KEY}'
The file then holds the reference, and Claude Code fills it in from each person's environment when it connects:
{
"mcpServers": {
"github": {
"type": "http",
"url": "https://www.prompt-tm.com/mcp/mcp_...",
"headers": {
"x-api-key": "${PROMPT_TM_KEY}"
}
}
}
}
Claude Code expands ${VAR} and ${VAR:-default} in the url and headers of .mcp.json. If you edit the file by hand, keep "type": "http". Claude Code reads an entry with a url but no type as a local stdio server, and that entry fails. Claude Code also asks each person to approve a project-scoped server the first time it starts in that repository.
On Prompt TM, give each teammate a scoped key instead of the project key. On the MCP server's page, enter the teammate's user id, tick Put a scoped key in the URL and click Generate URL. The URL that comes back carries the key as key=. Copy that value into the teammate's PROMPT_TM_KEY. The key opens only that server and only for the user id you entered, so the URL in .mcp.json needs no user_id. Leave the user id empty and the key isn't tied to one user. The project key from the first example is fine on your own machine, but it also opens the project's whole REST API, so don't hand it to teammates.
Or sign in with OAuth instead of a key
Claude Code supports OAuth for remote servers. Add the server without a header:
claude mcp add --transport http github "https://www.prompt-tm.com/mcp/mcp_..."
claude mcp get github now reports Needs authentication. Run /mcp in a session and pick the server, or run claude mcp login github from your shell. Your browser opens the server's sign-in page. On Prompt TM that is a consent page where you sign in, choose the MCP server and the user id the agent acts as, and allow access. How the token exchange works behind that page is in MCP OAuth for AI agents.
Prompt TM lists each grant on the MCP server's page in the dashboard, where you can revoke it. On your side, claude mcp logout github clears the stored credentials. The Claude Code docs note that claude mcp remove deletes the stored tokens without revoking them at the authorization server, so run logout first if you want them revoked.
Change or remove a server
claude mcp remove github
If a server exists in more than one scope, add -s local, -s project or -s user. To change the key or the URL, remove the server and add it again with the new values.
When it doesn't connect
zsh: no matches found. The URL wasn't quoted. Put it in double quotes.
error: missing required argument 'name'. --header came before the name. Move it after the URL.
401 with "Missing or invalid credentials". The server got no key, or a revoked one. Check the header with claude mcp get github. With ${PROMPT_TM_KEY} in .mcp.json, check that the variable is set in the shell that started Claude Code.
403 with "This key is scoped to another user id". The URL asks for a user_id that the scoped key doesn't cover. Drop user_id from the URL, or use that user's key.
403 with "This key belongs to another MCP server". A scoped key opens one server only. Generate a key on the server you're connecting to.
The tools load but a call fails for lack of an account. The user id has no connected account for that app yet. Connect one in the dashboard or send the user a connect link, as in how to give an AI agent access to GitHub.
The MCP client docs have the same server set up for Claude Desktop, Cursor, VS Code and the agent SDKs.