Skip to content

MCP Server Integration

This module is about operationalizing MCP: - Where MCP server config lives - How credentials are handled - How Claude Code discovers tools/resources - How to decide between existing MCP servers and custom ones.

The exam is likely to test practical judgment:

Should this MCP server be project-scoped or personal?
Should this token be committed?
Should this data be a tool or a resource?
Why is Claude Code still using Grep instead of the MCP tool?
Should we build a custom Jira MCP server or use an existing one?


1. Core mental model

MCP servers add external capabilities to Claude Code and agent workflows. Claude Code can connect to remote HTTP servers, local stdio servers, SSE servers, and WebSocket servers, etc; current Claude Code docs recommend HTTP for remote cloud services where available, while stdio is used for local processes that need direct system access. (Claude Code)

The exam version:

MCP server = capability provider.
Claude Code / agent = MCP client.
Configured MCP servers expose tools, resources, and prompts.
    Tools let the model perform actions or retrieval.
    Resources expose contextual data/catalogs.
    Prompts expose reusable interaction templates.


2. MCP server scoping

The official statement emphasizes two scopes:

Project-level: .mcp.json
User-level: ~/.claude.json

Current Claude Code docs further distinguish local, user, and project scopes. - Local and user-scoped servers are stored in ~/.claude.json; - Project-scoped servers are stored in .mcp.json at the project root. Project scope is designed to be shared with the team through version control. (Claude Code)

2.1 Project-scoped MCP servers: .mcp.json

Use project scope when the MCP server is part of the team’s shared workflow.

Examples:

Team Jira integration
Team GitHub workflow server
Internal documentation server
Project database schema server
Design-system knowledge server
Release-management server

Claude Code stores project-scoped servers in a .mcp.json file at the project root; the docs explicitly describe this as suitable for team collaboration and version control. (Claude Code)

Example:

{
  "mcpServers": {
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/",
      "headers": {
        "Authorization": "Bearer ${GITHUB_TOKEN}"
      }
    },
    "project-docs": {
      "command": "npx",
      "args": ["-y", "@company/project-docs-mcp"],
      "env": {
        "DOCS_API_TOKEN": "${DOCS_API_TOKEN}"
      }
    }
  }
}

Exam answer pattern:

Put shared team tooling in project-scoped .mcp.json, but use environment variable expansion so credentials are not committed.

Project server approval flow

Project-scoped servers from .mcp.json are not trusted automatically. Because .mcp.json is checked into version control, a malicious or compromised commit could otherwise inject an MCP server that runs on every teammate's machine. To prevent this, Claude Code requires the user to approve a project-scoped server on first use before its tools become available; until approved, the server shows as pending. The /mcp command shows server status and lets the user review and approve project servers. This approval gate is the safeguard against malicious committed configs. (Claude Code)

2.2 User-scoped MCP servers: ~/.claude.json

Use user scope for tools that are personal, experimental, or useful across many projects but should not be imposed on the team.

Examples:

Personal Notion MCP server
Experimental browser automation server
Private local scripts
Personal productivity tools
Prototype MCP server under development
Cross-project HubSpot or personal CRM access

Claude Code docs say user-scoped servers are stored in ~/.claude.json, are available across all projects on the machine, and remain private to that user account. (Claude Code)

Example command:

claude mcp add --transport http hubspot --scope user https://mcp.hubspot.com/anthropic

2.3 Local scope nuance

The official exam statement calls out project vs user scope. Current Claude Code docs also describe ==local scope as the default==: it loads only in the project where it was added, stays private to the user, and is stored under that project’s path inside ~/.claude.json. (Claude Code)

For the exam, remember:

Need Best scope
Shared by team, checked into repo Project scope: .mcp.json
Personal across all projects User scope: ~/.claude.json
Personal to one project only Local scope: ~/.claude.json under project path
Enterprise-controlled fixed server set Managed configuration, not imp for exam

3. Environment variable expansion

The official statement specifically mentions:

${GITHUB_TOKEN}

This is exam-important.

Correct pattern

Commit the server definition, not the secret:

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "${GITHUB_TOKEN}"
      }
    }
  }
}

Then each developer sets:

export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx

Claude Code supports ${VAR} and ${VAR:-default} expansion in .mcp.json; expansion works in fields such as command, args, env, url, and HTTP headers. If a required environment variable has no default and is not set, Claude Code fails to parse the config. (Claude Code)

Bad pattern:

{
  "mcpServers": {
    "github": {
      "env": {
        "GITHUB_TOKEN": "ghp_real_secret_token_committed_to_git"
      }
    }
  }
}

Why bad:

Secret is committed.
Token rotation becomes painful.
Everyone shares the same credential.
Least-privilege access becomes harder.
Auditability suffers.

Better HTTP example:

{
  "mcpServers": {
    "secure-api": {
      "type": "http",
      "url": "${API_BASE_URL:-https://api.example.com}/mcp",
      "headers": {
        "Authorization": "Bearer ${API_TOKEN}"
      }
    }
  }
}

Claude Code’s Agent SDK docs also show environment variable expansion for MCP server credentials in .mcp.json, including ${GITHUB_TOKEN} and ${API_TOKEN}. (Claude Code)


4. Tool discovery from configured MCP servers

The official statement says tools from all configured MCP servers are discovered at connection time and made available to the agent.

Current Claude Code behavior has an important nuance: ==MCP Tool Search is enabled by default==, so tool definitions may be deferred instead of all loaded into context upfront. Claude Code says ==only tool names and server instructions load at session start==, and Claude can search/load relevant tools when needed. From the user’s perspective, MCP tools continue to work as before, but this reduces context usage for large MCP tool sets. (Claude Code)

Exam-safe wording:

Configured MCP servers are connected/discovered as part of the agent environment.
Their tools can be available simultaneously.
With current Claude Code Tool Search, full tool definitions may be deferred until needed.

Why this matters

If you configure:

GitHub MCP
Jira MCP
Docs MCP
Database MCP
Sentry MCP

Claude may have access to all of those capabilities in one workflow. That is powerful, but it also creates the D2.3 risk: too many tools can increase decision complexity. D2.4 focuses on integration, but you should still remember D2.3’s principle: configure only what the workflow needs.

Checking availability

Claude Code provides commands such as:

claude mcp list
claude mcp get github

and inside Claude Code:

/mcp

The docs say /mcp shows server status and tool count, and project-scoped servers may require approval before use. (Claude Code)

In Agent SDK workflows, MCP tools follow the naming pattern:

mcp__<server-name>__<tool-name>

For example:

mcp__github__list_issues

The Agent SDK docs say MCP tools require explicit permission before Claude can use them, and allowedTools can allow specific MCP tools or wildcards such as mcp__github__*. (Claude Code)


5. MCP resources: reducing exploratory tool calls

This is one of the most important D2.4 concepts.

An MCP tool is for actions or retrieval. An MCP resource is for exposing contextual data that the client can list/read, such as files, database schemas, documentation indexes, issue summaries, or content catalogs. The MCP spec says resources expose data that provides context to language models, each identified by a URI. (Model Context Protocol)

Problem without resources

Suppose Claude needs to understand what documentation exists.

Without a resource catalog, it may do this:

search_docs("auth")
search_docs("authentication")
search_docs("OAuth")
search_docs("login")
search_docs("SSO")
search_docs("permissions")

This creates exploratory tool-call noise.

Better resource design

Expose a resource catalog:

resource: docs://catalog

Example resource contents:

{
  "sections": [
    {
      "id": "auth",
      "title": "Authentication and SSO",
      "uri": "docs://auth/index",
      "summary": "OAuth, SAML, SSO, token refresh, and session handling."
    },
    {
      "id": "billing",
      "title": "Billing and Entitlements",
      "uri": "docs://billing/index",
      "summary": "Plans, invoices, subscriptions, and entitlement checks."
    },
    {
      "id": "api",
      "title": "Public API Reference",
      "uri": "docs://api/index",
      "summary": "REST APIs, webhooks, rate limits, and examples."
    }
  ]
}

Then Claude can inspect the catalog and choose the relevant resource instead of blindly searching.

The MCP spec defines resources/list for discovering available resources and resources/read for retrieving a specific resource by URI. (Model Context Protocol)

Good resource candidates

Content type Why resource is better than exploratory tools
Database schemas Claude can inspect tables/columns before querying
Documentation hierarchy Claude can navigate known docs rather than guessing terms
Issue summaries Claude sees available issues before fetching details
API catalogs Claude can locate relevant endpoints
Architecture indexes Claude can select relevant subsystem docs
Test inventory Claude can inspect test coverage before proposing changes

Tools vs resources vs prompts: the precise distinction

This three-way contrast is exam-worthy. Each primitive is controlled by a different party and serves a different purpose.

Primitive Controlled by What it is Purpose
Tools Model-invoked Actions/retrieval functions the model decides to call Perform an operation or fetch data on demand
Resources Application-controlled Content catalogs/data the agent can read (files, schemas, doc indexes, issue summaries) Give the agent visibility into what data exists, so it avoids exploratory tool calls
Prompts User-invoked Reusable interaction templates the user triggers Standardize a workflow the user launches (e.g. "draft release notes")

The key contrast: tools are model-invoked actions, resources are content catalogs the agent reads to avoid exploratory tool calls, and prompts are user-invoked templates. A static schema or doc index should be a resource (read it once instead of guessing search terms); a query-by-parameters operation should be a tool; a standardized user-launched workflow should be a prompt.

Exam heuristic

Use resources when the agent needs visibility into what data exists.

Use tools when the agent needs to perform an operation.

Resource: "Here is the catalog of available docs."
Tool: "Search docs for this query."
Resource: "Here is the database schema."
Tool: "Run this approved query."
Resource: "Here are open issue summaries."
Tool: "Fetch issue JIRA-123 in full."

6. Preventing Claude Code from preferring built-in tools over MCP tools

The official statement calls out this skill:

Enhance MCP tool descriptions to explain capabilities and outputs in detail, preventing the agent from preferring built-in tools like Grep over more capable MCP tools.

This is a subtle but highly testable point.

Bad MCP tool description:

search_docs: Search docs.

Claude Code may prefer built-in Grep because it knows Grep searches files.

Better MCP tool description

search_architecture_docs:
Search the indexed architecture documentation service, including design docs, ADRs, RFCs, and generated API docs that may not exist in the local checkout. Use this instead of Grep when the question concerns architecture decisions, historical design rationale, ownership, or documentation outside the current repository. Returns ranked document snippets with title, URI, owner team, last-updated date, and confidence score. Do not use this for searching local source files; use Grep for local code text search.

This description tells Claude:

what the MCP tool can access beyond local files;
when it is better than Grep;
what it returns;
when Grep is still better.

Exam pattern

If Claude keeps using Grep instead of a richer MCP tool, the best fix is usually:

Improve the MCP tool description to make its capabilities, data scope, outputs, and advantages explicit.

Not:

Disable Grep globally.
Force the MCP tool on every turn.
Tell Claude vaguely to use MCP more.


7. Community MCP server vs custom MCP server

The official guide says:

Use existing community MCP servers for standard integrations.
Build custom servers for team-specific workflows.

This is a proportionate-architecture principle.

Anthropic’s Agent SDK docs describe MCP as a way for agents to query databases and integrate with APIs like Slack and GitHub without writing custom tool implementations. (Claude Code)

Use an existing/community server when:

The integration is standard.
The API is common.
Your workflow is generic.
The server is maintained and trusted.
You mainly need CRUD/search/list actions.

Examples:

Jira
GitHub
Slack
PostgreSQL
Sentry
Notion
Google Drive

Build a custom server when:

The workflow is company-specific.
You need opinionated business logic.
You need custom authorization checks.
You need to aggregate across internal systems.
You need to expose curated resources/catalogs.
You need domain-specific error handling or guardrails.

Examples:

release_readiness_server
customer_escalation_triage_server
autodesk_build_pipeline_server
design_review_context_server
entitlement_diagnostics_server

Exam heuristic

For Jira:

Need normal Jira issue search/update? Use existing Jira MCP server.
Need company-specific release-blocker triage across Jira + GitHub + CI + ownership metadata? Build custom MCP server.

8. Configuration examples

8.1 Project-scoped .mcp.json with GitHub token

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "${GITHUB_TOKEN}"
      }
    }
  }
}

Use when:

All developers on the project should have the GitHub MCP integration.
Each developer supplies their own token through the environment.
No secret is committed.

8.2 Project-scoped HTTP server with default URL

{
  "mcpServers": {
    "project-docs": {
      "type": "http",
      "url": "${DOCS_MCP_URL:-https://docs.example.com/mcp}",
      "headers": {
        "Authorization": "Bearer ${DOCS_TOKEN}"
      }
    }
  }
}

Use when:

The team shares one docs server by default.
Developers can override the base URL.
Token stays in the environment.

8.3 User-scoped personal server

claude mcp add --transport http notion --scope user https://mcp.notion.com/mcp

Use when:

Only the individual user needs the server.
The server should be available across projects.
It should not be committed into the repo.

8.4 Agent SDK MCP configuration

import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "List recent issues in the current repository",
  options: {
    mcpServers: {
      github: {
        command: "npx",
        args: ["-y", "@modelcontextprotocol/server-github"],
        env: {
          GITHUB_TOKEN: process.env.GITHUB_TOKEN
        }
      }
    },
    allowedTools: [
      "mcp__github__list_issues",
      "mcp__github__search_issues"
    ]
  }
})) {
  if (message.type === "system" && message.subtype === "init") {
    console.log("MCP servers:", message.mcp_servers);
  }
}

This mirrors the Agent SDK pattern where MCP servers are configured in code and MCP tools are allowed using allowedTools. (Claude Code)


9. D2.4 exam decision table

Scenario Best answer
Team wants everyone to use the same Jira MCP server Put it in project .mcp.json
Developer is experimenting with a personal MCP server Put it in ~/.claude.json user/local scope
.mcp.json contains real token Replace token with ${TOKEN_NAME}
Claude Code uses Grep instead of docs MCP search Improve MCP tool description: scope, capability, output, when better than Grep
Agent does many exploratory searches to discover docs Expose docs catalog as MCP resources
Need standard Jira integration Use existing/community MCP server
Need team-specific triage across Jira + CI + ownership Build custom MCP server
Multiple MCP servers configured Their tools/capabilities may be available in same agent environment; use scoping/permissions/tool search to control complexity
Large tool set consumes context Use MCP Tool Search / avoid always loading too many tools
Need to verify MCP server status Use /mcp, claude mcp list, or claude mcp get <name>

10. Exam traps

Trap 1: Committing secrets in .mcp.json

Wrong:

"GITHUB_TOKEN": "ghp_actual_secret"

Right:

"GITHUB_TOKEN": "${GITHUB_TOKEN}"

Trap 2: Personal tools in project config

Wrong:

Commit your personal Notion MCP server into .mcp.json.

Right:

Use user scope in ~/.claude.json.

Trap 3: Team tooling only in user config

Wrong:

Ask every teammate to manually add the same Jira MCP server to ~/.claude.json.

Right:

Use project-scoped .mcp.json with env vars for credentials.

Trap 4: Using tools for catalogs

Wrong:

Agent repeatedly calls search_docs just to discover what docs exist.

Right:

Expose docs://catalog as an MCP resource.

Trap 5: Building custom servers too early

Wrong:

Build a custom Jira MCP server for basic issue search.

Right:

Use an existing Jira/community server unless the workflow is team-specific.

Trap 6: Weak MCP tool descriptions

Wrong:

search_docs: Search docs.

Right:

Explain what corpus it searches, what it returns, when it is better than Grep, and when not to use it.

11. Scenario-based questions

Question 1

A team wants every developer working on a repository to have the same Jira MCP tools available in Claude Code. The server needs each developer’s own token.

What is the best configuration?

A. Put the Jira MCP server and a shared token in .mcp.json.
B. Put the Jira MCP server in project .mcp.json and reference ${JIRA_TOKEN}.
C. Ask each developer to configure it manually in user-level ~/.claude.json.
D. Build a custom Jira server from scratch.

Answer

B. Project .mcp.json is right for shared team tooling. Environment variable expansion keeps credentials out of version control.


Question 2

A developer is experimenting with a personal MCP server that connects to their private Notion workspace. Nobody else on the team should use it.

Where should it be configured?

A. Project .mcp.json
B. User-level ~/.claude.json
C. README.md
D. Hardcoded into CLAUDE.md

Answer

B. Personal or experimental servers belong in user/local configuration, not shared project config.


Question 3

Claude repeatedly uses Grep to search local files even though a documentation MCP server indexes ADRs, RFCs, and docs outside the repo.

What is the best fix?

A. Disable Grep globally.
B. Force the docs MCP tool on every turn.
C. Improve the MCP tool description to explain its external corpus, richer outputs, and when it should be preferred over Grep.
D. Remove the MCP server.

Answer

C. The model needs to understand why the MCP tool is more capable for certain tasks.


Question 4

Claude makes many exploratory calls like search_docs("auth"), search_docs("login"), and search_docs("SSO") just to understand what documentation exists.

What should you expose?

A. A broader search tool.
B. A docs catalog as an MCP resource.
C. A forced tool call.
D. A new system prompt saying “search less.”

Answer

B. Resources expose available context catalogs and reduce exploratory tool calls.


Question 5

A company needs basic Jira issue search and update from Claude Code.

What is the best first choice?

A. Use an existing trusted Jira MCP server.
B. Build a custom Jira MCP server immediately.
C. Avoid MCP and paste Jira exports manually.
D. Store Jira credentials in the repo.

Answer

A. For standard integrations, prefer existing/community MCP servers. Build custom only for team-specific workflows.


Question 6

A release workflow needs to combine Jira blockers, GitHub PR status, CI failures, ownership metadata, and internal release policy into one curated workflow.

What is the best approach?

A. Use only a generic Jira MCP server.
B. Build a custom team-specific MCP server or workflow layer.
C. Ask Claude to manually search every tool.
D. Commit all API keys into .mcp.json.

Answer

B. This is no longer a standard integration. It is a team-specific workflow spanning multiple systems and policies.


Question 7

A .mcp.json file contains:

{
  "headers": {
    "Authorization": "Bearer abc123-real-token"
  }
}

What is wrong?

A. Nothing.
B. Secrets should not be committed; use environment variable expansion such as Bearer ${API_TOKEN}.
C. Headers are never allowed.
D. MCP servers cannot use HTTP.

Answer

B. The config should be shareable without exposing credentials.


Question 8

Which statement best describes MCP resources?

A. They are model-controlled functions used to perform actions.
B. They are application-exposed contextual data such as files, schemas, or catalogs.
C. They are always destructive.
D. They replace all tools.

Answer

B. Resources provide context; tools perform actions or retrieval.


Question 9

A project .mcp.json server appears as pending approval.

What should happen?

A. Claude Code should silently run it.
B. The user should review and approve it in Claude Code.
C. The token should be committed.
D. The server must be moved to user scope.

Answer

B. Claude Code prompts for approval before using project-scoped servers from .mcp.json. (Claude Code)


Question 10

An Agent SDK workflow configures a GitHub MCP server, but Claude cannot call its tools.

What is a likely missing piece?

A. allowedTools for the MCP tools.
B. A larger prompt.
C. A different programming language.
D. A .gitignore entry.

Answer

A. In Agent SDK workflows, MCP tools require explicit permission, and allowedTools can permit specific tools or wildcards. (Claude Code)


12. High-yield D2.4 checklist

Memorize this:

1. Project-shared MCP servers go in .mcp.json.
2. Personal or experimental MCP servers go in ~/.claude.json.
3. Current Claude Code also distinguishes local scope, stored in ~/.claude.json for one project.
4. Do not commit secrets in .mcp.json.
5. Use environment variable expansion such as ${GITHUB_TOKEN}.
6. Environment variables can be used in env, headers, url, args, and command fields.
7. Configured MCP servers expose tools/resources/prompts into the agent environment.
8. MCP Tool Search may defer full tool definitions to reduce context usage.
9. Use /mcp, claude mcp list, and claude mcp get to inspect configured servers.
10. MCP tools are named like mcp__server__tool in Agent SDK contexts.
11. allowedTools controls which MCP tools an SDK agent may use.
12. Improve MCP tool descriptions when Claude prefers built-in tools like Grep.
13. Use existing/community MCP servers for standard integrations.
14. Build custom MCP servers for team-specific workflows.
15. Use MCP resources to expose content catalogs and reduce exploratory tool calls.

D2.4 mental model

Scope determines who gets the server.
Environment variables determine how secrets stay out of config.
Tool descriptions determine whether Claude chooses MCP tools correctly.
Resources determine whether Claude can see what content exists before searching.
Community-vs-custom determines whether you are solving a standard integration or a team-specific workflow.