Extending Claude Code: Your First MCP Server and Subagent
Claude Code ships with a fixed set of built-in tools — but you can extend it. Add a public MCP server in one command to give it new capabilities, then create a subagent to delegate focused work in an isolated context. This is the hands-on bridge from user to power user.
You have shipped a project with Claude Code. You know the agent loop, the slash commands, and the debugging workflow. Out of the box, Claude Code already has a strong set of built-in tools — it can read and write files, run shell commands, search the web, and edit code. But the moment your work needs a capability it does not ship with, or you want to delegate a focused slice of a task, you hit a ceiling.
This lesson is how you break through it. There are two levers, and you will use both by the end:
- MCP servers extend what Claude Code can do — they plug new tools (a filesystem server, a database connector, an HTTP client) into the agent in a single command.
- Subagents extend how Claude Code delegates — they let the main agent hand a scoped task to a named helper that reasons in its own isolated context.
By the end of this lesson you will have run claude mcp add to give Claude Code a real new capability and used it, and created a subagent via .claude/agents/ and dispatched it. This is the single biggest step from Claude Code user to Claude Code power user.
Part 1: What an MCP Server Actually Is
MCP stands for Model Context Protocol. The name sounds heavy; the idea is simple. An MCP server is a small, separate program that exposes a set of tools over a standard wire protocol. Claude Code is an MCP client — it knows how to talk to any MCP server. So instead of every capability having to be baked into Claude Code itself, anyone can write a server, and you can plug it in.
The filesystem server gives the agent scoped read/write access to a directory you choose. A Postgres server lets it query a database. There are dozens of public servers, and the protocol is the same for all of them — which is exactly why one command can wire any of them in.
Notice what you did not do in that flow: you never wrote the filesystem logic. The server already implements it. You registered a process; Claude Code did the handshake; the model gained a tool. That is the leverage of MCP — you are composing capabilities, not building them.
Part 1 — Hands On: Add a Public MCP Server and Use It
You will add the official filesystem server, which gives Claude Code scoped read/write access to a directory you choose.
Open a terminal in any project and run:
claude mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem /tmp
Read the command carefully — the structure matters:
filesystemis the name you are giving this server (you will see it in/mcp).- Everything after
--is the command Claude Code runs to start the server:npx -y @modelcontextprotocol/server-filesystem /tmp. npx -ydownloads and runs the server package without a permanent install./tmpis a required argument — the server is scoped to this directory only and cannot reach outside it. You can replace/tmpwith any path you want the server to access.
Now start a Claude Code session and confirm the server connected:
claude
Inside the session, run:
/mcp
You should see filesystem listed as a connected server with its tools available (typically read_file, write_file, list_directory, and others). If it shows as failed, the most common cause is that npx could not reach the package — check your network and that Node is installed.
Now use it. Ask Claude to do something with the scoped directory:
Use the filesystem tool to create a file at /tmp/mcp-test.txt
with the content "MCP is working." Then read it back and confirm.
Watch the tool call happen. Claude emits a call to the filesystem server's tool, you approve it, the server writes the file, and Claude reads it back to confirm. That round trip is the entire point: the model reached outside itself, through a tool you added, to do real file work in a scoped directory.
Part 2: What a Subagent Is
An MCP server gives the agent new tools. A subagent gives the agent a new way to use tools — by delegating.
A subagent is a named role you define once. It has three things: a description (so the main agent knows when to dispatch it), a system prompt (its specialized instructions), and a tools allow-list (the only tools it is permitted to use). When the main agent decides a task fits a subagent, it dispatches that task — and the subagent runs in its own fresh context window, does the work, and returns only its result.
That context isolation is the feature. Consider asking Claude to "review this diff, write tests for the new function, and draft a README section." Done in one context, the diff dump, the test scaffolding, and the doc draft all pile into the same window and start crowding each other out. Split across three subagents, each one reasons cleanly and hands back a tight result.
The tools allow-list is the "getting out of their way" part done safely. A subagent scoped to Read, Grep cannot write a file — not because it chooses not to, but because the tool is not in its world. That is least privilege, the same discipline you apply to settings.json permissions, applied to delegation.
Part 2 — Hands On: Create a Subagent and Dispatch It
Subagents are defined by Markdown files with YAML frontmatter stored under .claude/agents/ in your project. Create that directory and the file directly:
mkdir -p .claude/agents
Create .claude/agents/code-reviewer.md with this content:
---
name: code-reviewer
description: Reviews the current git diff for bugs, missing error handling, and style issues. Use after writing or editing code, before committing.
tools: Read, Grep, Bash
---
You are a focused code reviewer. Read the current git diff. Report concrete issues only — bugs, missing error handling, unsafe patterns — with file and line. Do not rewrite the code; just flag what needs attention. Be concise.
The YAML frontmatter is what makes this a subagent: name is how the main agent identifies it, description is how it decides when to dispatch it, and tools is the allow-list — the hard ceiling of what this subagent can use, written as a single comma-separated line. (If you omit the tools field entirely, the subagent inherits all tools — so when you mean to restrict it, make sure the field is present.) The body is its system prompt.
Restart your Claude Code session (or start a fresh one) so it picks up the new file:
claude
Now dispatch it. Make a small code change (or have Claude make one), then ask:
Use the code-reviewer subagent to review my current changes.
Watch what happens: Claude dispatches the code-reviewer, which spins up in its own context, runs git diff and reads the changed files, and returns a focused list of findings. The main session never filled up with the raw diff — it got back a clean review. You delegated, and you stayed in command.
When to Reach for Which
These two levers solve different problems, and knowing which to reach for is the skill:
Reach for an MCP server when Claude Code lacks a capability. It cannot read your database, hit an internal API, or fetch a page it does not have a tool for. An MCP server adds that tool. The question is "what can it do?"
Reach for a subagent when you want to delegate a focused slice of work in a clean context. The capability already exists; you just want it run in isolation so the main context stays sharp, or run in parallel with other slices. The question is "how should this work be partitioned?"
They compose. A subagent can be given access to MCP-server tools in its allow-list — a researcher subagent scoped to the fetch tool, dispatched to gather sources while the main agent keeps planning. Capability plus delegation, working together.
Lesson Drill
Do both halves end to end in one session:
claude mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem /tmp, then/mcpto confirm it connected.- Ask Claude to create and read back a file in
/tmpusing the filesystem tool. Watch the tool call. - Create
.claude/agents/code-reviewer.mdwith the YAML frontmatter shown above, restart your session, then dispatch the subagent to review a small code change. - Open
.claude/agents/code-reviewer.mdand tweak one line of its system prompt, then re-dispatch to see the change take effect.
Fifteen minutes, and you will have permanently leveled up how you use Claude Code.
Build Challenge
Before you move on, lock in the mental model by building the config layer yourself. Both an MCP server entry and a subagent definition are just structured config — and config that is not validated is a silent landmine. Assemble and validate both:
Bottom Line
Claude Code is extensible along two axes. MCP servers add capability: claude mcp add <name> -- <command> registers a separate server process, Claude Code handshakes with it, and the model gains its tools — you compose capabilities you never had to build. Subagents add scoped delegation: a .claude/agents/<name>.md file defines a named role with its own system prompt and a tools allow-list, and the main agent dispatches focused work to it in an isolated context, keeping the orchestrator's window clean. Reach for MCP when a capability is missing; reach for a subagent when work should be partitioned. Master both and you stop being a Claude Code user and start being a Claude Code operator.
Next: you have the core workflow and now the extension model — the natural continuation is the craft of communicating with the agent itself, which the Prompt Engineering track picks up.