skills/ai-platform/mcp-server-development/SKILL.md
Build MCP (Model Context Protocol) servers. Covers tool/resource/prompt registration, stdio/SSE/HTTP transports, authentication, testing, and publishing to the MCP ecosystem.
npx skillsauth add bereniketech/claude_kit mcp-server-developmentInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Build Model Context Protocol servers that expose tools, resources, and prompts to Claude.
MCP primitives:
- Tools: Functions Claude can call (with parameters, return values)
- Resources: Files/data Claude can read (URI-addressed)
- Prompts: Reusable prompt templates Claude can use
Transports:
- stdio: CLI tools, local integrations (default)
- SSE: Server-Sent Events — web-based, one-directional push
- HTTP: REST-style, stateless
npm install @modelcontextprotocol/sdk zod
// server.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({
name: "my-mcp-server",
version: "1.0.0",
});
// Register a tool
server.tool(
"get_weather",
"Get current weather for a city",
{
city: z.string().describe("City name"),
units: z.enum(["celsius", "fahrenheit"]).default("celsius"),
},
async ({ city, units }) => {
const data = await fetchWeather(city, units);
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
}
);
// Register a resource
server.resource(
"config://app",
"Application configuration",
async (uri) => ({
contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(config) }],
})
);
// Register a prompt
server.prompt(
"analyze_code",
"Analyze code for issues",
{ code: z.string(), language: z.string() },
({ code, language }) => ({
messages: [{
role: "user",
content: { type: "text", text: `Analyze this ${language} code:\n\n${code}` },
}],
})
);
// Start server
const transport = new StdioServerTransport();
await server.connect(transport);
pip install mcp
# server.py
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-server")
@mcp.tool()
def search_database(query: str, limit: int = 10) -> list[dict]:
"""Search the database for records matching query."""
return db.search(query, limit=limit)
@mcp.resource("data://{table}")
def get_table_data(table: str) -> str:
"""Read all records from a table."""
return json.dumps(db.get_table(table))
if __name__ == "__main__":
mcp.run()
// GOOD: specific, typed, documented
server.tool(
"create_issue", // lowercase_snake_case name
"Create a GitHub issue in the specified repository", // clear description
{
owner: z.string().describe("Repository owner (username or org)"),
repo: z.string().describe("Repository name"),
title: z.string().max(256).describe("Issue title"),
body: z.string().optional().describe("Issue body in Markdown"),
labels: z.array(z.string()).default([]).describe("Label names to apply"),
},
async ({ owner, repo, title, body, labels }) => { ... }
);
// BAD: vague, untyped
server.tool("do_thing", "Does something", { input: z.any() }, async () => {});
Tool design rules:
verb_noun format (get_file, create_user, search_docs)z.string().describe(...) — Claude needs param descriptionstype: "text" content; add isError: true for failuresserver.tool("risky_operation", "...", schema, async (params) => {
try {
const result = await doOperation(params);
return { content: [{ type: "text", text: JSON.stringify(result) }] };
} catch (error) {
// Return error as tool result (not thrown exception)
return {
content: [{ type: "text", text: `Error: ${error.message}` }],
isError: true,
};
}
});
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
await server.connect(serverTransport);
const client = new Client({ name: "test-client", version: "1.0" }, {});
await client.connect(clientTransport);
// Call tool
const result = await client.callTool({ name: "get_weather", arguments: { city: "London" } });
console.assert(result.content[0].type === "text");
// ~/.claude/claude_desktop_config.json (macOS)
// %APPDATA%\Claude\claude_desktop_config.json (Windows)
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["/absolute/path/to/server.js"],
"env": {
"API_KEY": "your-key-here"
}
}
}
}
// package.json
{
"name": "@yourorg/mcp-server-name",
"version": "1.0.0",
"bin": { "mcp-server-name": "dist/server.js" },
"files": ["dist/"],
"engines": { "node": ">=18" }
}
# Build and publish
npm run build
npm publish --access public
List on: modelcontextprotocol.io/servers and Claude's MCP marketplace.
testing
AUTHORIZED USE ONLY: This skill contains dual-use security techniques. Before proceeding with any bypass or analysis: > 1.
development
Detects missing zeroization of sensitive data in source code and identifies zeroization removed by compiler optimizations, with assembly-level analysis, and control-flow verification. Use for auditing C/C++/Rust code handling secrets, keys, passwords, or other sensitive data.
development
Comprehensive guide to auditing web content against WCAG 2.2 guidelines with actionable remediation strategies.
development
Expert in threat modeling methodologies, security architecture review, and risk assessment. Masters STRIDE, PASTA, attack trees, and security requirement extraction. Use PROACTIVELY for security architecture reviews, threat identification, or building secure-by-design systems.