Skip to main content
mcp-standards 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".
Zur Installation springen Skills Marktplatz Entdecken und erkunden Sie KI-Skills, die von der Community erstellt wurden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Prompt kopierenPrompt-Details anzeigen Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
npx skills add https://github.com/MadAppGang/claude-code --skill mcp-standardsDer Befehl bleibt in einer Zeile. Scrollen Sie horizontal, um ihn vor dem Kopieren vollständig zu prüfen.
Sie bevorzugen eine lokale Kopie? Laden Sie die Dateien herunter, die SkillsMP derzeit vorliegen.
ZIP herunterladen Herunterladen... Basierend auf der SOC-Berufsklassifikation
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:
Predictable Behavior : Developers know what to expect from MCP tools
Easier Debugging : Consistent patterns make issues easier to identify
Better Discoverability : Standard naming helps Claude and users find tools
Maintainability : Common patterns reduce maintenance burden
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) #!/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 { fetchTool, createTool, updateTool } from "./tools/index.js" ;
const server = new Server (
{
name : "mcp-plugin-server" ,
version : "1.0.0" ,
},
{
capabilities : {
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} ` );
}
});
async function main ( ) {
const transport = new StdioServerTransport ();
await server.connect (transport);
}
main ().catch (console .error );
Tool Module Pattern
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>
mcp__ - Universal prefix indicating MCP tool
<plugin-name> - Plugin identifier (matches plugin.json id)
<tool-name> - Descriptive snake_case tool name
Real-World Examples
"mcp__frontend__figma_fetch"
"mcp__frontend__figma_export_assets"
"mcp__frontend__lighthouse_audit"
"mcp__code-analysis__claudemem_search"
"mcp__code-analysis__claudemem_enrich"
"mcp__bun__apidog_sync"
"mcp__bun__apidog_validate"
"mcp__seo__analyze_page"
"mcp__seo__check_schema"
Tool Name Guidelines
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
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 fetchRetrieve single resource fetch_userlistRetrieve multiple resources list_projectssearchQuery with filters search_filescreateCreate new resource create_issueupdateModify existing resource update_configdeleteRemove resource delete_cachevalidateCheck data validity validate_schemaanalyzePerform analysis analyze_performancesyncSynchronize data sync_databaseexportExport data export_report
4. Transport Configuration
stdio Transport (Most Common) Standard for local development and command-line usage:
{
"mcpServers" : {
"frontend-tools" : {
"command" : "node" ,
"args" : [ "${CLAUDE_PLUGIN_ROOT}/mcp-servers/frontend-tools/index.js" ] ,
"transport" : "stdio"
}
}
}
Local plugin development
Command-line integrations
Single-user scenarios
No network requirements
Simple setup
No port conflicts
Secure (local only)
Low latency
HTTP Transport For remote services or multi-user scenarios:
{
"mcpServers" : {
"shared-service" : {
"url" : "http://localhost:3000/mcp" ,
"transport" : "http" ,
"headers" : {
"Authorization" : "Bearer ${API_TOKEN}"
}
}
}
}
Remote API services
Shared team resources
Cloud-hosted tools
Microservice architecture
Network accessible
Scalable
Can use load balancing
Standard HTTP tooling
WebSocket Transport For real-time bidirectional communication:
{
"mcpServers" : {
"realtime-service" : {
"url" : "ws://localhost:8080/mcp" ,
"transport" : "websocket"
}
}
}
Real-time updates
Streaming responses
Bidirectional communication
Live collaboration tools
Environment Variable Interpolation All transports support environment variable substitution:
{
"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.
Safe to call multiple times
No state changes
Fast response times
Cacheable results
mcp__plugin__fetch_config
mcp__plugin__get_status
mcp__plugin__list_projects
mcp__plugin__list_files
mcp__plugin__search_code
mcp__plugin__query_database
Write Tools Purpose : Create, update, or delete resources.
Modify state
Require validation
Need error handling
Should be idempotent when possible
mcp__plugin__create_file
mcp__plugin__create_issue
mcp__plugin__update_config
mcp__plugin__update_document
mcp__plugin__delete_cache
mcp__plugin__remove_entry
Analysis Tools Purpose : Process data and provide insights.
Compute-intensive
Return structured results
May have longer timeouts
Often cacheable
mcp__plugin__analyze_performance
mcp__plugin__audit_security
mcp__plugin__validate_schema
mcp__plugin__check_quality
Integration Tools Purpose : Connect to external services.
Bridge systems
Handle authentication
Manage rate limits
Deal with network errors
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
const TIMEOUT_CONFIG = {
fetch : 5000 ,
search : 10000 ,
analyze : 30000 ,
sync : 60000 ,
};
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 class RateLimiter {
private requests : number = 0 ;
private resetTime : number = Date .now () + 60000 ;
async checkLimit (limit : number = 100 ) {
if (Date .now () > this .resetTime ) {
this .requests = 0 ;
this .resetTime = Date .now () + 60000 ;
}
if (this .requests >= limit) {
throw new Error ("Rate limit exceeded. Try again later." );
}
this .requests ++;
}
}
Error Handling Patterns class MCPError extends Error {
constructor (
message : string ,
public code : string ,
public details ?: unknown
) {
super (message);
this .name = "MCPError" ;
}
}
try {
const result = await externalAPI.fetch (id);
return { content : [{ type : "text" , text : JSON .stringify (result) }] };
} catch (error) {
if (error.code === "NOT_FOUND" ) {
throw new MCPError ("Resource not found" , "NOT_FOUND" , { id });
}
if (error.code === "RATE_LIMITED" ) {
throw new MCPError ("Rate limit exceeded" , "RATE_LIMITED" );
}
throw new MCPError ("Unexpected error" , "INTERNAL_ERROR" , { error });
}
7. Security Patterns
Input Validation Always validate inputs using a schema validation library:
import { z } from "zod" ;
const fetchInputSchema = z.object ({
id : z.string ().uuid ("Invalid UUID format" ),
includePrivate : z.boolean ().default (false ),
});
export const handler = async (args : unknown ) => {
const validated = fetchInputSchema.parse (args);
};
Output Sanitization Never return raw data that might contain sensitive information:
function sanitizeOutput (data : any ): any {
const { password, apiKey, secret, ...safe } = data;
if (typeof safe === "object" && safe !== null ) {
for (const key in safe) {
if (key.toLowerCase ().includes ("token" ) ||
key.toLowerCase ().includes ("key" ) ||
key.toLowerCase ().includes ("password" )) {
safe[key] = "[REDACTED]" ;
}
}
}
return safe;
}
Permission Checks Implement permission checks before executing operations:
async function checkPermission (userId : string , action : string ): Promise <void > {
const permissions = await getPermissions (userId);
if (!permissions.includes (action)) {
throw new MCPError (
`User ${userId} lacks permission: ${action} ` ,
"PERMISSION_DENIED"
);
}
}
export const handler = async (args : unknown ) => {
await checkPermission (args.userId , "resource:write" );
};
Sensitive Data Handling Environment variables for secrets :
const API_KEY = process.env .EXTERNAL_API_KEY ;
if (!API_KEY ) {
throw new Error ("EXTERNAL_API_KEY environment variable is required" );
}
const response = await fetch (url, {
headers : {
Authorization : `Bearer ${API_KEY} ` ,
},
});
Audit logging for sensitive operations :
async function auditLog (
action : string ,
userId : string ,
details : object
): Promise <void > {
const timestamp = new Date ().toISOString ();
console .log (JSON .stringify ({ timestamp, action, userId, details }));
}
await auditLog ("delete_resource" , userId, { resourceId });
await deleteResource (resourceId);
8. Configuration Patterns
Plugin Manifest (plugin.json) {
"id" : "example-plugin" ,
"name" : "Example Plugin" ,
"version" : "1.0.0" ,
"mcpServers" : {
"example-tools" : {
"command" : "node" ,
"args" : [ "${CLAUDE_PLUGIN_ROOT}/mcp-servers/example-tools/index.js" ] ,
"env" : {
"EXAMPLE_API_TOKEN" : "${EXAMPLE_API_TOKEN}" ,
"EXAMPLE_BASE_URL" : "${EXAMPLE_BASE_URL}"
}
}
}
}
Project Settings (.claude/settings.json) Override plugin defaults per project:
{
"enabledPlugins" : {
"example-plugin@marketplace" : true
} ,
"mcpServers" : {
"example-tools" : {
"env" : {
"EXAMPLE_BASE_URL" : "https://custom-api.example.com"
}
}
}
}
Environment Variables
EXAMPLE_API_TOKEN=your-token-here
APIDOG_API_TOKEN=your-apidog-token
EXAMPLE_BASE_URL=https://api.example.com
CHROME_EXECUTABLE_PATH=/usr/bin/chromium
const config = {
apiToken : process.env .EXAMPLE_API_TOKEN ,
baseUrl : process.env .EXAMPLE_BASE_URL || "https://api.example.com" ,
};
9. Best Practices
DO
Use Standard Naming : Follow mcp__plugin__action_resource pattern
Validate All Inputs : Use Zod or similar schema validation
Handle Errors Gracefully : Return clear error messages
Document Tools : Provide detailed descriptions and examples
Set Appropriate Timeouts : Don't let operations hang indefinitely
Test Thoroughly : Unit tests for all tools
Log Operations : Help with debugging and auditing
Use Environment Variables : Never hardcode secrets
Implement Rate Limiting : Protect external APIs
Version Your Servers : Track breaking changes
DON'T
Don't Return Sensitive Data : Sanitize outputs
Don't Ignore Errors : Handle and report all failures
Don't Use Hardcoded Credentials : Always use environment variables
Don't Skip Validation : Trust no input
Don't Create Side Effects in Read Tools : Keep reads idempotent
Don't Use Blocking Operations : Use async/await properly
Don't Expose Internal Implementation : Abstract away complexity
Don't Forget Error Context : Include relevant details
Don't Mix Concerns : One tool, one purpose
Don't Skip Documentation : Future you will thank you
Testing MCP Servers import { describe, it, expect, beforeEach } from "bun:test" ;
import { fetchTool } from "./fetch-tool.js" ;
describe ("fetchTool" , () => {
it ("should fetch resource by ID" , async () => {
const result = await fetchTool.handler ({ id : "test-123" });
expect (result.content [0 ].text ).toContain ("test-123" );
});
it ("should throw on invalid ID" , async () => {
await expect (
fetchTool.handler ({ id : "invalid" })
).rejects .toThrow ("Invalid UUID format" );
});
});
Documentation Requirements
README.md : Overview, installation, usage
Tool descriptions : In tool definitions
Input schemas : With descriptions for each field
Error documentation : Possible error codes and meanings
Examples : Sample requests and responses
10. Examples
Example 1: Simple Read-Only MCP Server #!/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 { z } from "zod" ;
const server = new Server (
{ name : "simple-reader" , version : "1.0.0" },
{ capabilities : { tools : {} } }
);
const fetchConfigTool = {
name : "mcp__simple__fetch_config" ,
definition : {
name : "mcp__simple__fetch_config" ,
description : "Fetch configuration by key" ,
inputSchema : {
type : "object" ,
properties : {
key : { type : "string" , description : "Configuration key" },
},
required : ["key" ],
},
},
handler : async (args : unknown ) => {
const { key } = z.object ({ key : z.string () }).parse (args);
const configs = {
apiUrl : "https://api.example.com" ,
timeout : "5000" ,
retries : "3" ,
};
const value = configs[key];
if (!value) {
throw new Error (`Configuration key not found: ${key} ` );
}
return {
content : [
{ type : "text" , text : `${key} =${value} ` },
],
};
},
};
server.setRequestHandler (ListToolsRequestSchema , async () => ({
tools : [fetchConfigTool.definition ],
}));
server.setRequestHandler (CallToolRequestSchema , async (request) => {
if (request.params .name === fetchConfigTool.name ) {
return fetchConfigTool.handler (request.params .arguments );
}
throw new Error (`Unknown tool: ${request.params.name} ` );
});
async function main ( ) {
const transport = new StdioServerTransport ();
await server.connect (transport);
}
main ().catch (console .error );
Example 2: Full CRUD MCP Server #!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js" ;
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js" ;
import { z } from "zod" ;
const store = new Map <string , any >();
const createTool = {
name : "mcp__crud__create_item" ,
definition : {
name : "mcp__crud__create_item" ,
description : "Create a new item" ,
inputSchema : {
type : "object" ,
properties : {
name : { type : "string" },
value : { type : "string" },
},
required : ["name" , "value" ],
},
},
handler : async (args : unknown ) => {
const { name, value } = z.object ({
name : z.string (),
value : z.string (),
}).parse (args);
if (store.has (name)) {
throw new Error (`Item already exists: ${name} ` );
}
const item = { name, value, createdAt : new Date ().toISOString () };
store.set (name, item);
return {
content : [{ type : "text" , text : JSON .stringify (item) }],
};
},
};
const readTool = {
name : "mcp__crud__read_item" ,
definition : {
name : "mcp__crud__read_item" ,
description : "Read an item by name" ,
inputSchema : {
type : "object" ,
properties : {
name : { type : "string" },
},
required : ["name" ],
},
},
handler : async (args : unknown ) => {
const { name } = z.object ({ name : z.string () }).parse (args);
const item = store.get (name);
if (!item) {
throw new Error (`Item not found: ${name} ` );
}
return {
content : [{ type : "text" , text : JSON .stringify (item) }],
};
},
};
const updateTool = {
name : "mcp__crud__update_item" ,
definition : {
name : "mcp__crud__update_item" ,
description : "Update an existing item" ,
inputSchema : {
type : "object" ,
properties : {
name : { type : "string" },
value : { type : "string" },
},
required : ["name" , "value" ],
},
},
handler : async (args : unknown ) => {
const { name, value } = z.object ({
name : z.string (),
value : z.string (),
}).parse (args);
const existing = store.get (name);
if (!existing) {
throw new Error (`Item not found: ${name} ` );
}
const updated = {
...existing,
value,
updatedAt : new Date ().toISOString (),
};
store.set (name, updated);
return {
content : [{ type : "text" , text : JSON .stringify (updated) }],
};
},
};
const deleteTool = {
name : "mcp__crud__delete_item" ,
definition : {
name : "mcp__crud__delete_item" ,
description : "Delete an item by name" ,
inputSchema : {
type : "object" ,
properties : {
name : { type : "string" },
},
required : ["name" ],
},
},
handler : async (args : unknown ) => {
const { name } = z.object ({ name : z.string () }).parse (args);
if (!store.has (name)) {
throw new Error (`Item not found: ${name} ` );
}
store.delete (name);
return {
content : [{ type : "text" , text : `Deleted: ${name} ` }],
};
},
};
const server = new Server (
{ name : "crud-server" , version : "1.0.0" },
{ capabilities : { tools : {} } }
);
server.setRequestHandler (ListToolsRequestSchema , async () => ({
tools : [
createTool.definition ,
readTool.definition ,
updateTool.definition ,
deleteTool.definition ,
],
}));
server.setRequestHandler (CallToolRequestSchema , async (request) => {
const { name, arguments : args } = request.params ;
const tools = { createTool, readTool, updateTool, deleteTool };
const tool = Object .values (tools).find ((t ) => t.name === name);
if (!tool) {
throw new Error (`Unknown tool: ${name} ` );
}
return tool.handler (args);
});
async function main ( ) {
const transport = new StdioServerTransport ();
await server.connect (transport);
}
main ().catch (console .error );
Example 3: External API Integration MCP Server #!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js" ;
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js" ;
import { z } from "zod" ;
const API_TOKEN = process.env .EXTERNAL_API_TOKEN ;
const BASE_URL = process.env .EXTERNAL_BASE_URL || "https://api.example.com" ;
if (!API_TOKEN ) {
throw new Error ("EXTERNAL_API_TOKEN environment variable is required" );
}
class ExternalAPIClient {
async fetch (endpoint : string , options = {} ) {
const response = await fetch (`${BASE_URL} ${endpoint} ` , {
...options,
headers : {
Authorization : `Bearer ${API_TOKEN} ` ,
"Content-Type" : "application/json" ,
...options.headers ,
},
});
if (!response.ok ) {
throw new Error (`API error: ${response.status} ${response.statusText} ` );
}
return response.json ();
}
}
const client = new ExternalAPIClient ();
const fetchUserTool = {
name : "mcp__external__fetch_user" ,
definition : {
name : "mcp__external__fetch_user" ,
description : "Fetch user data from external API" ,
inputSchema : {
type : "object" ,
properties : {
userId : { type : "string" , description : "User ID" },
},
required : ["userId" ],
},
},
handler : async (args : unknown ) => {
const { userId } = z.object ({ userId : z.string () }).parse (args);
try {
const user = await client.fetch (`/users/${userId} ` );
return {
content : [{ type : "text" , text : JSON .stringify (user, null , 2 ) }],
};
} catch (error) {
throw new Error (`Failed to fetch user: ${error.message} ` );
}
},
};
const server = new Server (
{ name : "external-api-server" , version : "1.0.0" },
{ capabilities : { tools : {} } }
);
server.setRequestHandler (ListToolsRequestSchema , async () => ({
tools : [fetchUserTool.definition ],
}));
server.setRequestHandler (CallToolRequestSchema , async (request) => {
if (request.params .name === fetchUserTool.name ) {
return fetchUserTool.handler (request.params .arguments );
}
throw new Error (`Unknown tool: ${request.params.name} ` );
});
async function main ( ) {
const transport = new StdioServerTransport ();
await server.connect (transport);
}
main ().catch (console .error );
Summary This skill provides comprehensive MCP server standards for Claude Code plugins:
Structure : Consistent directory layout and entry point patterns
Naming : mcp__plugin__action_resource convention
Transports : stdio (local), HTTP (remote), WebSocket (realtime)
Categories : Read, Write, Analysis, Integration tools
Performance : Response time targets, timeouts, rate limiting
Security : Input validation, output sanitization, permission checks
Configuration : plugin.json, settings.json, environment variables
Best Practices : Comprehensive DO/DON'T list
Examples : Three complete, production-ready MCP servers
Follow these standards to create maintainable, secure, and performant MCP servers for your Claude Code plugins.
Mehr aus diesem Repository