From plugin-dev
Guides integration of Model Context Protocol (MCP) servers into Claude Code plugins via .mcp.json or plugin.json for external service tools, with scope management (local, project, user).
npx claudepluginhub sjnims/plugin-dev --plugin plugin-devThis skill uses the workspace's default tool permissions.
Model Context Protocol (MCP) enables Claude Code plugins to integrate with external services and APIs by providing structured tool access. Use MCP integration to expose external service capabilities as tools within Claude Code.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Model Context Protocol (MCP) enables Claude Code plugins to integrate with external services and APIs by providing structured tool access. Use MCP integration to expose external service capabilities as tools within Claude Code.
Key capabilities:
Plugins can bundle MCP servers in two ways:
Create .mcp.json at plugin root:
{
"database-tools": {
"command": "${CLAUDE_PLUGIN_ROOT}/servers/db-server",
"args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"],
"env": {
"DB_URL": "${DB_URL}"
}
}
}
Benefits:
Add mcpServers field to plugin.json:
{
"name": "my-plugin",
"version": "1.0.0",
"mcpServers": {
"plugin-api": {
"command": "${CLAUDE_PLUGIN_ROOT}/servers/api-server",
"args": ["--port", "8080"]
}
}
}
Benefits:
MCP server configurations follow scope precedence: Local > Project > User.
| Scope | Storage | Sharing | Best For |
|---|---|---|---|
| Local | ~/.claude.json (project path) | Private, current project | Experimental, sensitive credentials |
| Project | .mcp.json in project root | Via version control | Team-shared, project-specific |
| User | ~/.claude.json (global) | All projects | Personal utilities, cross-project |
Plugin-bundled MCP servers (via .mcp.json or inline in plugin.json) auto-start when the plugin is enabled. They interact with user/project MCP configs — if a user has a server with the same name, scope precedence determines which loads.
Find existing MCP servers for your plugin using PulseMCP, the comprehensive MCP server directory with 6,800+ servers.
Discovery workflow:
https://www.pulsemcp.com/servers?q=[keyword].mcp.json configuration based on server typeSee references/server-discovery.md for detailed search instructions, URL patterns, and curated server recommendations by category.
Execute local MCP servers as child processes. Best for local tools and custom servers.
Configuration:
{
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/allowed/path"],
"env": {
"LOG_LEVEL": "debug"
}
}
}
Use cases:
Process management:
Connect to hosted MCP servers with OAuth support. Best for cloud services.
Configuration:
{
"asana": {
"type": "sse",
"url": "https://mcp.asana.com/sse"
}
}
Use cases:
Authentication:
Connect to RESTful MCP servers with token authentication.
Configuration:
{
"api-service": {
"type": "http",
"url": "https://api.example.com/mcp",
"headers": {
"Authorization": "Bearer ${API_TOKEN}",
"X-Custom-Header": "value"
}
}
}
Use cases:
Connect to WebSocket MCP servers for real-time bidirectional communication.
Configuration:
{
"realtime-service": {
"type": "ws",
"url": "wss://mcp.example.com/ws",
"headers": {
"Authorization": "Bearer ${TOKEN}"
}
}
}
Use cases:
All MCP configurations support environment variable substitution:
${CLAUDE_PLUGIN_ROOT} - Plugin directory (always use for portability):
{
"command": "${CLAUDE_PLUGIN_ROOT}/servers/my-server"
}
User environment variables - From user's shell:
{
"env": {
"API_KEY": "${MY_API_KEY}",
"DATABASE_URL": "${DB_URL}"
}
}
Env vars support fallback values: ${VAR:-default_value}. If VAR is unset, default_value is used. Supported in command, args, env, url, and headers fields.
Best practice: Document all required environment variables in plugin README.
When MCP servers provide tools, they're automatically prefixed:
Format: mcp__plugin_<plugin-name>_<server-name>__<tool-name>
Example:
asanaasanacreate_taskmcp__plugin_asana_asana__asana_create_taskMCP servers can expose resources that Claude can access using the @ syntax:
@server-name:protocol://path
Examples:
@filesystem:file:///Users/me/project/README.md
@database:postgres://localhost/mydb/users
@github:https://github.com/user/repo
Reference resources directly in your prompts:
Look at @filesystem:file:///path/to/config.json and suggest improvements
Claude will fetch the resource content and include it in context.
MCP servers can expose prompts that appear as slash commands in Claude Code:
Format: /mcp__servername__promptname
Example:
github exposes prompt create-pr/mcp__github__create-prMCP prompts appear alongside regular commands in the / menu. They accept arguments and execute the server's prompt template with Claude. This enables MCP servers to provide guided workflows beyond simple tool calls.
Plugin design note: If your MCP server exposes prompts, document their names and expected arguments in your plugin README so users can discover them.
Plugin-provided MCP prompts: If your plugin bundles an MCP server, that server can expose prompts that automatically become slash commands for users. This provides guided workflows beyond simple tool calls — for example, a /mcp__myserver__setup-project prompt that walks users through project configuration.
For MCP servers with many tools, use Tool Search to find relevant tools:
When to use:
How it works:
Tool Search activates automatically when MCP servers collectively provide more tools than fit efficiently in Claude's context window (default threshold: 10% of context). Instead of loading all tool descriptions upfront, Claude searches for relevant tools on-demand.
Plugin design implications:
ENABLE_TOOL_SEARCH=auto:5 (custom 5% threshold) or ENABLE_TOOL_SEARCH=false (disable)This feature is automatic - just ask Claude about available tools or describe what you want to do.
Pre-allow specific MCP tools in command frontmatter:
---
allowed-tools: mcp__plugin_asana_asana__asana_create_task, mcp__plugin_asana_asana__asana_search_tasks
---
Wildcard (use sparingly):
---
allowed-tools: mcp__plugin_asana_asana__*
---
Best practice: Pre-allow specific tools, not wildcards, for security.
Automatic startup:
Lifecycle:
mcp__plugin_...__...Viewing servers:
Use /mcp command to see all servers including plugin-provided ones.
OAuth handled automatically by Claude Code:
{
"type": "sse",
"url": "https://mcp.example.com/sse"
}
User authenticates in browser on first use. No additional configuration needed.
Static or environment variable tokens:
{
"type": "http",
"url": "https://api.example.com",
"headers": {
"Authorization": "Bearer ${API_TOKEN}"
}
}
Document required environment variables in README.
Pass configuration to MCP server:
{
"command": "python",
"args": ["-m", "my_mcp_server"],
"env": {
"DATABASE_URL": "${DB_URL}",
"API_KEY": "${API_KEY}",
"LOG_LEVEL": "info"
}
}
Commands use MCP tools with user interaction:
# Command: create-item.md
---
allowed-tools: `mcp__plugin_name_server__create_item`
Steps:
1. Gather item details from user
2. Use `mcp__plugin_name_server__create_item`
3. Confirm creation
Use for: Adding validation or preprocessing before MCP calls.
Agents use MCP tools autonomously:
# Agent: data-analyzer.md
Analysis Process:
1. Query data via `mcp__plugin_db_server__query`
2. Process and analyze results
3. Generate insights report
Use for: Multi-step MCP workflows without user interaction.
Integrate multiple MCP servers:
{
"github": {
"type": "sse",
"url": "https://mcp.github.com/sse"
},
"jira": {
"type": "sse",
"url": "https://mcp.jira.com/sse"
}
}
Use for: Workflows spanning multiple services.
Always use secure connections:
✅ "url": "https://mcp.example.com/sse"
❌ "url": "http://mcp.example.com/sse"
DO:
DON'T:
Pre-allow only necessary MCP tools:
✅ allowed-tools: `mcp__plugin_api_server__read_data`, `mcp__plugin_api_server__create_item`
❌ allowed-tools: mcp__plugin_api_server__*
Organizations can control MCP server access through managed settings.
Place managed-mcp.json at the system-wide managed settings path for exclusive control over MCP server configuration. Alternatively, use allow/deny lists in managed settings:
{
"allowedMcpServers": [
{ "serverName": "github" },
{ "serverCommand": ["npx", "-y", "@company/mcp-server"] },
{ "serverUrl": "https://mcp.company.com/*" }
],
"deniedMcpServers": [
{ "serverName": "untrusted-server" }
]
}
Matcher types:
serverName — Match by configured server nameserverCommand — Match by exact command arrayserverUrl — Match by URL pattern (supports * wildcards)These settings are configured by administrators and cannot be overridden by users or plugins.
Claude Code can itself act as an MCP server, exposing its capabilities to other tools:
claude mcp serve
This enables other MCP-compatible clients to use Claude Code's tools. Useful for building tool chains where Claude Code is one component.
Users who already have MCP servers configured in Claude Desktop can import them:
claude mcp add-from-claude-desktop
This copies MCP server configurations from Claude Desktop into Claude Code. Plugin developers should note that users may already have servers configured this way — avoid name conflicts with commonly used server names.
MCP servers can notify Claude Code when their available tools change at runtime using the list_changed notification. This enables servers that dynamically add or remove tools based on context (e.g., loading project-specific tools after initialization). Claude Code automatically re-discovers tools when list_changed fires, without requiring a restart.
Plugin design note: If your MCP server's available tools depend on runtime state, implement list_changed to ensure Claude Code always has an up-to-date tool list.
MCP tool responses are subject to size limits:
MAX_MCP_OUTPUT_TOKENS environment variable to adjust the maximumDesign MCP tools to return concise, relevant data. Use pagination or filtering for large datasets.
Handle MCP server unavailability:
Handle failed MCP operations:
Validate MCP configuration:
MCP servers connect on-demand:
Batch similar requests when possible:
# Good: Single query with filters
tasks = search_tasks(project="X", assignee="me", limit=50)
# Avoid: Many individual queries
for id in task_ids:
task = get_task(id)
.mcp.json.claude-plugin/)/mcp to verify server appearsclaude --debug logs for connection issues/mcp outputFor testing and managing MCP servers during development:
# Add servers
claude mcp add --transport stdio <name> -- <command> [args...]
claude mcp add --transport http <name> <url>
claude mcp add --transport http <name> <url> --header "Authorization: Bearer token"
# Manage servers
claude mcp list # List configured servers
claude mcp get <name> # Show server details
claude mcp remove <name> # Remove a server
# Advanced
claude mcp add-json <name> '<json>' # Add from JSON config
claude mcp add-from-claude-desktop # Import from Claude Desktop
claude mcp reset-project-choices # Reset project MCP approval choices
Key flags: --scope (local/project/user), --env KEY=value, --callback-port (for OAuth).
claude --debug
Look for:
Server not connecting:
Tools not available:
/mcp to see available toolsAuthentication failing:
| Type | Transport | Best For | Auth |
|---|---|---|---|
| stdio | Process | Local tools, custom servers | Env vars |
| SSE | HTTP | Hosted services, cloud APIs | OAuth |
| HTTP | REST | API backends, token auth | Tokens |
| ws | WebSocket | Real-time, streaming | Tokens |
DO:
DON'T:
For detailed information, consult:
references/server-discovery.md - Find MCP servers using PulseMCP directoryreferences/server-types.md - Deep dive on each server typereferences/authentication.md - Authentication patterns and OAuthreferences/tool-usage.md - Using MCP tools in commands and agentsWorking examples in examples/:
stdio-server.json - Local stdio MCP serversse-server.json - Hosted SSE server with OAuthhttp-server.json - REST API with token authws-server.json - WebSocket server for real-time communicationclaude --debug and /mcp commandTo add MCP integration to a plugin:
.mcp.json at plugin root with configuration/mcp commandFocus on stdio for custom/local servers, SSE for hosted services with OAuth.