MCP & Skills

Claude Code uses two complementary extension mechanisms: the Model Context Protocol (MCP) for connecting external tool servers and data sources, and the Skills system for reusable, composable slash command scripts.

What is MCP?

The Model Context Protocol is an open standard for connecting AI models to external tools and data sources. It defines a client-server architecture where:

  • MCP Servers expose tools, resources, and prompts over a standardized protocol (JSON-RPC over stdio, SSE, or WebSocket).
  • MCP Clients (Claude Code) discover and invoke these capabilities on behalf of the model.
  • Tools, resources, and prompts are all first-class protocol concepts, enabling rich integrations without custom code in the client.

From Claude Code's perspective, an MCP tool is treated identically to a built-in tool at runtime, it goes through the same permission system, progress reporting, and rendering pipeline. The difference is that its call() implementation delegates to the MCP server via JSON-RPC.

How MCP Integrates

The MCP integration lives in services/mcp/. The key files are:

FilePurpose
client.tsMCP SDK client wrapper; manages connection lifecycle
MCPConnectionManager.tsxReact component managing connection state across all configured servers
types.tsTypeScript types: MCPServerConnection, ServerResource, config types
config.tsLoad and merge MCP server configs from settings files
auth.tsOAuth flow for MCP servers that require authentication
channelAllowlist.tsSecurity: origin allowlist for bridge connections
channelPermissions.tsPer-channel permission rules for bridge-connected servers
normalization.tsNormalize MCP tool names and schemas to internal format
officialRegistry.tsPrefetch official MCP server registry from Anthropic
InProcessTransport.tsFor MCP servers that run in-process (no subprocess)

Connection Lifecycle

1 · CONFIG LOADING Read ~/.claude/settings.json + project .claude/settings.json · merge mcpServers config 2 · SERVER LAUNCH For each configured server: stdio: spawn subprocess with command + args sse: connect to HTTP endpoint 3 · CAPABILITY DISCOVERY MCP initialize handshake tools/list → collect tool schemas resources/list · prompts/list 4 · TOOL REGISTRATION Create MCPTool wrappers: name = "mcp__serverName__toolName" call() → JSON-RPC tools/call · inputJSONSchema from server 5 · MCP tools included in next API request's tools array → exposed to Claude

MCP Server Configuration

MCP servers are configured in ~/.claude/settings.json (global) or .claude/settings.json (project-scoped):

// ~/.claude/settings.json - MCP server configuration
{
  "mcpServers": {
    "filesystem": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"],
      "env": {}
    },
    "github": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
      }
    },
    "my-custom-api": {
      "type": "sse",
      "url": "https://my-company.internal/mcp",
      "headers": {
        "Authorization": "Bearer ${MY_API_TOKEN}"
      }
    }
  }
}

Environment variable interpolation (${VAR_NAME}) is supported in MCP server configs via envExpansion.ts. This allows storing credentials in environment variables rather than hardcoding them in settings files, which is important if your settings are committed to version control.

MCP Resources

MCP servers can expose resources in addition to tools. Resources are read-only data sources (files, database records, API responses) that Claude can access via the ListMcpResourcesTool and ReadMcpResourceTool built-in tools:

// How Claude accesses MCP resources:
// 1. Discover available resources
// (uses ListMcpResourcesTool)
// → { uri: "file:///home/user/data.csv", name: "Sales Data", mimeType: "text/csv" }

// 2. Read a specific resource by URI
// (uses ReadMcpResourceTool)
// → Contents of the resource as text or base64-encoded binary

// resources are different from tools - they are accessed directly
// by URI without calling any server-side logic beyond the fetch itself

MCP Authentication

MCP servers that require authentication (e.g., a company's internal API) can implement the OAuth 2.0 flow via the MCP protocol's elicitation mechanism. When Claude Code encounters a tool call that returns error code -32042 (authentication required), it launches the OAuth flow:

  1. The MCP server returns -32042 with an authorization URL.
  2. Claude Code opens the URL in the user's browser.
  3. After OAuth completion, the token is stored in the keychain.
  4. Future calls include the token in the MCP connection headers.

The McpAuthTool and elicitationHandler.ts implement this flow. In print/SDK mode, elicitations are surfaced as structured events rather than UI dialogs.

The Skills System

Skills are the scripting layer of Claude Code. A skill is a markdown file (with optional YAML frontmatter) that defines a reusable slash command. Skills live in ~/.claude/skills/ (global), .claude/skills/ (project), or are bundled with the tool itself (src/skills/bundled/).

When a user types /commit, the skill system:

  1. Looks up the skill file matching "commit".
  2. Reads and parses the skill's markdown template.
  3. Expands any template variables ($ARGUMENTS, $CWD, etc.).
  4. Submits the expanded prompt as a user message to the query pipeline.

Skill File Format

---
# skills/commit.md - skill frontmatter
name: commit
description: Create a git commit with a smart message
aliases:
  - c
  - git-commit
# Arguments this skill accepts (for autocomplete and help)
arguments:
  - name: message
    description: Optional commit message override
    required: false
---

Review the git diff and create a well-structured commit message.

Focus on the "why" not the "what". Format as:

<type>(<scope>): <short description>

<body if needed>

Then run: `git commit -m "..."` with the generated message.

$ARGUMENTS

Template Variables

VariableValue
$ARGUMENTSAny text the user typed after the slash command name
$CWDCurrent working directory path
$SELECTIONCurrently selected text (in IDE integrations)

Bundled Skills

Claude Code ships with a set of bundled skills in src/skills/bundled/. These are compiled into the binary and available without any configuration:

SkillDescription
batch.tsRun multiple tasks in parallel as separate subagent calls.
claudeApi.tsIntegration helpers for building apps with the Claude API.
commit.tsSmart git commit with AI-generated commit message following conventional commits.
index.tsSkill registry/index; lists all available skills.
keybindings.tsHelper for customizing Claude Code keyboard bindings.
loop.tsRun a prompt or skill on a recurring interval (polling pattern).
loremIpsum.tsGenerate placeholder text, useful for testing layouts.
remember.tsSave facts or instructions to persistent memory.
scheduleRemoteAgents.tsCreate, list, and manage scheduled remote agent triggers.
simplify.tsReview changed code for quality and refactoring opportunities.
skillify.tsConvert a prompt or workflow into a reusable skill file.
stuck.tsGet unstuck: analyze what's blocking progress and suggest approaches.
updateConfig.tsConfigure Claude Code settings via natural language description.
verify.tsVerify a claim or implementation against tests and specifications.
verifyContent.tsVerify that content (docs, comments) matches the actual code behavior.
claudeApiContent.tsGenerate content using the Claude API with streaming.
claudeInChrome.tsIntegration with Claude's Chrome extension.
debug.tsStep through a debugging workflow systematically.

Writing Your Own Skill

Creating a custom skill is straightforward. Here is a complete example of a skill that performs a security review of changed files:

---
name: security-check
description: Review changed files for security vulnerabilities
aliases:
  - sec
  - security
arguments:
  - name: files
    description: Specific files to check (defaults to git diff)
    required: false
---

Perform a security review of the following changes.

Check for:
1. **Injection vulnerabilities**, SQL injection, shell injection, XSS
2. **Authentication issues**, missing auth checks, JWT misuse
3. **Secrets in code**, API keys, passwords, tokens hardcoded
4. **Dependency vulnerabilities**, outdated packages with CVEs
5. **Input validation**, missing sanitization of user inputs
6. **Path traversal**, unvalidated file paths
7. **Cryptographic issues**, weak algorithms, improper key handling

For each finding, rate severity (LOW/MEDIUM/HIGH/CRITICAL) and suggest a fix.

$ARGUMENTS

Save this as ~/.claude/skills/security-check.md (global) or .claude/skills/security-check.md (project-only). It will be available as /security-check (or /sec via the alias) in any Claude Code session.

Skill Discovery and Loading

Skills are loaded by skills/loadSkillsDir.ts, which scans skill directories and builds a registry. The bundledSkills.ts file exports the pre-compiled bundled skills. At runtime, the skill registry is merged from all sources: user global, project-local, and bundled.

When the EXPERIMENTAL_SKILL_SEARCH feature flag is enabled, services/skillSearch/prefetch.js runs at turn start to pre-index the skills directory for semantic search. This allows the model to discover and invoke skills based on intent rather than exact command names.

MCP-Based Skills

The skills/mcpSkillBuilders.ts file enables skills to be exposed as MCP tools. This means a skill defined in your ~/.claude/skills/ directory can be made available to any MCP client, not just Claude Code's own REPL. This is the bridge between the simple markdown-skill format and the full MCP ecosystem.

// skills/mcpSkillBuilders.ts - exposes skills as MCP tools
export function buildMCPSkillTool(skill: SkillDefinition): MCPToolDefinition {
  return {
    name: skill.name,
    description: skill.description,
    inputSchema: {
      type: 'object',
      properties: {
        arguments: {
          type: 'string',
          description: 'Arguments to pass to the skill',
        },
      },
    },
    // When called, expands the skill template and submits it
    handler: async ({ arguments: args }) => {
      const expanded = expandSkillTemplate(skill.content, args)
      return { content: expanded }
    },
  }
}

Skills are a lightweight alternative to full MCP server development for many use cases. If you need to give Claude Code a repeatable workflow (code review, deployment checklist, commit message format), a skill file is often the right tool. Only build a full MCP server when you need real-time data access, persistent state, or tools that non-Claude clients also need.

MCP vs. Skills: When to Use Each

Consideration Use MCP Server Use a Skill
Real-time data access ✓ Database, APIs, live data - Static templates only
Complex server logic ✓ Computation, transformations - Delegates to Claude
Other AI clients ✓ Works with any MCP client - Claude Code only
Setup complexity High (Node.js server, deployment) Low (single markdown file)
Reusable prompts - Overkill ✓ Perfect fit
Team sharing ✓ Via server URL ✓ Via project .claude/skills/
Version control ✓ Server source code ✓ Markdown files in repo

Frequently Asked Questions

What is MCP (Model Context Protocol)?
MCP allows seamless connection to external data sources and custom local toolchains without hardcoding them into the main binary application.
How do skills differ from tools?
Skills are typically declarative markdown or instruction sets that map to a sequence of actions, whereas tools are hardcoded, native TypeScript functionality.
Can I build my own MCP server?
Yes! You can serve endpoints that the agent connects to natively for extending its capabilities and bridging it to internal tools or databases.
How are skills parsed?
They are loaded from the file structure and interpreted as dynamic tool expansions, allowing Claude to read and execute the unique workflows described within.
Are skills shared globally?
You can have workspace-specific skill directories and global tools, making it easy to specialize the agent for a specific project without muddying your global CLI setup.