How to Build an MCP Server
Create an MCP server from scratch that gives AI agents new capabilities. By the end of this guide, you'll have a working server with your own custom tools.
This guide covers the fundamentals. If you want a production-ready boilerplate with five tool patterns, a publishing pipeline, and a monetization guide, check out the Ship Your MCP Server starter kit.
1 Set up your project
Create a new directory and initialize it:
npm init -y
npm install @modelcontextprotocol/sdk zod
Open package.json and add "type": "module" so you can use ES module imports. Also add a bin field so the server can be run as a CLI command:
"name": "my-mcp-server",
"version": "1.0.0",
"type": "module",
"bin": { "my-mcp": "./index.js" },
"dependencies": {
"@modelcontextprotocol/sdk": "^1.0.0",
"zod": "^3.22.0"
}
}
2 Create the server
Create index.js with the shebang line (required for npx), imports, and server setup:
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 Add your first tool
Tools are the core of an MCP server. Each tool has a name, description, input schema (using Zod), and a handler function. Here's a simple example — a tool that checks if a website is up:
"check_website",
"Check if a website is responding and return the status code",
{ url: z.string().describe("URL to check") },
async ({ url }) => {
try {
const res = await fetch(url, { method: "HEAD", signal: AbortSignal.timeout(10000) });
return { content: [{ type: "text", text: `Status: ${res.status} ${res.statusText}` }] };
} catch (e) {
return { content: [{ type: "text", text: `Error: ${e.message}` }] };
}
}
);
The pattern is always the same: name, description, schema, handler. The description matters — it's what the AI agent reads to decide when to use your tool. Make it specific.
4 Connect the transport
Add this at the bottom of index.js to start the server using stdio (the standard transport for local MCP servers):
await server.connect(transport);
Make the file executable:
5 Test it
Add the server to your AI tool's config and restart:
"mcpServers": {
"my-server": {
"command": "node",
"args": ["/absolute/path/to/my-mcp-server/index.js"]
}
}
}
Ask your agent: "Check if google.com is up." It should call your check_website tool and return a real status code.
Where to go from here
This is the minimal version. A production MCP server typically includes:
Multiple tool categories — network tools, data tools, API wrappers, computation tools. Each focused on things the AI agent can't do natively.
Error handling — timeouts, rate limits, input validation, graceful failures. Your tools need to be as reliable as any API your code depends on.
Structured output — return data in formats the agent can reason about. Tables, JSON, clear labels. Not raw text dumps.
Publishing — npm publish makes it installable via npx for anyone. The MCP Registry and awesome-mcp-servers GitHub repo drive discovery.
Monetization — MCPize lets you sell access with an 85% revenue share. Freemium works: give away core tools, charge for premium ones. Industry benchmarks show 6-8% conversion from free to paid.
Ship Your MCP Server — Starter Kit
Production-ready boilerplate with five tool patterns (network, API, database, file system, scraper), a complete publishing pipeline, a monetization playbook, and our full 24-tool server as a reference. Go from idea to published, revenue-generating MCP server in an afternoon.
Get the kit — $79