Claude Code MCP Servers: Setup, Config & Cron-Safe Template
Originally published at Unattended . Claude Code MCP servers are external programs or hosted endpoints that give Claude Code extra tools, such as a browser, GitHub, Sentry or a database. You add one with claude mcp add , check it with claude mcp list and remove it with claude mcp remove . In the wo

Posted on Oct 29 • Originally published at en.aobaworks.com
Claude Code MCP servers are external programs or hosted endpoints that give Claude Code extra tools, such as a browser, GitHub, Sentry or a database. You add one with claude mcp add, check it with claude mcp list and remove it with claude mcp remove <name>. In the words of the official MCP docs, "MCP servers give Claude Code access to your tools, databases, and APIs." Most guides stop at the interactive setup. This one also covers what changes when nobody is at the keyboard: which servers a cron run loads, how to scope their permissions, which timeouts apply, and what happens when a server goes down partway through a job.
Choose the scope and transport that fit how you work, then open the matching page. Each row gives a one-line reason.
For a cron job, keep the automation's server list out of your personal config. The rest of this guide explains why.
A Claude Code MCP server is a process or hosted URL that exposes extra tools to Claude Code over the Model Context Protocol. Claude Code calls those tools like its built-in ones. The quickstart describes it as letting Claude Code use tools "beyond its built-in set, such as searching an issue tracker, querying a database, or controlling a web browser."
Each tool appears to Claude under a prefixed name, mcp__<server>__<tool>. That name matters later, because permission rules match against it ( permissions docs ).
So, can Claude Code use MCP servers? Yes, in every surface. The CLI, the desktop app, VS Code and cloud sessions can all connect. Connectors you add at claude.ai also load in the CLI when you sign in with that account ( quickstart: Connect from other surfaces ).
For most servers, installing is the same step as registering. You run claude mcp add, and either Claude Code fetches the package through npx the first time it starts the server, or you point it at a hosted URL.
Then run the add command in your shell, not inside a claude session:
# Remote example from the docs: no auth needed claude mcp add --transport http claude-code-docs https://code.claude.com/docs/mcp # Local example from the docs: Playwright browser server claude mcp add playwright -- npx -y @playwright/mcp@latest Enter fullscreen mode Exit fullscreen mode Common install mistakes and fixes:
If you already set up servers in the Claude Desktop chat app, claude mcp add-from-claude-desktop copies them into the CLI on macOS or WSL ( quickstart ).
Claude Code stores MCP server configuration in ~/.claude.json or a project's.mcp.json, depending on scope. ~/.claude.json holds the local and user scopes, and.mcp.json in the project root holds the project scope. The file depends on the --scope you pick ( quickstart ).
On Windows, ~/.claude.json resolves to %USERPROFILE%\.claude.json. If CLAUDE_CONFIG_DIR is set, Claude Code reads the file from that directory instead ( quickstart ). When one name exists in several scopes, precedence runs local, then project, then user, then plugins, then claude.ai connectors ( MCP reference ).
Here is a hand-written.mcp.json example. The first two entries come from the docs. The ${...} variables and the timeout field are documented options:
{ "mcpServers": { "claude-code-docs": { "type": "http", "url": "https://code.claude.com/docs/mcp" }, "playwright": { "type": "stdio", "command": "npx", "args": [ "-y", "@playwright/mcp@latest" ] }, "internal-api": { "type": "http", "url": "${API_BASE_URL:-https://api.example.com}/mcp", "headers": { "Authorization": "Bearer ${API_KEY}" }, "timeout": 600000 } } } Enter fullscreen mode Exit fullscreen mode The details that matter, all from the MCP reference:
Pitfall: editing the wrong file. Claude Code does not read ~/.claude/.mcp.json, ~/.claude/mcp.json, ~/.claude/config/mcp.json or %APPDATA%\Claude\mcp.json ( quickstart troubleshooting ). Edits to.mcp.json take effect only when a new session starts ( quickstart troubleshooting ). A malformed entry is skipped while the others still load, so run claude mcp list and look for the parse warning ( quickstart troubleshooting ).
You add a Claude Code MCP server with claude mcp add (or add-json ) and remove it with claude mcp remove <name>. Both commands print the file they modified ( quickstart ).
The -- separator is the most common mistake. Your own options ( --transport, --env, --scope ) go before it, and the docs say "Everything after -- is passed to the server untouched" ( MCP reference ). If claude mcp get <name> shows a different command from the one you typed, remove the server and add it again with -- in place.
claude mcp remove claude-code-docs # default scope claude mcp remove claude-code-docs --scope local # when it exists in several scopes Enter fullscreen mode Exit fullscreen mode If the name exists in more than one scope, remove reports exists in multiple scopes, and you choose one with --scope ( quickstart ). To pause a server without deleting it, toggle it off in the /mcp panel. Claude Code records that choice per project in a disabledMcpServers list in ~/.claude.json ( MCP reference ). You can't change a server's scope in place. Remove it and add it again at the new scope ( quickstart ).
Claude Code connects to local servers over stdio and to remote servers over HTTP. SSE still works but is deprecated, and WebSocket can only be configured through JSON ( MCP reference ). For unattended runs, the biggest difference between them is how each transport fails and recovers.
The idle timeout figures come from the environment variables reference ( CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT, v2.1.187 or later). The retry behavior comes from the MCP reference. Authentication errors are different: Claude Code stops retrying and waits for you to sign in again. A cron job can't do that, which is why OAuth servers fit unattended runs poorly unless their credentials stay valid.
Quick connectivity check. For an HTTP server, run curl -I <url>. A 404 or 405 still means the server is up, because many MCP endpoints answer only POST. A 401 or 403 means you need to authenticate. No response at all points to the URL or the network ( quickstart troubleshooting ).
You use a Claude Code MCP server by asking for the task in plain language. Claude picks the relevant tool on its own, and you approve the first call when prompted ( quickstart ).
Naming the server in your prompt isn't required. The docs do it in the walkthrough so the test definitely goes through the new server rather than a built-in tool such as web fetch.
Watch the output size. Claude Code shows a warning when an MCP tool returns more than 10,000 tokens and caps output at 25,000 tokens by default. MAX_MCP_OUTPUT_TOKENS changes the cap ( MCP reference ). Large database or log queries hit that cap quickly. For ways to trim them, see how to see token usage and reduce it.
Status meanings you'll see ( quickstart ):
For recurring solo-builder work, start with two or three servers that each cover a job you would otherwise script by hand. Each server you connect adds context cost and permission surface ( quickstart ).
Sources: the quickstart for docs, Playwright and Sentry, the MCP reference for GitHub, and the modelcontextprotocol/servers repo for the reference set.
Two things many "best MCP servers" lists get wrong as of October 2026. First, the official repo now maintains seven reference servers: Everything, Fetch, Filesystem, Git, Memory, Sequential Thinking and Time. Second, it archived thirteen others, including GitHub, PostgreSQL, Slack, Puppeteer and SQLite, in servers-archived ( servers repo ). If a tutorial tells you to install the old GitHub or Postgres package from that repo, look for the vendor's own server instead.
Find Claude Code MCP servers in the official MCP Registry, Anthropic's reviewed Anthropic Directory, or vendor GitHub repos. Vet each one before an automation depends on it.
The official repo says plainly that its servers are educational examples, "not as production-ready solutions" ( modelcontextprotocol/servers ). Anthropic's MCP page adds: "Verify you trust each server before connecting it." It also warns that servers which fetch external content carry prompt injection risk ( MCP reference ).
A short vetting checklist before a server goes into a scheduled job:
Also be careful with similar names: projects like steipete/claude-code-mcp run Claude Code itself as an MCP server for other agents ( GitHub ). That's the opposite direction from this guide.
Give each headless job its own server file, allowlist named MCP tools, set short timeouts, and check server status in the output. A claude -p run has nobody to answer prompts.
Without --bare, claude -p loads the MCP servers in the working directory's.mcp.json, and the headless docs note: "A -p session shows no workspace trust dialog and no per-server approval prompt." The approval that protects you interactively is skipped. Two flags close the gap:
From v2.1.302, a -p run starts in Manual mode when nothing else sets a mode. Any call that needs approval is denied unless an allow rule, a PermissionRequest hook or a permission prompt tool approves it ( headless docs ). Use allow rules to list exactly which MCP tools the job may call:
The rule format is described in the permissions docs. Prefer naming single tools for jobs that write anything. Also add --permission-prompts none (v2.1.259 or later). With it, Claude is told nobody can approve, so it stops retrying denied calls, and any MCP elicitation request that no hook answers is cancelled ( headless docs ). For a complete rule set, see the headless permissions template.
Sources: headless docs, env vars, MCP reference.
The last row matters most for cron. After 2 minutes, a long MCP call moves to the background. The headless docs say that when a -p run ends, for a call that automatic backgrounding moved, "the call's result is lost". Setting CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS=0 turns automatic backgrounding off ( env vars ). Also set CLAUDE_CODE_MCP_ALLOWLIST_ENV=1. Stdio servers then get only a safe baseline environment plus their configured env, instead of inheriting every secret in your shell ( env vars ).
The run does not crash on its own. An entry that fails validation is skipped and the run "continues and exits cleanly" ( headless docs ). A server that never connects means its tools are simply missing, so Claude may finish the task without them and still exit 0. Your script has to check for that. The system/init event in stream-json output lists mcp_servers (each with name and status ) and mcp_server_errors. A redirected stderr shows no warning, so read these fields instead. Exit code 143 means the process got SIGTERM ( headless docs ).
The following example wrapper adapts documented flags. Check the status strings your version emits before relying on the filter.
#!/usr/bin/env bash set -euo pipefail cd /srv/myproject export MCP_TIMEOUT = 15000 export CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT = 120000 export CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS = 0 export CLAUDE_CODE_MCP_ALLOWLIST_ENV = 1 timeout 20m claude -p "Summarize issues labeled bug opened in the last 24h" \ --mcp-config./automation.mcp.json --strict-mcp-config \ --allowedTools "mcp__github__list_issues,mcp__github__get_issue" \ --permission-prompts none \ --output-format stream-json --verbose > run.jsonl # Fail the job if any server is not connected (example filter) if jq -e 'select(.type=="system" and.subtype=="init") | (.mcp_server_errors // []) + [.mcp_servers[] | select(.status!="connected")] | length > 0' run.jsonl > /dev/null; then echo "MCP server missing; result not trusted" > &2; exit 2 fi Enter fullscreen mode Exit fullscreen mode Scheduling, retries and alerting belong in your cron layer. See the cron job setup guide and catching silent failures. For every -p flag and the auth trade-offs, see the headless mode guide.
If you'd rather not run servers yourself: use vendor-hosted remote servers from the Anthropic Directory, so the vendor handles uptime and updates. You still configure scopes and tokens. Claude Code itself requires a paid plan: Pro is $20/month billed monthly ($17/month on annual billing), and Max starts at $100/month (as of October 2026; check the official pricing page ). Pro suits one person running a few scheduled jobs. It's a poor fit if you need --bare everywhere, because bare mode needs an API key billed separately through the Claude Console ( headless docs ).
For HTTP servers, Claude Code retries up to 5 times with exponential backoff starting at 1 second. For stdio servers in claude -p, it retries on the next tool call ( MCP reference ). If the server stays down, that server's tools fail but the run can still exit 0. Check mcp_servers in the system/init event and treat a missing server as a failed job.
Yes. List as many as you need under mcpServers in one file. Each server's tool names and instructions load into the context window, though, so remove ones you don't use ( quickstart ). Tool search reduces that cost when you have many tools ( MCP reference ).
Local and user scopes live in ~/.claude.json on macOS and Linux, and in %USERPROFILE%\.claude.json on Windows. Project scope is.mcp.json in the repo root. Run claude mcp get <name> to see which scope holds a server ( quickstart ).
It's reasonably safe only when the job loads a fixed server list ( --strict-mcp-config or --bare ), allows named MCP tools only, and uses narrowly scoped tokens. Without those, a -p run connects whatever.mcp.json the directory contains, with no approval prompt ( headless docs ). Servers that read web pages or issues can also carry prompt injection.
This article was created with the help of AI. Sources are linked inline; check the official documentation for the latest details.