194 lines
4.8 KiB
Markdown
194 lines
4.8 KiB
Markdown
---
|
|
name: ck-mcp-builder
|
|
description: >
|
|
Scaffolds and implements Model Context Protocol (MCP) servers with tools, resources, and prompts.
|
|
Activate when user says 'build an MCP server', 'create MCP tools', 'scaffold MCP',
|
|
'add MCP integration', or 'expose API as MCP'. Accepts tool definitions,
|
|
resource schemas, and target transport (stdio, SSE, HTTP).
|
|
---
|
|
|
|
## Overview
|
|
Generates complete MCP server implementations using the official MCP SDK. Covers tool registration, resource endpoints, prompt templates, and transport configuration for Claude Desktop or other MCP clients.
|
|
|
|
## When to Use
|
|
- Exposing custom tools or APIs to Claude via MCP protocol
|
|
- Building a server that Claude can use to access databases, APIs, or file systems
|
|
- Creating reusable MCP integrations for a team or organization
|
|
- Adding MCP support to an existing service
|
|
|
|
## Don't Use When
|
|
- Simple one-off script that doesn't need to be invocable by an LLM
|
|
- Task requires an existing MCP server configuration (use ck-mcp-management)
|
|
- Building a client that consumes MCP servers (different SDK surface)
|
|
|
|
## Steps / Instructions
|
|
|
|
### 1. Initialize Project
|
|
|
|
```bash
|
|
mkdir my-mcp-server && cd my-mcp-server
|
|
npm init -y
|
|
npm install @modelcontextprotocol/sdk zod
|
|
npm install -D typescript @types/node tsx
|
|
```
|
|
|
|
`tsconfig.json`:
|
|
```json
|
|
{
|
|
"compilerOptions": {
|
|
"target": "ES2022",
|
|
"module": "Node16",
|
|
"moduleResolution": "Node16",
|
|
"outDir": "./dist",
|
|
"strict": true
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. Create the Server
|
|
|
|
```typescript
|
|
// src/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",
|
|
});
|
|
```
|
|
|
|
### 3. Register Tools
|
|
|
|
```typescript
|
|
// Simple tool with input schema
|
|
server.tool(
|
|
"get_weather",
|
|
"Get current weather for a city",
|
|
{
|
|
city: z.string().describe("City name to get weather for"),
|
|
units: z.enum(["celsius", "fahrenheit"]).default("celsius"),
|
|
},
|
|
async ({ city, units }) => {
|
|
// implementation
|
|
const data = await fetchWeather(city, units);
|
|
return {
|
|
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
};
|
|
}
|
|
);
|
|
|
|
// Tool that returns multiple content types
|
|
server.tool(
|
|
"capture_screenshot",
|
|
"Take a screenshot of a URL",
|
|
{ url: z.string().url() },
|
|
async ({ url }) => {
|
|
const imageBuffer = await screenshot(url);
|
|
return {
|
|
content: [
|
|
{ type: "text", text: `Screenshot of ${url}` },
|
|
{ type: "image", data: imageBuffer.toString("base64"), mimeType: "image/png" },
|
|
],
|
|
};
|
|
}
|
|
);
|
|
```
|
|
|
|
### 4. Register Resources
|
|
|
|
```typescript
|
|
// Static resource
|
|
server.resource(
|
|
"config",
|
|
"app://config",
|
|
async (uri) => ({
|
|
contents: [{
|
|
uri: uri.href,
|
|
mimeType: "application/json",
|
|
text: JSON.stringify({ version: "1.0.0", env: process.env.NODE_ENV }),
|
|
}],
|
|
})
|
|
);
|
|
|
|
// Dynamic resource with URI template
|
|
server.resource(
|
|
"user-profile",
|
|
new ResourceTemplate("users://{userId}/profile", { list: undefined }),
|
|
async (uri, { userId }) => ({
|
|
contents: [{
|
|
uri: uri.href,
|
|
mimeType: "application/json",
|
|
text: JSON.stringify(await getUser(userId)),
|
|
}],
|
|
})
|
|
);
|
|
```
|
|
|
|
### 5. Register Prompt Templates
|
|
|
|
```typescript
|
|
server.prompt(
|
|
"code-review",
|
|
"Generate a code review for a file",
|
|
{
|
|
filename: z.string(),
|
|
focus: z.string().optional().describe("Specific aspect to focus on"),
|
|
},
|
|
({ filename, focus }) => ({
|
|
messages: [{
|
|
role: "user",
|
|
content: {
|
|
type: "text",
|
|
text: `Review the code in ${filename}${focus ? ` focusing on ${focus}` : ""}.
|
|
Check for: correctness, performance, security, readability.`,
|
|
},
|
|
}],
|
|
})
|
|
);
|
|
```
|
|
|
|
### 6. Start the Server
|
|
|
|
```typescript
|
|
// Stdio transport (for Claude Desktop)
|
|
async function main() {
|
|
const transport = new StdioServerTransport();
|
|
await server.connect(transport);
|
|
console.error("MCP server running on stdio");
|
|
}
|
|
|
|
main().catch(console.error);
|
|
```
|
|
|
|
### 7. Configure in Claude Desktop
|
|
|
|
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"my-server": {
|
|
"command": "node",
|
|
"args": ["/absolute/path/to/dist/server.js"],
|
|
"env": {
|
|
"API_KEY": "..."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### 8. Test with MCP Inspector
|
|
|
|
```bash
|
|
npx @modelcontextprotocol/inspector node dist/server.js
|
|
```
|
|
|
|
## Notes
|
|
- Use `console.error` for logging — stdout is reserved for the MCP protocol
|
|
- Never hardcode secrets; pass via environment variables in the config
|
|
- Tool descriptions are critical — the LLM uses them to decide when to call the tool
|
|
- Keep tools focused and single-purpose; compose complex behavior at the LLM level
|
|
- Zod schemas auto-generate JSON Schema for tool input validation
|