- name
- mcp-standards
- description
- MCP server standardization patterns for Claude Code plugins. Use when implementing MCP servers, designing tool interfaces, configuring MCP transports, or standardizing MCP naming conventions. Trigger keywords - "MCP", "MCP server", "MCP tools", "MCP transport", "tool naming", "MCP configuration".
- version
- 0.1.0
- tags
- ["dev","mcp","standards","server","tools","protocol"]
- keywords
- ["mcp","server","tools","transport","naming","configuration","protocol","stdio","http"]
- plugin
- dev
- updated
- 2026-01-28T00:00:00.000Z
# MCP Standards Skill
## 1. Overview
### What is MCP in Claude Code?
Model Context Protocol (MCP) is the standard way to extend Claude Code with custom tools and integrations. MCP servers provide:
- **Tool Integration**: Connect to external APIs, databases, and services
- **Context Providers**: Supply relevant information to Claude during conversations
- **Action Handlers**: Execute operations in external systems
- **Data Sources**: Access project-specific or organization-specific data
### Why Standardization Matters
Standardized MCP servers ensure:
1. **Predictable Behavior**: Developers know what to expect from MCP tools
2. **Easier Debugging**: Consistent patterns make issues easier to identify
3. **Better Discoverability**: Standard naming helps Claude and users find tools
4. **Maintainability**: Common patterns reduce maintenance burden
5. **Team Consistency**: Multiple developers follow same conventions
### MCP in the Plugin Ecosystem
MCP servers are plugin components alongside agents, commands, and skills:
```
plugin/
├── agents/ # Specialized Claude instances
├── commands/ # CLI commands
├── skills/ # Knowledge documents
└── mcp-servers/ # MCP tool providers ← We're here
```
**Key Difference**: While agents use built-in tools, MCP servers provide NEW tools that extend Claude's capabilities.
---
## 2. MCP Server Structure
### Standard Directory Layout
```
mcp-servers/
├── server-name/
│ ├── index.ts # Server entry point
│ ├── package.json # Dependencies and metadata
│ ├── tsconfig.json # TypeScript configuration
│ ├── README.md # Server documentation
│ ├── tools/ # Tool implementations
│ │ ├── read-tool.ts
│ │ ├── write-tool.ts
│ │ └── index.ts # Tool exports
│ ├── lib/ # Shared utilities
│ │ ├── client.ts # API client
│ │ ├── validation.ts # Input validation
│ │ └── errors.ts # Error handling
│ └── tests/ # Test files
│ ├── read-tool.test.ts
│ └── write-tool.test.ts
```
### Entry Point Pattern (index.ts)
```typescript
#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
// Import tools
import { fetchTool, createTool, updateTool } from "./tools/index.js";
const server = new Server(
{
name: "mcp-plugin-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
// Register tools
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [fetchTool.definition, createTool.definition, updateTool.definition],
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case fetchTool.name:
return fetchTool.handler(args);
case createTool.name:
return createTool.handler(args);
case updateTool.name:
return updateTool.handler(args);
default:
throw new Error(`Unknown tool: ${name}`);
}
});
// Start server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
main().catch(console.error);
```
### Tool Module Pattern
```typescript
// tools/fetch-tool.ts
import { z } from "zod";
const inputSchema = z.object({
id: z.string().describe("The resource ID to fetch"),
includeMetadata: z.boolean().optional().describe("Include metadata in response"),
});
export const fetchTool = {
name: "mcp__plugin__fetch_resource",
definition: {
name: "mcp__plugin__fetch_resource",
description: "Fetch a resource by ID from the external service",
inputSchema: {
type: "object",
properties: {
id: {
type: "string",
description: "The resource ID to fetch",
},
includeMetadata: {
type: "boolean",
description: "Include metadata in response",
},
},
required: ["id"],
},
},
handler: async (args: unknown) => {
const validated = inputSchema.parse(args);
try {
const result = await fetchResourceById(validated.id);
return {
content: [
{
type: "text",
text: JSON.stringify(result, null, 2),
},
],
};
} catch (error) {
throw new Error(`Failed to fetch resource: ${error.message}`);
}
},
};
```
---
## 3. Tool Naming Conventions
### Standard Pattern
```
mcp__<plugin-name>__<tool-name>
```
**Components**:
- `mcp__` - Universal prefix indicating MCP tool
- `<plugin-name>` - Plugin identifier (matches plugin.json id)
- `<tool-name>` - Descriptive snake_case tool name
### Real-World Examples
```typescript
// Frontend Plugin
"mcp__frontend__figma_fetch" // Fetch Figma designs
"mcp__frontend__figma_export_assets" // Export Figma assets
"mcp__frontend__lighthouse_audit" // Run Lighthouse audit
// Code Analysis Plugin
"mcp__code-analysis__claudemem_search" // Search codebase
"mcp__code-analysis__claudemem_enrich" // Enrich file context
// Bun Backend Plugin
"mcp__bun__apidog_sync" // Sync with Apidog
"mcp__bun__apidog_validate" // Validate API spec
// SEO Plugin
"mcp__seo__analyze_page" // Analyze page SEO
"mcp__seo__check_schema" // Validate schema markup
```
### Tool Name Guidelines
**DO**:
- Use snake_case for tool names
- Use action verbs (fetch, create, update, analyze)
- Be specific about what the tool does
- Keep names under 50 characters
**DON'T**:
- Use camelCase or PascalCase
- Use generic names like "do_thing"
- Include version numbers in names
- Use abbreviations unless widely known
### Verb Conventions
| Verb | Use Case | Example |
|------|----------|---------|
| `fetch` | Retrieve single resource | `fetch_user` |
| `list` | Retrieve multiple resources | `list_projects` |
| `search` | Query with filters | `search_files` |
| `create` | Create new resource | `create_issue` |
| `update` | Modify existing resource | `update_config` |
| `delete` | Remove resource | `delete_cache` |
| `validate` | Check data validity | `validate_schema` |
| `analyze` | Perform analysis | `analyze_performance` |
| `sync` | Synchronize data | `sync_database` |
| `export` | Export data | `export_report` |
---
## 4. Transport Configuration
### stdio Transport (Most Common)
Standard for local development and command-line usage:
```json
{
"mcpServers": {
"frontend-tools": {
"command": "node",
"args": ["${CLAUDE_PLUGIN_ROOT}/mcp-servers/frontend-tools/index.js"],
"transport": "stdio"
}
}
}
```
**When to Use**:
- Local plugin development
- Command-line integrations
- Single-user scenarios
- No network requirements
**Advantages**:
- Simple setup
- No port conflicts
- Secure (local only)
- Low latency
### HTTP Transport
For remote services or multi-user scenarios:
```json
{
"mcpServers": {
"shared-service": {
"url": "http://localhost:3000/mcp",
"transport": "http",
"headers": {
"Authorization": "Bearer ${API_TOKEN}"
}
}
}
}
```
**When to Use**:
- Remote API services
- Shared team resources
- Cloud-hosted tools
- Microservice architecture
**Advantages**:
- Network accessible
- Scalable
- Can use load balancing
- Standard HTTP tooling
### WebSocket Transport
For real-time bidirectional communication:
```json
{
"mcpServers": {
"realtime-service": {
"url": "ws://localhost:8080/mcp",
"transport": "websocket"
}
}
}
```
**When to Use**:
- Real-time updates
- Streaming responses
- Bidirectional communication
- Live collaboration tools
### Environment Variable Interpolation
All transports support environment variable substitution:
```json
{
"mcpServers": {
"apidog-sync": {
"command": "node",
"args": ["${CLAUDE_PLUGIN_ROOT}/mcp-servers/apidog/index.js"],
"env": {
"APIDOG_API_TOKEN": "${APIDOG_API_TOKEN}",
"APIDOG_PROJECT_ID": "${APIDOG_PROJECT_ID}"
}
}
}
}
```
**Pattern**: `${VARIABLE_NAME}` is replaced at runtime.
---
## 5. Tool Categories
### Read-Only Tools
**Purpose**: Retrieve information without side effects.
**Characteristics**:
- Safe to call multiple times
- No state changes
- Fast response times
- Cacheable results
**Examples**:
```typescript
// Fetch single resource
mcp__plugin__fetch_config
mcp__plugin__get_status
// List multiple resources
mcp__plugin__list_projects
mcp__plugin__list_files
// Search/query
mcp__plugin__search_code
mcp__plugin__query_database
```
### Write Tools
**Purpose**: Create, update, or delete resources.
**Characteristics**:
- Modify state
- Require validation
- Need error handling
- Should be idempotent when possible
**Examples**:
```typescript
// Create
mcp__plugin__create_file
mcp__plugin__create_issue
// Update
mcp__plugin__update_config
mcp__plugin__update_document
// Delete
mcp__plugin__delete_cache
mcp__plugin__remove_entry
```
### Analysis Tools
**Purpose**: Process data and provide insights.
**Characteristics**:
- Compute-intensive
- Return structured results
- May have longer timeouts
- Often cacheable
**Examples**:
```typescript
mcp__plugin__analyze_performance
mcp__plugin__audit_security
mcp__plugin__validate_schema
mcp__plugin__check_quality
```
### Integration Tools
**Purpose**: Connect to external services.
**Characteristics**:
- Bridge systems
- Handle authentication
- Manage rate limits
- Deal with network errors
**Examples**:
```typescript
mcp__plugin__sync_database
mcp__plugin__import_data
mcp__plugin__export_report
mcp__plugin__webhook_notify
```
---
## 6. Performance Standards
### Response Time Targets
| Tool Type | Target | Max Acceptable |
|-----------|--------|----------------|
| Simple fetch | <50ms | 200ms |
| List operation | <100ms | 500ms |
| Search | <200ms | 1000ms |
| Analysis | <500ms | 3000ms |
| Write operation | <300ms | 2000ms |
| Sync operation | <1000ms | 5000ms |
### Timeout Configuration
```typescript
// Set timeouts for different operations
const TIMEOUT_CONFIG = {
fetch: 5000, // 5 seconds
search: 10000, // 10 seconds
analyze: 30000, // 30 seconds
sync: 60000, // 1 minute
};
async function callWithTimeout<T>(
operation: Promise<T>,
timeoutMs: number
): Promise<T> {
const timeout = new Promise<never>((_, reject) =>
setTimeout(() => reject(new Error("Operation timed out")), timeoutMs)
);
return Promise.race([operation, timeout]);
}
```
### Rate Limiting
Ver no GitHub