| title | MCP Integration Reference | ||||
|---|---|---|---|---|---|
| category | integration | ||||
| target_platform | linux | ||||
| audience | ai_agent | ||||
| keywords |
|
MCP (Model Context Protocol): Standard for connecting AI to external services
Provides: External tools, resources, prompts, sampling
Configuration: .mcp.json at plugin root
Capabilities:
- External tools (callable functions)
- Resources (accessible data)
- Prompts (templates)
- Sampling (AI completions)
Transport: stdin/stdout Use case: Local processes, npm packages Pros: Simple, universal Cons: One process per connection
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}Transport: HTTP streaming Use case: Remote services, cloud deployments Pros: Remote hosting, multiple clients Cons: Requires HTTP server
{
"mcpServers": {
"remote-service": {
"url": "https://api.example.com/mcp",
"headers": {
"Authorization": "Bearer ${API_TOKEN}"
}
}
}
}Transport: HTTP long-polling Use case: Firewall-friendly connections Pros: Standard HTTP, NAT-friendly Cons: More complex than stdio
{
"mcpServers": {
"api-server": {
"url": "http://localhost:8080/mcp",
"transport": "http"
}
}
}Location: .mcp.json at plugin root (not inside .claude-plugin/)
{
"server-name": {
"command": "node",
"args": ["dist/server.js"],
"env": {
"VARIABLE": "value"
}
}
}For npx-based servers:
{
"server-name": {
"command": "npx",
"args": ["-y", "@scope/package"]
}
}For stdio servers:
- command: Executable command
- args: Command arguments (optional)
For HTTP/SSE servers:
- url: Server endpoint
{
"env": {
"API_KEY": "${API_KEY}"
},
"timeout": 30000,
"disabled": false,
"scope": "user"
}- env: Environment variables
- timeout: Request timeout in milliseconds
- disabled: Skip loading this server
- scope: Configuration scope (user/project/local)
Reference environment variables with ${VAR_NAME}:
{
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}",
"API_URL": "${CUSTOM_API_URL:-https://api.default.com}"
}
}With defaults: ${VAR:-defaultValue}
Users must set these in their environment:
export GITHUB_TOKEN=ghp_xxxxxxxxxxxx
claude{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}Tools: Create issues, PRs, manage repos, search code Setup: Requires GitHub personal access token
{
"mcpServers": {
"gitlab": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-gitlab"],
"env": {
"GITLAB_TOKEN": "${GITLAB_TOKEN}",
"GITLAB_URL": "${GITLAB_URL:-https://gitlab.com}"
}
}
}
}Tools: Manage issues, MRs, pipelines Setup: Requires GitLab access token
{
"mcpServers": {
"slack": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-slack"],
"env": {
"SLACK_BOT_TOKEN": "${SLACK_BOT_TOKEN}",
"SLACK_TEAM_ID": "${SLACK_TEAM_ID}"
}
}
}
}Tools: Send messages, create channels, manage users Setup: Requires Slack app with bot token
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"POSTGRES_CONNECTION_STRING": "${POSTGRES_CONNECTION_STRING}"
}
}
}
}Tools: Query database, inspect schema Setup: Requires connection string
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/allowed/path1",
"/allowed/path2"
]
}
}
}Tools: Read/write files outside workspace Setup: Specify allowed paths
Choose your language:
Python (FastMCP):
from fastmcp import FastMCP
mcp = FastMCP("my-server")
@mcp.tool()
def my_tool(param: str) -> str:
"""Tool description."""
return f"Result: {param}"
if __name__ == "__main__":
mcp.run()TypeScript (MCP SDK):
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = new Server({
name: 'my-server',
version: '1.0.0',
});
server.setRequestHandler('tools/list', async () => ({
tools: [
{
name: 'my_tool',
description: 'Tool description',
inputSchema: {
type: 'object',
properties: {
param: { type: 'string' },
},
},
},
],
}));
const transport = new StdioServerTransport();
await server.connect(transport);Create plugin with MCP server:
my-plugin/
├── .claude-plugin/
│ └── plugin.json
├── .mcp.json # MCP server config goes here, at plugin root
├── dist/
│ └── server.bundle.cjs # Pre-built server binary
└── README.md
.mcp.json:
{
"my-server": {
"command": "node",
"args": ["${CLAUDE_PLUGIN_ROOT}/dist/server.bundle.cjs"]
}
}Use ${CLAUDE_PLUGIN_ROOT} to reference the plugin's installation directory.
Note: Plugin install does not run npm install. Distribute a pre-built binary in dist/, or use npx to install at runtime.
In README.md, document:
- What the server does
- Required environment variables
- Installation steps
- Usage examples
Most common authentication method:
{
"env": {
"API_TOKEN": "${SERVICE_API_TOKEN}"
}
}Document in README:
## Setup
1. Get API token from https://service.com/tokens
2. Set environment variable:
```bash
export SERVICE_API_TOKEN=your_token_here
```- Restart Claude Code
### OAuth
For OAuth services, use a helper server:
```json
{
"mcpServers": {
"oauth-service": {
"command": "npx",
"args": ["-y", "@myorg/oauth-server"],
"env": {
"CLIENT_ID": "${OAUTH_CLIENT_ID}",
"CLIENT_SECRET": "${OAUTH_CLIENT_SECRET}"
}
}
}
}
The server handles OAuth flow.
Support multiple accounts:
{
"mcpServers": {
"github-personal": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_PERSONAL_TOKEN}"
}
},
"github-work": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_WORK_TOKEN}"
}
}
}
}MCP servers can provide resources (data Claude can access):
@mcp.resource("config://settings")
def get_settings() -> str:
"""Current application settings."""
return json.dumps(load_settings())Claude can read these with:
Show me the current settings
Claude automatically discovers available tools from MCP servers.
If many tools available, Claude searches by name/description:
@mcp.tool()
def create_github_issue(title: str, body: str) -> dict:
"""Create a new GitHub issue.
Args:
title: Issue title
body: Issue description
"""
# ImplementationGood descriptions help Claude find relevant tools.
For complex services, provide managed config:
{
"mcpServers": {
"complex-service": {
"command": "npx",
"args": ["-y", "@myorg/complex-server"],
"managed": true,
"config": {
"endpoint": "https://api.example.com",
"features": ["feature1", "feature2"],
"rateLimit": 100
}
}
}
}Pass configuration via command args or stdin.
If MCP server fails to start:
- Claude logs error
- Server marked as unavailable
- Tools from that server disabled
View errors: /plugin → Errors tab
Set appropriate timeouts:
{
"timeout": 60000 // 60 seconds
}For long-running operations, use async patterns.
MCP servers should implement retries:
import tenacity
@tenacity.retry(
wait=tenacity.wait_exponential(min=1, max=10),
stop=tenacity.stop_after_attempt(3)
)
def api_call():
# Network request
passReuse connections when possible:
# Initialize once
client = APIClient(token=os.env["API_TOKEN"])
@mcp.tool()
def query_api(param: str):
return client.query(param) # Reuses connectionCache responses for expensive operations:
from functools import lru_cache
@lru_cache(maxsize=128)
@mcp.tool()
def expensive_lookup(key: str):
return slow_api_call(key)For large responses, use streaming:
@mcp.tool()
def large_data_query(filter: str):
"""Stream large dataset."""
for chunk in query_database(filter):
yield chunkRun server manually to see errors:
npx -y @modelcontextprotocol/server-githubInteract via stdin/stdout to test.
Set debug environment variable:
{
"env": {
"DEBUG": "mcp:*"
}
}Use MCP inspector tool to test servers:
npx @modelcontextprotocol/inspector npx -y @modelcontextprotocol/server-githubClaude logs MCP activity:
claude --debugLook for MCP connection and tool call logs.
Always validate tool inputs:
@mcp.tool()
def delete_file(path: str):
# Validate path is safe
if ".." in path or path.startswith("/"):
raise ValueError("Invalid path")
# Proceed with deletionOnly grant necessary permissions:
# ✅ Good: Read-only access
client = GitHubClient(token, read_only=True)
# ❌ Bad: Full write access
client = GitHubClient(token, scope="admin:*")Never hardcode secrets:
# ❌ Bad
token = "ghp_xxxxxxxxxxxx"
# ✅ Good
token = os.environ["GITHUB_TOKEN"]Log tool calls for security monitoring:
@mcp.tool()
def sensitive_operation(param: str):
logger.info(f"Tool called with: {param}")
# Implementation{
"name": "company-api-plugin",
"version": "1.0.0",
"mcpServers": {
"company-api": {
"command": "python",
"args": ["-m", "company_mcp_server"],
"env": {
"API_KEY": "${COMPANY_API_KEY}",
"API_URL": "${COMPANY_API_URL:-https://api.company.com}"
}
}
}
}{
"name": "dev-tools",
"version": "1.0.0",
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
},
"jira": {
"command": "npx",
"args": ["-y", "@myorg/jira-mcp-server"],
"env": {
"JIRA_TOKEN": "${JIRA_TOKEN}",
"JIRA_URL": "${JIRA_URL}"
}
},
"slack": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-slack"],
"env": {
"SLACK_BOT_TOKEN": "${SLACK_BOT_TOKEN}"
}
}
}
}Write helpful descriptions:
✅ Good: "Create a new GitHub issue with title and body" ❌ Vague: "Create issue"
Use proper type annotations:
from typing import List, Dict
@mcp.tool()
def search_items(query: str, limit: int = 10) -> List[Dict[str, str]]:
"""Search items matching query."""
passProvide actionable error messages:
try:
api_call()
except AuthError:
raise Exception(
"Authentication failed. "
"Check that GITHUB_TOKEN is set correctly."
)Document each tool thoroughly:
@mcp.tool()
def complex_operation(
param1: str,
param2: int,
param3: bool = False
) -> dict:
"""Perform a complex operation.
Args:
param1: Description of param1
param2: Description of param2
param3: Optional flag for special behavior
Returns:
Dictionary containing:
- result: Operation result
- status: Success/failure status
Raises:
ValueError: If param1 is invalid
APIError: If API request fails
"""
pass- Create plugins to bundle MCP servers
- Plugins reference for technical details
- Discover plugins to find existing integrations
- MCP documentation for protocol details