Rubric
Contents — domains, guide and mocks

MCP servers in Claude Code

CCAR-F 2.410 min read · checked 21 September 2026

Task statementIntegrate MCP servers into Claude Code and agent workflows

Where a Claude Code MCP server can live

Highest precedence first

  1. Local (the default)~/.claude.json, this project; only you
  2. Project.mcp.json in the repo; the whole team
  3. User~/.claude.json top level; you, all projects
  4. Plugin-providedservers bundled with installed plugins
  5. Claude.ai connectorsloaded when signed in to that account
When the same server name is defined in more than one place, the higher layer wins. Only the project layer travels with the repository.

Choosing a scope

claude mcp add registers a server, and its --scope flag decides where the definition is written. Without a flag the server goes to local scope: private to you and active only in the current project. User scope is still private but follows you into every project. Project scope writes to .mcp.json at the repository root, which you commit, so everyone who clones the project gets the same servers.

ScopeStored inWho gets itGood for
local~/.claude.json, under this projectOnly you, only hereTrying a server out; a personal key for one repo
project.mcp.json at the project rootEveryone who clones the repoTools the whole team relies on
user~/.claude.json, top-level mcpServersOnly you, every projectPersonal utilities you use everywhere

Which scope does this server need?

Who should have this server?
  • The whole team, this repo
    --scope projectcommit .mcp.json
  • Just me, every project
    --scope userpersonal utilities
  • Just me, trying it here
    default localno flag needed
Adding servers at each scopebash
# Team-shared: writes .mcp.json in the project root
claude mcp add --scope project --transport http docs https://code.claude.com/docs/mcp

# Personal, every project: writes ~/.claude.json (top level)
claude mcp add --scope user --transport http sentry https://mcp.sentry.dev/mcp

# Local stdio server: everything after -- is the command to run
claude mcp add playwright -- npx -y @playwright/mcp@latest

claude mcp list          # status of every configured server

Project scope has a safety step. The first time Claude Code sees a server from .mcp.json, it asks you to approve it, so a repository you clone cannot launch processes on your machine without consent. If you rejected one by mistake, claude mcp reset-project-choices clears those decisions. Non-interactive runs such as claude -p and the Agent SDK load project servers without the prompt, which is one reason to review .mcp.json changes like code.

Sharing a server without sharing the secret

A shared .mcp.json must never contain a token. Claude Code expands environment variables in it: ${VAR} takes the value from each person’s environment, and ${VAR:-default} supplies a fallback. Expansion works in command, args, env, url and headers. Each teammate sets their own token locally; the committed file holds only the placeholder.

Committing configuration, not credentials

Token in the repo

{
 "mcpServers": {
  "jira": {
   "type": "http",
   "url": "https://mcp.example.com",
   "headers": {
    "Authorization":
      "Bearer 7f3Kx9…real token"
   }
  }
 }
}

Placeholder per person

{
 "mcpServers": {
  "jira": {
   "type": "http",
   "url": "https://mcp.example.com",
   "headers": {
    "Authorization":
      "Bearer ${JIRA_TOKEN}"
   }
  }
 }
}
Both files configure the same server. Only the right-hand one is safe to commit, and it lets every developer use their own token.

Two details prevent surprises. If a variable is unset and has no default, Claude Code warns in claude mcp list and /mcp and leaves the literal ${VAR} in place, so the server fails to authenticate rather than silently using nothing. And for remote servers, Claude Code deliberately reads certain credential variables, such as ANTHROPIC_API_KEY, as empty inside url and headers, so a shared file cannot be used to send your Anthropic key to a third-party server.

The same servers in the Agent SDK

Agents built with the Agent SDK use MCP the same way. Pass servers in the mcpServers option (mcp_servers in Python), or let the SDK pick up the project’s .mcp.json, which it loads when the project setting source is enabled — as it is by default. Tools appear to Claude as mcp__<server>__<tool>, and must be permitted: list them, or a server wildcard such as mcp__github__*, in allowedTools. The docs recommend this over broad permission modes, since a wildcard grants exactly one server.

An agent with one remote MCP serverpython
import asyncio, os
from claude_agent_sdk import query, ClaudeAgentOptions, SystemMessage

options = ClaudeAgentOptions(
    mcp_servers={
        "github": {
            "type": "http",
            "url": "https://api.githubcopilot.com/mcp/",
            "headers": {"Authorization": f"Bearer {os.environ['GITHUB_TOKEN']}"},
        }
    },
    allowed_tools=["mcp__github__list_issues"],   # permit only what the task needs
)

async def main():
    async for message in query(prompt="List the 3 newest issues", options=options):
        if isinstance(message, SystemMessage) and message.subtype == "init":
            for server in message.data.get("mcp_servers", []):
                if server.get("status") in ("failed", "needs-auth"):
                    print("Unavailable:", server["name"])

asyncio.run(main())

Check the connection status. The init message reports each server as pending, connected, failed, needs-auth or disabled. The docs warn that when a server is unavailable Claude can fall back to built-in tools, so a failed connection does not stop the run — it quietly changes how the answer was produced.

Build, reuse, or expose as a resource

For a standard system — GitHub, Sentry, a Postgres database, a browser — an existing server is usually the right choice: someone else maintains it, and the Anthropic Directory and the MCP servers repository list many. Build your own when the workflow is specific to your team: an internal deploy pipeline, a house data model, a tool that combines several internal APIs into one task. Whichever you use, remember that Claude also has built-in tools. If an MCP tool’s description does not say clearly what it offers beyond them — for instance, that a code-search tool searches every repository in the organisation, not just the checkout — Claude may reach for Grep instead.

Not everything should be a tool. MCP servers can also expose resources: readable content identified by a URI, such as a database schema, a documentation index or a list of open incidents. The MCP specification calls resources application-driven, while tools are model-controlled — the application or user decides to include a resource, where a tool is something the model chooses to call. In Claude Code you can reference a server’s resources with @ mentions. Offering a catalogue as a resource lets the agent start from a map instead of spending tool calls exploring.

NeedBetter asWhy
Look up one customer, create a ticketToolAn action with inputs that the model decides to take
The database schema, the docs hierarchyResourceReference context; avoids exploratory calls
Standard SaaS integrationExisting serverMaintained elsewhere; no code to own
Team-specific multi-step workflowCustom serverNo off-the-shelf server fits the job

Traps the wrong answers are built from

Tempting but wrongDo this instead
Committing a token inside .mcp.jsonUse ${VAR} expansion and let each developer set the variable.
Putting team tooling in one person’s user or local scopeDefine shared servers at project scope in .mcp.json.
Adding personal or experimental servers to .mcp.jsonUse user scope (all projects) or local scope (this project only).
Building a custom server for a standard integrationUse a maintained existing server; build only for team-specific workflows.
Making the agent explore a catalogue with many tool callsExpose the catalogue as an MCP resource it can start from.

You should now be able to

  • Choose local, project or user scope for an MCP server based on who needs it.
  • Share a server in .mcp.json using ${VAR} and ${VAR:-default} instead of secrets.
  • Connect MCP servers to an Agent SDK agent, permit their tools and check connection status.
  • Decide between an existing server and a custom one for a given integration.
  • Expose reference content as MCP resources to cut exploratory tool calls.

Practice questions

Original questions written for this lesson, in the exam’s style. Answer first, then open the reasoning — every option is explained, including why the wrong ones are tempting.

  1. Question 1

    A team wants every developer on a repository to have the same Jira MCP server in Claude Code. Each developer has their own Jira API token.

    What is the best configuration?

    1. AEach developer adds the server with --scope user and their token.
    2. BCommit .mcp.json with the server and one team token in its env.
    3. CCommit .mcp.json with the server and ${JIRA_TOKEN} in its env.
    4. DAdd the server at local scope and share the resulting ~/.claude.json.
    Show answer and reasoning
    1. AIncorrect. It works, but the setup is not shared or versioned, and each copy drifts.
    2. BIncorrect. It shares the server but commits a secret and makes everyone act as one identity.
    3. CCorrect. Project scope shares the configuration; expansion gives each developer their own token without committing it.
    4. DIncorrect. That file is personal and holds other private settings; it is not meant to be shared.
  2. Question 2

    A developer is trying out a new MCP server for a code-metrics service. They are not sure the team will want it, and it needs their personal API key.

    Where should they add it?

    1. ALocal scope, the default for claude mcp add.
    2. BProject scope, so the team can see it early.
    3. CProject scope with the key hard-coded, removed later.
    4. DA new ~/.claude/mcp.json file in their home folder.
    Show answer and reasoning
    1. ACorrect. It stays private to them and active only in this project while they evaluate it.
    2. BIncorrect. That pushes an unvetted server and an approval prompt onto every teammate.
    3. CIncorrect. The key would enter version control history, where removing it later does not help.
    4. DIncorrect. Claude Code does not read that path; configuration lives in ~/.claude.json or .mcp.json.
  3. Question 3

    An agent answering questions about an analytics warehouse spends its first eight tool calls listing tables and describing columns before it writes any query. The schema changes only weekly.

    Which change most directly reduces those exploratory calls?

    1. ARaise MAX_MCP_OUTPUT_TOKENS so each listing returns more at once.
    2. BTell the agent in its prompt to guess table names first.
    3. CAdd a second database server so the agent has more tools to try.
    4. DExpose the schema as an MCP resource the agent can start from.
    Show answer and reasoning
    1. AIncorrect. Bigger results may cut a call or two, but the agent is still exploring from scratch.
    2. BIncorrect. Guessing produces failed queries; it swaps exploration for errors.
    3. CIncorrect. More overlapping tools make selection harder and do not supply the schema.
    4. DCorrect. A resource gives the agent the map up front, so it can go straight to the right query.

Sources

Drafted with AI assistance and checked against the sources above; expert review is in progress. Spotted an error? Tell us and it gets fixed, dated and listed on how this is written.