Create MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. The quality of an MCP server is measured by how well it enables LLMs to accomplish real-world tasks.
Create MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. The quality of an MCP server is measured by how well it enables LLMs to accomplish real-world tasks.
Creating a high-quality MCP server involves four main phases:
API Coverage vs. Workflow Tools: Balance comprehensive API endpoint coverage with specialized workflow tools. Workflow tools can be more convenient for specific tasks, while comprehensive coverage gives agents flexibility to compose operations. Performance varies by client—some clients benefit from code execution that combines basic tools, while others work better with higher-level workflows. When uncertain, prioritize comprehensive API coverage.
Tool Naming and Discoverability:
Clear, descriptive tool names help agents find the right tools quickly. Use consistent prefixes (e.g., github_create_issue, github_list_repos) and action-oriented naming.
Context Management: Agents benefit from concise tool descriptions and the ability to filter/paginate results. Design tools that return focused, relevant data. Some clients support code execution which can help agents filter and process data efficiently.
Actionable Error Messages: Error messages should guide agents toward solutions with specific suggestions and next steps.
Navigate the MCP specification:
Start with the sitemap to find relevant pages: https://modelcontextprotocol.io/sitemap.xml
Then fetch specific pages with .md suffix for markdown format (e.g., https://modelcontextprotocol.io/specification/draft.md).
Key pages to review:
src/
├── index.ts # Entry point
├── server.ts # MCP server setup
├── tools/
│ ├── index.ts # Tool registration
│ └── [tool-name].ts # Individual tools
├── utils/
│ ├── api-client.ts # API wrapper
│ └── errors.ts # Error handling
└── types.ts # TypeScript types
For each tool:
Input Schema:
Output Schema:
outputSchema where possible for structured datastructuredContent in tool responses (TypeScript SDK feature)Tool Description:
Implementation:
Annotations:
readOnlyHint: true/falsedestructiveHint: true/falseidempotentHint: true/falseopenWorldHint: true/falseReview for:
TypeScript:
npm run build to verify compilationnpx @modelcontextprotocol/inspectorPython:
python -m py_compile your_server.pyAfter implementing your MCP server, create comprehensive evaluations to test its effectiveness.
To create effective evaluations, follow this process:
Ensure each question is:
Create an XML file with this structure:
<evaluation>
<qa_pair>
<question>Find discussions about AI model launches with animal codenames...</question>
<answer>3</answer>
</qa_pair>
<!-- More qa_pairs... -->
</evaluation>
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new Server({
name: "my-mcp-server",
version: "1.0.0",
});
// Register a tool
server.registerTool({
name: "get_weather",
description: "Get current weather for a city",
inputSchema: z.object({
city: z.string().describe("City name"),
units: z.enum(["metric", "imperial"]).default("metric"),
}),
outputSchema: z.object({
temperature: z.number(),
conditions: z.string(),
}),
annotations: {
readOnlyHint: true,
},
handler: async ({ city, units }) => {
const weather = await fetchWeather(city, units);
return {
content: [{ type: "text", text: JSON.stringify(weather) }],
structuredContent: weather,
};
},
});
// Start server
const transport = new StdioServerTransport();
await server.connect(transport);
github_, slack_)