Python SDK for programmatically interacting with Claude Code, enabling AI-powered automation workflows with support for bidirectional conversations, custom in-process tools, hooks, and fine-grained permission control
—
—
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
—
The risk profile of this skill
This plugin was archived by the owner on Jun 3, 2026
Reason: Retiring all tiles created prior to the transition to plugin support
MCP (Model Context Protocol) servers provide custom tools for Claude to use. Configure external MCP servers that run as separate processes or SDK MCP servers that run in-process within your Python application.
Union of all MCP server configuration types.
McpServerConfig = (
McpStdioServerConfig | McpSSEServerConfig | McpHttpServerConfig | McpSdkServerConfig
)
"""
Union of MCP server configuration types.
MCP servers can be configured in four ways:
- McpStdioServerConfig: External process communicating via stdio
- McpSSEServerConfig: Remote server using Server-Sent Events
- McpHttpServerConfig: Remote server using HTTP
- McpSdkServerConfig: In-process SDK server (recommended for Python)
Used in ClaudeAgentOptions.mcp_servers.
"""Configuration for MCP servers that run as external processes.
class McpStdioServerConfig(TypedDict):
"""
MCP stdio server configuration.
Configures an external MCP server that runs as a separate process and
communicates via stdin/stdout. This is the traditional MCP server mode.
Fields:
type: Server type marker (optional for backward compatibility)
command: Command to execute
args: Command line arguments
env: Environment variables
"""
type: NotRequired[Literal["stdio"]]
"""Server type marker.
Optional type field. Set to "stdio" for clarity, but can be omitted
for backward compatibility with older configurations.
"""
command: str
"""Command to execute.
The command to run the MCP server. Can be:
- An absolute path: "/usr/local/bin/my-mcp-server"
- A command in PATH: "npx"
- A Python script: "python"
Examples:
"npx"
"node"
"/usr/local/bin/mcp-server"
"python"
"""
args: NotRequired[list[str]]
"""Command arguments.
List of arguments to pass to the command. Order matters.
Examples:
["-y", "@modelcontextprotocol/server-filesystem", "/home/user/data"]
["mcp_server.py", "--config", "config.json"]
["/path/to/server.js"]
"""
env: NotRequired[dict[str, str]]
"""Environment variables.
Environment variables to set for the server process. Merged with
the current process environment.
Example:
{"API_KEY": "secret", "DEBUG": "true"}
"""Configuration for MCP servers using Server-Sent Events.
class McpSSEServerConfig(TypedDict):
"""
MCP SSE server configuration.
Configures a remote MCP server that uses Server-Sent Events (SSE)
for communication. Useful for remote or cloud-hosted MCP servers.
Fields:
type: Must be "sse"
url: Server URL
headers: Optional HTTP headers
"""
type: Literal["sse"]
"""Server type marker.
Must be "sse" to indicate SSE transport.
"""
url: str
"""Server URL.
The full URL of the SSE endpoint.
Example:
"https://mcp.example.com/sse"
"http://localhost:8080/events"
"""
headers: NotRequired[dict[str, str]]
"""HTTP headers.
Optional headers to include in the SSE connection request.
Useful for authentication.
Example:
{"Authorization": "Bearer token123"}
"""Configuration for MCP servers using HTTP.
class McpHttpServerConfig(TypedDict):
"""
MCP HTTP server configuration.
Configures a remote MCP server that uses HTTP for communication.
Fields:
type: Must be "http"
url: Server URL
headers: Optional HTTP headers
"""
type: Literal["http"]
"""Server type marker.
Must be "http" to indicate HTTP transport.
"""
url: str
"""Server URL.
The base URL of the HTTP server.
Example:
"https://mcp.example.com/api"
"http://localhost:3000"
"""
headers: NotRequired[dict[str, str]]
"""HTTP headers.
Optional headers to include in HTTP requests.
Useful for authentication and API keys.
Example:
{"X-API-Key": "secret", "Content-Type": "application/json"}
"""Configuration for in-process SDK MCP servers.
class McpSdkServerConfig(TypedDict):
"""
SDK MCP server configuration.
Configures an in-process MCP server created with create_sdk_mcp_server().
These servers run within your Python application for better performance.
Fields:
type: Must be "sdk"
name: Server name
instance: Server instance
"""
type: Literal["sdk"]
"""Server type marker.
Must be "sdk" to indicate an SDK server.
"""
name: str
"""Server name.
Unique identifier for this server. Used in logging and debugging.
"""
instance: "McpServer"
"""Server instance.
The MCP server instance created by create_sdk_mcp_server().
This is an actual mcp.server.Server object.
"""from claude_agent_sdk import (
tool, create_sdk_mcp_server, ClaudeAgentOptions, query
)
# Define tools
@tool("greet", "Greet a user", {"name": str})
async def greet(args):
return {"content": [{"type": "text", "text": f"Hello, {args['name']}!"}]}
@tool("calculate", "Do math", {"expression": str})
async def calculate(args):
result = eval(args["expression"]) # Use safely in production!
return {"content": [{"type": "text", "text": f"Result: {result}"}]}
# Create SDK server
server = create_sdk_mcp_server("mytools", tools=[greet, calculate])
# Use in options
options = ClaudeAgentOptions(
mcp_servers={"mytools": server},
allowed_tools=["greet", "calculate"]
)
async for msg in query(prompt="Greet Alice and calculate 2+2", options=options):
print(msg)from claude_agent_sdk import ClaudeAgentOptions, query
# Filesystem server using npx
filesystem_server = {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/documents"]
}
options = ClaudeAgentOptions(
mcp_servers={"filesystem": filesystem_server}
)
async for msg in query(prompt="List files in my documents", options=options):
print(msg)from claude_agent_sdk import ClaudeAgentOptions, query
# Python MCP server
python_server = {
"type": "stdio",
"command": "python",
"args": ["/path/to/my_mcp_server.py"],
"env": {
"SERVER_MODE": "production",
"API_KEY": "secret"
}
}
options = ClaudeAgentOptions(
mcp_servers={"custom": python_server}
)
async for msg in query(prompt="Use custom server", options=options):
print(msg)from claude_agent_sdk import ClaudeAgentOptions, query
# Node.js MCP server
node_server = {
"command": "node", # 'type' is optional for stdio
"args": ["/path/to/server.js"],
"env": {"DEBUG": "mcp:*"}
}
options = ClaudeAgentOptions(
mcp_servers={"nodeserver": node_server}
)
async for msg in query(prompt="Query node server", options=options):
print(msg)from claude_agent_sdk import ClaudeAgentOptions, query
# Remote SSE server
sse_server = {
"type": "sse",
"url": "https://mcp.example.com/sse",
"headers": {
"Authorization": "Bearer your-token-here"
}
}
options = ClaudeAgentOptions(
mcp_servers={"remote": sse_server}
)
async for msg in query(prompt="Use remote server", options=options):
print(msg)from claude_agent_sdk import ClaudeAgentOptions, query
# HTTP MCP server
http_server = {
"type": "http",
"url": "https://api.example.com/mcp",
"headers": {
"X-API-Key": "your-api-key",
"Content-Type": "application/json"
}
}
options = ClaudeAgentOptions(
mcp_servers={"api": http_server}
)
async for msg in query(prompt="Use HTTP API", options=options):
print(msg)from claude_agent_sdk import (
tool, create_sdk_mcp_server, ClaudeAgentOptions, query
)
# SDK server for custom tools
@tool("custom_tool", "My custom tool", {"param": str})
async def custom_tool(args):
return {"content": [{"type": "text", "text": f"Got: {args['param']}"}]}
sdk_server = create_sdk_mcp_server("custom", tools=[custom_tool])
# External filesystem server
filesystem_server = {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/data"]
}
# External database server
db_server = {
"command": "python",
"args": ["/path/to/db_server.py"],
"env": {"DATABASE_URL": "postgresql://localhost/mydb"}
}
# Configure all servers
options = ClaudeAgentOptions(
mcp_servers={
"custom": sdk_server,
"files": filesystem_server,
"database": db_server
}
)
async for msg in query(prompt="Use all servers", options=options):
print(msg)from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query
# Point to MCP config file
config_path = Path.home() / ".config" / "claude" / "mcp.json"
options = ClaudeAgentOptions(
mcp_servers=config_path # Can be string or Path
)
async for msg in query(prompt="Use configured servers", options=options):
print(msg)import os
from claude_agent_sdk import ClaudeAgentOptions, query
# Different config for dev/prod
environment = os.getenv("ENVIRONMENT", "development")
if environment == "production":
servers = {
"api": {
"type": "http",
"url": "https://prod-api.example.com/mcp",
"headers": {"X-API-Key": os.getenv("PROD_API_KEY")}
}
}
else:
servers = {
"api": {
"command": "python",
"args": ["dev_server.py"],
"env": {"DEBUG": "true"}
}
}
options = ClaudeAgentOptions(mcp_servers=servers)
async for msg in query(prompt="Query API", options=options):
print(msg)import os
from claude_agent_sdk import ClaudeAgentOptions, query
# Server that needs many environment variables
server = {
"command": "python",
"args": ["mcp_server.py"],
"env": {
"DATABASE_URL": os.getenv("DATABASE_URL"),
"REDIS_URL": os.getenv("REDIS_URL"),
"API_KEY": os.getenv("API_KEY"),
"LOG_LEVEL": "debug",
"CACHE_DIR": "/tmp/mcp-cache",
"MAX_CONNECTIONS": "10"
}
}
options = ClaudeAgentOptions(
mcp_servers={"data": server}
)
async for msg in query(prompt="Query database", options=options):
print(msg)from claude_agent_sdk import (
tool, create_sdk_mcp_server, ClaudeAgentOptions, query
)
# Fast in-process tools for simple operations
@tool("add", "Add numbers", {"a": float, "b": float})
async def add(args):
result = args["a"] + args["b"]
return {"content": [{"type": "text", "text": f"Sum: {result}"}]}
math_server = create_sdk_mcp_server("math", tools=[add])
# External server for file system access
filesystem_server = {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/project"]
}
options = ClaudeAgentOptions(
mcp_servers={
"math": math_server, # In-process, fast
"files": filesystem_server # External, isolated
}
)
async for msg in query(prompt="Calculate sum and save to file", options=options):
print(msg)from claude_agent_sdk import ClaudeAgentOptions, query
# Server that should run in specific directory
server = {
"command": "python",
"args": ["./server.py"], # Relative path
"env": {
"WORKSPACE": "/home/user/project"
}
}
# Note: The server process will inherit the cwd from ClaudeAgentOptions
options = ClaudeAgentOptions(
mcp_servers={"local": server},
cwd="/home/user/project" # Sets working directory for CLI and servers
)
async for msg in query(prompt="Use local server", options=options):
print(msg)import os
from claude_agent_sdk import ClaudeAgentOptions, query
# SSE server with authentication
server = {
"type": "sse",
"url": "https://mcp-prod.example.com/stream",
"headers": {
"Authorization": f"Bearer {os.getenv('MCP_TOKEN')}",
"X-Client-ID": "python-sdk",
"X-Client-Version": "0.1.0"
}
}
options = ClaudeAgentOptions(
mcp_servers={"prod": server}
)
async for msg in query(prompt="Use production server", options=options):
print(msg)from claude_agent_sdk import (
tool, create_sdk_mcp_server, ClaudeAgentOptions, query
)
import os
# Create appropriate server based on environment
if os.getenv("ENV") == "production":
# Production: Use external server
server = {
"type": "http",
"url": "https://api.example.com/mcp",
"headers": {"X-API-Key": os.getenv("API_KEY")}
}
else:
# Development: Use SDK server
@tool("dev_tool", "Development tool", {"input": str})
async def dev_tool(args):
return {"content": [{"type": "text", "text": f"Dev: {args['input']}"}]}
server = create_sdk_mcp_server("dev", tools=[dev_tool])
options = ClaudeAgentOptions(
mcp_servers={"main": server}
)
async for msg in query(prompt="Use appropriate server", options=options):
print(msg)# Example: ~/.config/claude/mcp.json
"""
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/data"]
},
"database": {
"command": "python",
"args": ["/path/to/db_server.py"],
"env": {
"DATABASE_URL": "postgresql://localhost/mydb"
}
},
"remote": {
"type": "sse",
"url": "https://mcp.example.com/sse",
"headers": {
"Authorization": "Bearer token"
}
}
}
}
"""
from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query
# Load from standard config location
config_path = Path.home() / ".config" / "claude" / "mcp.json"
options = ClaudeAgentOptions(
mcp_servers=str(config_path)
)
async for msg in query(prompt="Use configured servers", options=options):
print(msg)from claude_agent_sdk import ClaudeAgentOptions, query
# Configure server with extra args for timeout/retry
server = {
"command": "python",
"args": [
"mcp_server.py",
"--timeout", "30",
"--retry", "3"
],
"env": {
"REQUEST_TIMEOUT": "30"
}
}
options = ClaudeAgentOptions(
mcp_servers={"reliable": server}
)
async for msg in query(prompt="Use reliable server", options=options):
print(msg)docs