claudio.cool
CCAR-FLessons

CCAR-F · Tool Design & MCP

MCP servers in Claude Code and in the agent: scope, credentials and resources

⏱ 3 min readDraft

MCP (Model Context Protocol) is the standard for connecting an agent to external systems: an MCP server exposes tools (actions) and resources (content). In Claude Code and the Agent SDK, exam questions revolve around four decisions: where each server goes, how credentials travel, what the agent sees when there are several, and what’s worth exposing as a resource.

Where each server goes

Scope File Who gets it
Project scope .mcp.json at the repo root The whole team, through git
User scope ~/.claude.json Only you, in all your projects

Team tooling (the Jira server, the staging database server) goes in .mcp.json. A personal or experimental server goes in ~/.claude.json: it’s available in all your projects and doesn’t affect anyone else. Putting it in .mcp.json would impose it on the team. (Claude Code also has a local scope, also stored in ~/.claude.json, for a server of your own in a single project.)

For security, Claude Code asks for approval in an interactive session before using servers from a .mcp.json that came with the repo.

Secrets are never written out

A token written literally in .mcp.json enters the git history and anyone with access can read it, even after it’s deleted. The fix is environment variable expansion:

{
  "mcpServers": {
    "github": {
      "command": "github-mcp",
      "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }
    }
  }
}

The file is shared; the value stays on each developer’s machine. There is also ${VAR:-value} for a default value. If the secret was already committed, it also has to be rotated.

Several servers at once

Tools from every configured server, project and user, are discovered at connection time and are available at the same time. The levels add up: the personal one doesn’t hide the team’s and there’s nothing to activate. An agent can use jira (from the project) and notes (yours) in the same request.

Tool or resource

An MCP resource exposes a content catalog: database schemas, policy documents, issue summaries, the documentation hierarchy. The agent sees what’s available without spending exploratory calls. If an agent makes five calls to list_tables and describe_table in every conversation, or rereads the same six policy documents, that’s a resource. Tools are actions; resources are content.

Community first

For a standard integration (Jira, Slack, GitHub), first evaluate a community MCP server: it’s maintained and covers the common cases. Build your own, small and narrow, only for the team’s real gap, such as an internal approval action.

If the agent ignores your MCP tool

If a search_codebase described as “Searches code” loses to Grep, the cause is the description: Grep comes with a detailed built-in description. Expand the MCP tool’s description with what it returns and when to prefer it. The model doesn’t measure speed and gives built-in tools no priority of their own.

The usual traps

  • Building a custom server without looking at existing ones.
  • Calling the API through Bash and losing descriptions and structured responses.
  • Copying the schema or the policies into the system prompt: it costs tokens on every request and goes stale.
  • Removing Bash or forcing tool_choice so the agent uses the MCP tool.

In the exam

“For the whole team” is .mcp.json; “just for me, in all my projects” is ~/.claude.json; a literal token becomes ${VARIABLE}; repeated exploratory calls call for a resource.

Quick question

A practice exam question on this domain. It counts towards your progress.

An electronics retailer's after-sales agent can issue refunds through a process_refund tool. Company policy lets the agent refund up to 500 pounds automatically; anything above that needs a human team leader.

A customer returns a faulty television and asks for a 750-pound refund. The tool returns an error: "Refund amount of 750 pounds exceeds the 500 pounds automatic refund limit." The agent retries the call three times, a few seconds apart, and each attempt fails with the same message. The customer waits several minutes before the agent finally says it cannot help.

The tool does set isError: true on the response, but it does not include any field that says whether the failure is worth retrying. The retail chain has 40 stores and the agent handles online orders only.

Why does each retry fail, and what should the agent do?

Practise this domain in a practice exam →