Mcp server patterns
Skill sairam0424/MindForge/.mindforge/skills/mcp-server-patterns
MindForge: The Enterprise Agentic Framework for Claude Code & Antigravity. High-performance autonomous execution, wave-parallelism, and multi-tier governance for production-grade AI engineering.From the repository description
npx -y skills add sairam0424/MindForge --skill mcp-server-patternsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
9.1 KB, ~2.0k tokens by cl100k_base, as published. Nobody here has run it
Skill — MCP Server Patterns
When this skill activates
When designing, building, or debugging Model Context Protocol (MCP) servers that expose tools, resources, or prompts to AI agents. Use when implementing the server side of MCP — registering capabilities, handling requests, managing transport, and following protocol conventions.
MCP is the standard protocol for extending AI agents with external capabilities. A well-built MCP server is the difference between an agent that can only talk and one that can act.
Mandatory actions when this skill is active
Before building the MCP server
-
Identify capability types needed:
Type Purpose Agent interaction Example Tools Actions agents invoke Agent calls with args, gets result create-file,run-query,send-emailResources Data agents read Agent requests by URI, gets content file://,db://schema,config://envPrompts Reusable templates Agent fills arguments, gets formatted prompt code-review,summarize,translate -
Choose transport:
Transport Use when Characteristics stdio Local tools, CLI integration, dev/test Process-based, simple, synchronous feel Streamable HTTP Remote servers, multi-client, production Scalable, stateless, HTTP-based -
Design the schema contract:
- Every tool must have a typed input schema (Zod for TypeScript, Pydantic for Python)
- Every resource must have a URI pattern and content type
- Every prompt must declare its arguments with descriptions
- Write the schema FIRST, implement SECOND (contract-first design)
-
Plan error handling strategy:
- Tool errors: return structured error with code and message (never throw unhandled)
- Resource not found: return appropriate MCP error code
- Validation failures: return detailed field-level errors
- Never expose internal stack traces to the client
During MCP server implementation
Project structure (TypeScript/Node.js):
mcp-server-[name]/
src/
index.ts # Server initialization and transport setup
tools/
index.ts # Tool registration aggregator
[tool-name].ts # One file per tool
resources/
index.ts # Resource registration aggregator
[resource-name].ts # One file per resource
prompts/
index.ts # Prompt registration aggregator
[prompt-name].ts # One file per prompt
lib/
errors.ts # Custom MCP error classes
schemas.ts # Shared Zod schemas
tests/
tools/
[tool-name].test.ts
integration/
stdio.test.ts # Full server integration via stdio
package.json
tsconfig.json
Tool registration pattern:
import { z } from "zod";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
const InputSchema = z.object({
filePath: z.string().describe("Absolute path to the target file"),
content: z.string().describe("Content to write to the file"),
overwrite: z.boolean().default(false).describe("Whether to overwrite existing files"),
});
export function registerCreateFileTool(server: McpServer) {
server.tool(
"create-file",
"Create a new file with the specified content at the given path",
InputSchema.shape,
async ({ filePath, content, overwrite }) => {
// Validate path is within allowed directories
validatePath(filePath);
// Check existing file
if (!overwrite && await fileExists(filePath)) {
return {
content: [{ type: "text", text: `Error: File already exists at ${filePath}. Use overwrite: true to replace.` }],
isError: true,
};
}
await writeFile(filePath, content);
return {
content: [{ type: "text", text: `Successfully created file at ${filePath} (${content.length} bytes)` }],
};
}
);
}
Resource registration pattern:
export function registerFileResource(server: McpServer) {
// Static resource
server.resource(
"project-config",
"config://project",
"The project's configuration file",
async (uri) => ({
contents: [{
uri: uri.href,
mimeType: "application/json",
text: await readFile("./config.json", "utf-8"),
}],
})
);
// Dynamic resource with URI template
server.resource(
"source-file",
new ResourceTemplate("file:///{path}", { list: undefined }),
"Read a source file by path",
async (uri, { path }) => ({
contents: [{
uri: uri.href,
mimeType: getMimeType(path),
text: await readFile(path, "utf-8"),
}],
})
);
}
Prompt registration pattern:
export function registerCodeReviewPrompt(server: McpServer) {
server.prompt(
"code-review",
"Generate a structured code review for the given diff",
{
diff: z.string().describe("The git diff to review"),
severity: z.enum(["quick", "thorough", "security"]).default("thorough")
.describe("Review depth level"),
},
({ diff, severity }) => ({
messages: [{
role: "user",
content: {
type: "text",
text: `Review this code diff at ${severity} level:\n\n${diff}\n\nProvide findings as: [SEVERITY] file:line - description`,
},
}],
})
);
}
Transport setup:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
const server = new McpServer({
name: "my-mcp-server",
version: "1.0.0",
});
// Register all capabilities
registerTools(server);
registerResources(server);
registerPrompts(server);
// stdio transport (local/CLI)
const transport = new StdioServerTransport();
await server.connect(transport);
// OR: Streamable HTTP transport (remote/production)
// const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
// app.post("/mcp", async (req, res) => { await transport.handleRequest(req, res); });
Error handling (mandatory):
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
// In tool handlers:
if (!isValid(input)) {
throw new McpError(
ErrorCode.InvalidParams,
`Invalid input: ${validationErrors.join(", ")}`
);
}
// For "soft" errors (operation failed but not a protocol error):
return {
content: [{ type: "text", text: `Operation failed: ${reason}` }],
isError: true,
};
Security considerations:
- Validate all file paths against an allowlist of directories
- Sanitize inputs that will be used in shell commands or SQL
- Rate limit tool invocations if exposed over HTTP
- Log all tool invocations for audit trail
- Never expose secrets through resource responses
- Use environment variables for sensitive configuration
After MCP server implementation
-
Testing protocol:
- Unit test each tool handler with valid inputs, invalid inputs, and edge cases
- Integration test via stdio transport (spawn server, send requests, verify responses)
- Use MCP Inspector for interactive testing during development:
npx @modelcontextprotocol/inspector node dist/index.js - Test error paths: malformed requests, missing required fields, timeout scenarios
- Verify resource URIs resolve correctly under all template patterns
-
Documentation requirements:
- README with: what the server does, prerequisites, installation, configuration
- Tool catalog: name, description, input schema, example usage, error cases
- Resource catalog: URI patterns, content types, access patterns
- Configuration: all environment variables with types and defaults
-
Deployment checklist:
package.jsonhas correctbinentry for stdio servers"type": "module"set if using ESM- All dependencies are production dependencies (not devDependencies)
- Server starts cleanly with no warnings or unhandled rejections
- Graceful shutdown on SIGTERM/SIGINT
Self-check before task completion
Before marking an MCP server task done:
- Did I define typed input schemas for every tool (Zod/Pydantic)?
- Did I implement proper error handling (McpError with codes, isError for soft failures)?
- Did I validate and sanitize all inputs (especially file paths and shell args)?
- Did I write integration tests using stdio transport?
- Did I test with MCP Inspector to verify the server works interactively?
- Did I document all tools, resources, and prompts with examples?
- Did I choose the appropriate transport for the deployment context?
- Does the server start cleanly and shut down gracefully?
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.
Gives 1 of the 12 instructions most mcp tooling skills give in ~2.0k tokens
Counted across 638 of the 750 authors here whose files we hold, read 2026-08-07
- Create ten complex or independent read-only evaluation questionsin 69 of 638, across 15 files
- Test servers using MCP Inspectorhere, and in 61 of 638, across 19 files
- Provide actionable error messages with specific next stepsin 54 of 638, across 12 files
- Prioritize comprehensive API coverage over specific workflows or workflow toolsin 54 of 638, across 12 files
- Use TypeScript and Streamable HTTP for remote servers or clientsin 54 of 638, across 8 files
- Define structured output schemas where possiblein 50 of 638, across 8 files
- Use Zod or Pydantic for input schemasin 47 of 638, across 5 files
- Fetch MCP specification pages with markdown suffixin 46 of 638, across 4 files
- Load framework documentation using WebFetchin 45 of 638, across 3 files
- Verify each evaluation answer independentlyin 45 of 638, across 3 files
- Implement API client with authentication and paginationin 45 of 638, across 3 files
- Define input schemas with validationin 27 of 638, across 9 files
Said here and by no other author read
- Design schema contracts before implementation
- Never expose internal stack traces to clients
- Sanitize inputs used in shell commands or SQL
- Write integration tests using stdio transport
- Set bin entry for stdio servers
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.