Tools, Skills, and MCPs: The Three Building Blocks of Claude Agents
Oscar Gallo
Published on March 19, 2026
Understanding what connects Claude to the world, what makes Claude smarter, and what bridges the gap between them.
If you're building agents with Claude — whether through the Agent SDK, Claude Code, or the API — you've probably run into three terms that get thrown around constantly: Tools, Skills, and MCPs. They sound similar. They overlap in places. And the docs, while thorough, don't always make it obvious when to reach for which.
This post breaks down exactly what each one is, how they differ, and — most importantly — how to think about combining them in real agent architectures.
The One-Liner Version
- Tools execute actions. They connect Claude to the outside world.
- Skills inject expertise. They teach Claude how to approach problems.
- MCPs expose capabilities. They're a protocol that turns any service into a set of tools Claude can discover and call.
If tools are Claude's hands, skills are Claude's training manuals, and MCPs are the standardized plugs that connect Claude to everything else.
Tools: What Claude Does
Tools are the most concrete of the three. A tool is a function Claude can call — it has a name, a JSON schema for its inputs, and it returns a result. When Claude decides it needs to read a file, run a shell command, or call an API, it's using a tool.
The Agent SDK ships with a set of built-in tools that cover the fundamentals:
- Read — Read file contents
- Write — Create or overwrite files
- Edit / MultiEdit — Surgical text replacements in existing files
- Bash — Execute shell commands
- Glob — Find files by pattern
- Grep — Search file contents
- Agent (formerly Task) — Spawn a subagent with its own context window
- WebSearch / WebFetch — Search the web and retrieve page content
These are action-oriented. Each one executes something and returns a result. Claude sees the tool definitions in its context window, decides when to invoke them, receives the output, and continues reasoning.
Custom Tools
Beyond the built-ins, you can define your own tools using in-process MCP servers (more on MCP below). The Agent SDK provides a tool() helper and createSdkMcpServer() to make this straightforward:
from claude_agent_sdk import tool, create_sdk_mcp_server
@tool("lookup_ticket", "Fetch a GitHub issue by number", {"issue_number": int})
async def lookup_ticket(args):
# Your logic here — call GitHub API, query a database, whatever
return {"content": [{"type": "text", "text": f"Issue #{args['issue_number']}: ..."}]}
server = create_sdk_mcp_server(
name="project-tools",
version="1.0.0",
tools=[lookup_ticket]
)
The key insight: tools are about doing. They take an input, perform a side effect or computation, and return a result. They don't teach Claude anything — they give Claude the ability to act.
The Performance Reality
Every tool definition consumes context window tokens. A typical five-MCP-server setup with ~58 tools can burn ~55,000 tokens before Claude processes a single user message. Anthropic has internally observed setups consuming 134,000 tokens in tool definitions alone.
More concerning than cost: accuracy degrades. Anthropic's internal benchmarks showed that with large tool libraries, Opus 4 dropped to 49% accuracy on tool selection — essentially a coin flip. The most common failure mode is picking the wrong tool when names are similar (e.g., notification-send-user vs. notification-send-channel).
Practical guidance: Keep your always-loaded tools scoped to what the agent actually needs for the current task. If an agent is doing git operations and file edits, don't load Slack, Jira, and analytics tools into that same context. For larger tool libraries, use the Tool Search Tool (covered below) to load tools on-demand.
Skills: What Claude Knows
Skills are fundamentally different from tools. They don't execute anything. They don't return results. Instead, skills prepare Claude to solve a problem by injecting domain-specific instructions, workflows, and best practices into the context.
A skill is a filesystem artifact — a directory containing a SKILL.md file and optional supporting resources (scripts, templates, reference data). The SKILL.md has two parts:
- YAML Frontmatter — Metadata that controls how and when the skill loads (name, description, allowed tools, model overrides)
- Markdown Content — The actual instructions that tell Claude what to do and how to do it
Here's what a simple skill structure looks like:
.claude/skills/
└── branch-naming/
└── SKILL.md
And the SKILL.md itself:
---
name: branch-naming
description: >
Enforces team branch naming conventions and PR description
standards. Use when creating branches, opening PRs, or
writing commit messages.
---
# Branch Naming Convention
When creating a new branch, always follow this pattern:
`{type}/{ticket-id}-{short-description}`
Types: feat, fix, chore, refactor, docs, test
## PR Descriptions
Always include:
1. Link to the ticket
2. Summary of changes (2-3 sentences)
3. Testing notes
4. Screenshots if UI changed
## Commit Messages
Use conventional commits: `type(scope): description`
When Claude encounters a task where this skill is relevant, it loads the SKILL.md into context and follows the instructions. The skill didn't do anything — it changed how Claude approaches the work.
Skills vs. Prompts
You might be thinking: "Isn't this just a system prompt?" Sort of, but with key differences:
- Prompts are conversation-level. You write them for one-off tasks.
- Skills are reusable and on-demand. They load dynamically when relevant, across any conversation or agent.
- Skills can include supporting resources — scripts, templates, example files — that go beyond plain text instructions.
The mental model from Anthropic's own docs: Projects say "here's what you need to know." Skills say "here's how to do things."
Using Skills in the Agent SDK
Enable skills by adding "Skill" to your allowed tools and configuring setting sources:
options = ClaudeAgentOptions(
setting_sources=["user", "project"], # Discover skills from filesystem
allowed_tools=["Skill", "Read", "Write", "Bash"],
)
Once configured, Claude automatically discovers skills from .claude/skills/ directories and invokes them when the task matches the skill's description.
The Power Combo: Skills + Tools
Skills and tools aren't competing — they're complementary. A skill might instruct Claude to use certain tools in specific ways. For example:
- A code-review skill might tell Claude to always run
grepforTODOandFIXMEbefore reviewing, usebashto run the test suite, and structure its feedback in a specific format. - A database-migration skill might tell Claude to always back up before running migrations, use a specific naming pattern for migration files, and verify the rollback path.
The skill provides the expertise. The tools provide the capability. Together, they create a specialized agent.
MCP: The Universal Connector
MCP — the Model Context Protocol — is the standardized protocol that lets Claude (and other AI models) connect to external services and data sources. It's the bridge between Claude and everything else: databases, SaaS platforms, APIs, local tools, and file systems.
If tools are individual functions, MCP is the framework for exposing and discovering those functions.
How MCP Works
An MCP server exposes a set of tools (and optionally resources and prompts) over a standardized transport — typically stdio for local servers or SSE/HTTP for remote ones. Claude communicates with these servers using the MCP protocol, which handles:
- Tool discovery — Claude can ask an MCP server what tools it offers
- Tool invocation — Claude calls a tool with structured input and gets structured output
- Resource access — MCP servers can expose data sources (files, database tables, API endpoints) that Claude can read
The Agent SDK supports MCP servers natively:
options = ClaudeAgentOptions(
mcp_servers={
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {"GITHUB_TOKEN": "..."}
},
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://..."]
}
},
allowed_tools=[
"mcp__github__create_pull_request",
"mcp__postgres__query"
]
)
MCP vs. Custom Tools
You can define tools directly in your application code or through MCP servers. Here's when to use which:
Use direct/custom tools when:
- The tool is tightly coupled to your application logic
- You want in-process execution (no IPC overhead)
- The tool needs access to your application's state or memory
Use MCP servers when:
- You're integrating with an external service (GitHub, Slack, databases)
- You want reusable, portable tool packages
- You want to share tool implementations across different agents or projects
- A community MCP server already exists for your use case
The Token Cost of MCP
Every MCP server adds its tool definitions to Claude's context window, even when those tools are idle. This is where the token overhead problem gets real:
- A typical MCP server adds 5-15 tools
- Each tool definition costs ~500-2,000 tokens (name, description, JSON schema)
- Five servers can easily consume 55,000+ tokens
- Jira's MCP server alone uses ~17,000 tokens in definitions
This isn't just a cost problem — it's a quality problem. More tools in context means more opportunities for Claude to pick the wrong one.
Tool Search Tool: The Scaling Solution
Anthropic's answer to MCP sprawl is the Tool Search Tool. Instead of loading all tool definitions upfront, you mark tools with defer_loading: true. Claude only sees the Tool Search Tool itself plus your most critical always-loaded tools. When it needs a specific capability, it searches for relevant tools, and matching definitions get expanded into context on-demand.
The results are significant: 85% reduction in token usage and accuracy jumps from 49% to 74% (Opus 4) and 79.5% to 88.1% (Opus 4.5).
For CLI-based workflows, prefer native CLI tools over MCP when possible. Running gh pr create through Bash consumes zero persistent context — the tool definition for Bash is already loaded. An MCP GitHub server, by contrast, adds dozens of tool definitions to every turn.
The Comparison Table
| Dimension | Tools | Skills | MCP |
|---|---|---|---|
| What it is | A function Claude can call | A knowledge pack Claude can load | A protocol for exposing tools |
| What it does | Executes an action, returns a result | Injects instructions into context | Connects Claude to external services |
| Analogy | Claude's hands | Claude's training manual | The electrical standard that lets any appliance plug in |
| Defined as | JSON schema (name, description, input schema) | SKILL.md file + optional resources | Server exposing tools over a transport |
| Context cost | ~500-2,000 tokens per tool definition | Loaded on-demand when relevant | Proportional to number of exposed tools |
| Persistence | Always present (unless deferred) | Loaded dynamically | Server runs continuously, definitions always present |
| Reusability | Tied to the application/SDK config | Portable across conversations and agents | Portable across any MCP-compatible client |
| In the Agent SDK | allowed_tools=["Read", "Bash", ...] | setting_sources=["project"] + allowed_tools=["Skill"] | mcp_servers={...} |
Architecture Patterns
Pattern 1: Scoped Agent Runs (Minimal Context)
Best for: CI/CD agents, ticket-scoped automation, batch processing.
Load only the tools the agent needs for one specific task. No MCP servers, no skill discovery. Fast, cheap, predictable.
options = ClaudeAgentOptions(
allowed_tools=["Read", "Write", "Bash"],
max_turns=10,
max_budget_usd=0.50,
)
Pattern 2: Skilled Specialist
Best for: Code review, documentation generation, data analysis.
Combine a focused toolset with domain-specific skills. The skills teach Claude your team's standards, and the tools let Claude apply them.
options = ClaudeAgentOptions(
setting_sources=["project"],
allowed_tools=["Skill", "Read", "Grep", "Glob", "Bash"],
)
Pattern 3: Connected Agent (MCP-Heavy)
Best for: Workflow automation across multiple platforms.
Multiple MCP servers give Claude access to external services. Use Tool Search Tool to manage context overhead.
options = ClaudeAgentOptions(
mcp_servers={
"github": github_server,
"slack": slack_server,
"linear": linear_server,
},
allowed_tools=["Read", "Bash", "ToolSearch", "mcp__github__*"],
)
Pattern 4: Subagent Delegation
Best for: Complex multi-step workflows where different phases need different capabilities.
The parent agent has a broad view. It spawns subagents with scoped tools and skills for specific phases. Each subagent gets its own context window, preventing cross-contamination.
options = ClaudeAgentOptions(
allowed_tools=["Agent", "Read", "Bash"],
agents={
"security-reviewer": {
"description": "Reviews code for security issues",
"allowed_tools": ["Read", "Grep", "Glob"],
"model": "sonnet",
},
"test-writer": {
"description": "Writes unit tests for changed code",
"allowed_tools": ["Read", "Write", "Bash"],
}
}
)
Key Takeaways
-
Tools are for doing, skills are for knowing, MCPs are for connecting. Don't conflate them. Each solves a different problem.
-
Context window is your scarcest resource. Every tool definition, every skill loaded, every MCP server connected consumes tokens. More tokens consumed by overhead means less room for actual work — and measurably worse tool selection accuracy.
-
Scope aggressively. The best agent architectures load only what's needed for the current task. If you're doing git operations, don't load your analytics MCP. If you're writing docs, you probably don't need the database tools.
-
Prefer CLI tools over MCP for simple integrations. Running
gh,aws, orsentry-clithrough Bash adds zero persistent token overhead. Reserve MCP for services that need structured, multi-tool interactions. -
Skills compound over time. Every workflow you encode as a skill is a workflow you never have to explain again — across any conversation, any agent, any teammate using your project.
-
Use Tool Search Tool beyond ~15-20 tools. Once you're connecting multiple MCP servers, the token overhead and accuracy degradation make on-demand discovery essential.
-
Skills and tools are better together. A skill that teaches Claude your code review standards, combined with tools that let Claude actually read code and run tests, creates a specialist that's more than the sum of its parts.
Building agents is fundamentally about giving Claude the right capabilities (tools), the right knowledge (skills), and the right connections (MCPs) — then scoping each run to only what it needs. Get that balance right, and you get agents that are fast, accurate, and cost-effective. Get it wrong, and you're burning tokens on context overhead while Claude picks the wrong tool half the time.