How to Build an MCP Server (Model Context Protocol)
The Model Context Protocol (MCP) is the new standard for connecting AI agents to external data. In this guide, we will build a simple MCP server in Node.js that allows an AI agent to read your company's internal database.
If you want your AI coding agent to be able to fetch Jira tickets, query your production database, or trigger a deployment, you need to build an MCP server.
An MCP server is essentially a lightweight wrapper around your existing APIs that translates them into a standardized format that any MCP-compatible client (like Cursor, Windsurf, or Claude Desktop) can understand.
Step 1: Setup the Project
We will use the official `@modelcontextprotocol/sdk` package for Node.js. Create a new directory and initialize it:
mkdir my-mcp-server cd my-mcp-server npm init -y npm install @modelcontextprotocol/sdk
Step 2: Initialize the Server
Create an `index.js` file. We need to initialize the server and define how it will communicate with the client. Most local MCP servers use `stdio` (Standard Input/Output) for communication.
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server({
name: "my-custom-mcp",
version: "1.0.0"
}, {
capabilities: {
tools: {}
}
});Step 3: Define Your Tools
"Tools" are the functions you want to expose to the AI. Let us create a tool that allows the AI to fetch a user's profile from our hypothetical database.
We have to tell the AI exactly what the tool does and what arguments it requires using JSON Schema.
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "get_user_profile",
description: "Fetch a user's profile by their email address.",
inputSchema: {
type: "object",
properties: {
email: {
type: "string",
description: "The email address of the user"
}
},
required: ["email"]
}
}
]
};
});Step 4: Handle Tool Execution
Now we need to write the actual logic that runs when the AI decides to call `get_user_profile`.
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "get_user_profile") {
const email = request.params.arguments.email;
// In a real app, you would query your database here
const mockDb = {
"[email protected]": { name: "Jason", role: "Admin" }
};
const user = mockDb[email];
if (!user) {
return {
content: [{ type: "text", text: "User not found." }],
isError: true
};
}
return {
content: [{ type: "text", text: JSON.stringify(user) }]
};
}
throw new Error("Tool not found");
});Step 5: Start the Transport
Finally, connect the server to the `stdio` transport so it can listen for messages from the AI client.
async function run() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Server running on stdio");
}
run().catch(console.error);Testing Your Server in Cursor
To test this in Cursor, go to Settings → MCP. Click "Add new MCP server". Set the type to "command", name it "my-custom-mcp", and set the command to `node /path/to/your/index.js`. Restart Cursor, and you can now ask the AI: "Can you get the profile for [email protected]?"
Why Build Your Own?
Building custom MCP servers is the key to unlocking true AI autonomy. If your agent can query your internal APIs, read your logs, and trigger your CI/CD pipelines, it stops being a text generator and becomes a real team member.
And if you need your agent to remember things across sessions, you don't even need to build a server—you can just use the pre-built Memstate MCP Server.
Skip the Boilerplate
Need persistent memory for your agent? Don't build it from scratch. Use Memstate's ready-to-go MCP server.