CCAR-F · Study Guide

← Domain 2: Tool Design & MCP Integration

2.4 · Lesson 4 of 5

MCP Server Integration

What You Need to Know

MCP (Model Context Protocol) servers extend Claude's capabilities by connecting it to external systems — databases, APIs, development tools, and issue trackers. Configuring them correctly determines whether your team shares a consistent toolset or descends into configuration chaos.

The Scoping Hierarchy

MCP server configuration lives at two levels, and mixing them up is where most setup problems start.

Project-level: .mcp.json

Lives in the project repository root. Version-controlled. Shared with every team member who clones or pulls the repository. Use this for servers that the entire team needs — your Jira integration, your GitHub tools, your internal API connectors.

{
  "mcpServers": {
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/"
    },
    "atlassian": {
      "type": "http",
      "url": "https://mcp.atlassian.com/v1/mcp/authv2"
    },
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "${WORKSPACE_ROOT:-.}"]
    }
  }
}

Note the two entry shapes. A remote server declares "type": "http" and a url. A local one declares a command and args, and speaks over stdio. An entry with a url but no type is a configuration error — Claude Code reads it as a stdio server, skips it, and tells you to add the type. Both GitHub and Atlassian ship official remote servers now, which is why neither is an npx line.

User-level: ~/.claude.json

Lives in the user's home directory. Personal. Not version-controlled. Not shared with teammates. Use this for experimental servers, personal integrations, or servers you are testing before proposing them to the team.

Key principle: all tools from all configured servers (both project-level and user-level) are discovered at connection time and available simultaneously. There is no manual activation step — if a server is configured and reachable, its tools appear in the agent's toolkit.

Environment Variable Expansion

The .mcp.json file supports ${VARIABLE_NAME} syntax for environment variable expansion. This is how you keep credentials out of version control whilst still sharing server configuration with your team.

{
  "env": {
    "GITHUB_TOKEN": "${GITHUB_TOKEN}",
    "DATABASE_URL": "${DATABASE_URL}"
  }
}

Each developer sets their own tokens locally (in their shell profile, .env file, or secrets manager). The .mcp.json file references the variable names, not the values. This means:

  • The configuration file is safe to commit to version control
  • Each developer authenticates with their own credentials
  • Token rotation does not require config file changes
  • No secrets leak through repository history

There is a second form worth knowing: ${VAR:-default} expands to the variable when it is set and falls back to default when it is not. Use it for machine-specific paths that have a sensible fallback, as in the ${WORKSPACE_ROOT:-.} argument above.

MCP Resources

MCP resources expose content catalogues to agents without requiring exploratory tool calls. Instead of calling a tool to discover what data exists, the agent can get that information upfront.

That is the exam guide's framing and the keyed answer. One precision from the MCP specification (September 2026): resources are application-controlled. The server lists them, but the client decides when to attach one to the model's context, so the agent sees a resource only when the host surfaces it. Claude Code does that through @server:resource mentions and a resource-listing tool. Putting a server in the config does not by itself place resource contents in the model context.

Examples of what to expose as resources:

  • Issue summaries — a list of current Jira issues with titles and statuses
  • Documentation hierarchies — a table of contents for your internal docs
  • Database schemas — table names, column types, and relationships

The payoff is fewer wasted calls. Without resources, an agent might call list_tables, then describe_table for every table, burning tool calls just to get its bearings. With a database schema resource, it knows that catalogue as soon as the host attaches it.

Resources show agents what data is available. Tools let them act on it.

The Build-vs-Use Decision

This decision comes up constantly, in the exam and in real work. Your team needs to integrate with an external system: build a custom MCP server, or use an existing community one?

Use community servers for standard integrations:

  • Jira, GitHub, Slack, Linear, and Notion all have maintained community MCP servers
  • They cover standard use cases, are tested by the community, and receive updates
  • Using them saves development time and maintenance burden

Community servers should be evaluated first for standard integrations. Build custom servers only when:

  • Your team has specific workflows that community servers cannot handle
  • You need custom business logic embedded in the tool layer
  • You require integration with proprietary internal systems that have no suitable community server

The exam consistently favours the pragmatic choice. Evaluate community servers first whenever a standard integration is involved. Build custom only when the scenario explicitly describes team-specific requirements that community servers cannot meet.

Enhancing MCP Tool Descriptions

When an MCP tool has a sparse description, the agent may prefer built-in tools (like Grep) even when the MCP tool is more capable. The model simply has better context about built-in tools — their descriptions are rich and detailed.

The fix: enhance your MCP tool descriptions to explain capabilities and outputs in detail. Instead of:

search_codebase: "Searches code"

Write:

search_codebase: "Performs semantic code search across the
entire repository using AST-aware indexing. Returns matching
functions, classes, and methods with full context including
file path, line numbers, and surrounding code. More accurate
than text-based grep for finding code by intent rather than
exact string match. Use this instead of Grep when searching
for code by what it does rather than what it contains."

The enhanced description should communicate capabilities, outputs, when to use the tool, and how it compares with built-in alternatives. That gives the model enough context to prefer the MCP tool when it is genuinely more capable than the built-in alternative.

Exam traps

  • Building a custom MCP server for a standard integration like Jira

    Community MCP servers exist for standard integrations and should be evaluated first. Custom builds are only justified for team-specific workflows that community servers cannot handle.

  • Putting team-wide MCP server configuration in ~/.claude.json

    ~/.claude.json is user-level and personal — it is not version-controlled or shared. Team-wide servers belong in .mcp.json at the project root.

  • Committing credentials directly in .mcp.json instead of using environment variable expansion

    Credentials in version control are a security risk. Use ${GITHUB_TOKEN} syntax so each developer sets tokens locally and secrets never enter repository history.

  • Leaving MCP tool descriptions sparse, causing the agent to prefer built-in tools

    The model defaults to tools it understands best. Sparse MCP descriptions lose out to detailed built-in tool descriptions. Enhance MCP descriptions to explain capabilities and outputs fully.

Practice scenario

A team needs to integrate with Jira for issue tracking in their Claude Code workflow. A developer proposes building a custom MCP server. What is the correct first step?

Choose one answer

Build exercise

Configure MCP Servers with Scoping and Environment Variables

30 minutes

What you'll learn

  • Configure project-level MCP servers in .mcp.json for team-wide sharing
  • Use environment variable expansion to keep credentials out of version control
  • Distinguish project-level and user-level MCP configuration scoping
  • Expose MCP resources to reduce unnecessary exploratory tool calls
  • Write enhanced MCP tool descriptions that compete with built-in tool descriptions
  1. Step 1

    Create a .mcp.json file in the project root configuring an official or community MCP server such as GitHub

    Add a project-level mcpServers entry for a standard integration, using the remote or local entry shape that matches how that server runs.

    Why: Project-level .mcp.json is version-controlled and shared with every team member who clones the repository. The exam tests whether you know that team-wide servers belong here, not in ~/.claude.json. Using community servers for standard integrations is always the correct first choice.

    You should see: A .mcp.json file at the project root containing an mcpServers object with at least one server entry. A remote server needs "type": "http" and a url; a local one needs command and args.

  2. Step 2

    Use ${GITHUB_TOKEN} environment variable expansion for authentication credentials

    Reference the credential by variable name in the server's environment or header configuration, and confirm the real token never appears in the diff.

    Why: Committing credentials directly in .mcp.json is a security risk the exam penalises. The ${VARIABLE_NAME} syntax lets the configuration file reference environment variables without containing the actual values, keeping secrets out of repository history.

    You should see: The environment or header configuration of your server references ${GITHUB_TOKEN} (not an actual token value). Running git diff confirms no secrets are staged for commit. Each developer sets their own token locally.

  3. Step 3

    Add a personal or experimental MCP server to ~/.claude.json

    Put a server you are trying out, and that the team does not share, in the user-level file in your home directory.

    Why: User-level configuration in ~/.claude.json is personal, not version-controlled, and not shared with teammates. The exam tests whether you know the scoping hierarchy: .mcp.json for team servers, ~/.claude.json for personal or experimental servers.

    You should see: A ~/.claude.json file with an mcpServers entry for a personal or experimental server. This file is not in your project repository and not in version control.

  4. Step 4

    Expose a content catalogue as an MCP resource

    Publish a documentation hierarchy or a database schema as a resource the host can attach, instead of making the agent discover that catalogue through tool calls.

    Why: MCP resources give agents visibility into available data without requiring exploratory tool calls. Without resources, an agent might call list_tables then describe_table for every table, wasting multiple tool calls. A schema resource makes that information available when the client attaches it.

    You should see: An MCP resource that exposes structured data (a list of database tables with column types, or a documentation table of contents) at a URI such as db://schema/main. The resource has a name, a description, and a mimeType.

  5. Step 5

    Enhance MCP tool descriptions so they can compete with built-in tools

    Rewrite sparse MCP tool descriptions so they state capabilities, outputs, when to use the tool, and how it differs from built-in alternatives such as Grep.

    Why: When an MCP tool has a sparse description, the agent prefers built-in tools like Grep because their descriptions are richer and more detailed. The exam tests whether you know that enhanced MCP descriptions are required to compete with built-in tools for selection priority.

    You should see: Tool descriptions that are about 3-5 sentences long, explaining what the tool does, what it returns, when to use it, and how it compares to built-in alternatives. For example, a search_codebase description that states it is more accurate than Grep for semantic search.

Sources