From claude-initial-setup
Guide for creating MCP (Model Context Protocol) servers in TypeScript and Python, including scaffolding, transports, lifecycle hooks, and testing. Use when the user wants to build an MCP server, add tools/resources/prompts to an MCP server, configure stdio or SSE transport, or test MCP server functionality.
npx claudepluginhub versoxbt/claude-initial-setup --plugin claude-initial-setupThis skill uses the workspace's default tool permissions.
How to build MCP servers from scratch in TypeScript and Python. Covers project setup,
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
How to build MCP servers from scratch in TypeScript and Python. Covers project setup, transport configuration, tool/resource/prompt registration, lifecycle hooks, and testing.
# Initialize project
mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node
npx tsc --init
// src/index.ts - Minimal MCP server with stdio transport
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-server",
version: "1.0.0",
});
// Register a tool
server.tool(
"greet",
"Greet a user by name. Use when the user wants a personalized greeting.",
{ name: z.string().describe("The person's name") },
async ({ name }) => ({
content: [{ type: "text", text: `Hello, ${name}!` }],
})
);
// Start with stdio transport
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP server running on stdio");
}
main().catch(console.error);
# Initialize project
mkdir my-mcp-server && cd my-mcp-server
pip install mcp
# server.py - Minimal MCP server with stdio transport
import asyncio
from mcp.server import Server
from mcp.server.stdio import stdio_server
import mcp.types as types
server = Server("my-server")
@server.list_tools()
async def list_tools() -> list[types.Tool]:
return [
types.Tool(
name="greet",
description="Greet a user by name. Use when the user wants a personalized greeting.",
inputSchema={
"type": "object",
"properties": {
"name": {"type": "string", "description": "The person's name"}
},
"required": ["name"]
}
)
]
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
if name == "greet":
return [types.TextContent(type="text", text=f"Hello, {arguments['name']}!")]
raise ValueError(f"Unknown tool: {name}")
async def main():
async with stdio_server() as (read_stream, write_stream):
await server.run(read_stream, write_stream, server.create_initialization_options())
if __name__ == "__main__":
asyncio.run(main())
For remote MCP servers accessible over HTTP.
// TypeScript - SSE transport
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import express from "express";
const app = express();
const server = new McpServer({ name: "my-server", version: "1.0.0" });
// Register tools on server...
app.get("/sse", async (req, res) => {
const transport = new SSEServerTransport("/messages", res);
await server.connect(transport);
});
app.post("/messages", async (req, res) => {
// Handle incoming messages from the transport
await transport.handlePostMessage(req, res);
});
app.listen(3001, () => console.error("MCP SSE server on port 3001"));
Handle server initialization and shutdown gracefully.
const server = new McpServer({ name: "my-server", version: "1.0.0" });
// The server handles lifecycle automatically, but you can add cleanup
process.on("SIGINT", async () => {
console.error("Shutting down MCP server...");
await server.close();
process.exit(0);
});
process.on("SIGTERM", async () => {
await server.close();
process.exit(0);
});
Test your MCP server using the MCP Inspector or programmatically with an in-memory client.
# Use MCP Inspector for interactive testing
npx @modelcontextprotocol/inspector node dist/index.js
// Programmatic testing with in-memory transport
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
async function testServer() {
const server = new McpServer({ name: "test", version: "1.0.0" });
// Register tools...
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
await server.connect(serverTransport);
const client = new Client({ name: "test-client", version: "1.0.0" });
await client.connect(clientTransport);
// Call a tool
const result = await client.callTool({ name: "greet", arguments: { name: "World" } });
console.assert(result.content[0].text === "Hello, World!");
await client.close();
await server.close();
}
Register your MCP server in Claude Desktop's config.
// ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["/absolute/path/to/dist/index.js"],
"env": {
"API_KEY": "your-key-here"
}
}
}
}
| Component | TypeScript Import |
|---|---|
| Server | @modelcontextprotocol/sdk/server/mcp.js |
| Stdio | @modelcontextprotocol/sdk/server/stdio.js |
| SSE | @modelcontextprotocol/sdk/server/sse.js |
| InMemory | @modelcontextprotocol/sdk/inMemory.js |
| Client | @modelcontextprotocol/sdk/client/index.js |
| Transport | Use Case |
|---|---|
| stdio | Local tools, CLI integration, Claude Desktop |
| SSE | Remote servers, web-accessible tools |
| In-memory | Testing, same-process communication |
MCP Inspector: npx @modelcontextprotocol/inspector <command> <args>