The Model Context Protocol (MCP) is rapidly becoming the industry standard for bridging LLMs with secure data sources. In this guide, we will walk you through the architecture of MCP and show you how to build your first custom server.
Understanding MCP Architecture
MCP operates on a simple, yet highly robust client-server design. The client (typically an AI assistant like Claude Code or Codex) communicates with the MCP server using standard JSON-RPC 2.0 messages over standard input/output (stdin/stdout) or Server-Sent Events (SSE). This keeps the connection isolated, secure, and low-latency.
An MCP server can declare three key capabilities:
- Resources: Read-only data schemas (like file content, database rows, or documentation pages) that the LLM can reference.
- Tools: Executable functions (like running a command, inserting a row, or calling a third-party API) that the LLM can trigger with user consent.
- Prompts: Pre-structured templates or system instructions that the LLM can load dynamically.
A Simple Custom Server in Node.js
Let us create a basic server that fetches system metrics. First, initialize a new project and install the official SDK:
npm install @modelcontextprotocol/sdk
Then, write the server file index.js:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
const server = new Server({
name: "system-monitor",
version: "1.0.0",
}, {
capabilities: {
tools: {},
},
});
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [{
name: "get_system_load",
description: "Returns the current CPU load and memory usage",
inputSchema: { type: "object", properties: {} },
}],
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "get_system_load") {
return {
content: [{
type: "text",
text: JSON.stringify({ cpu: "18%", memory: "58% used" }),
}],
};
}
throw new Error("Tool not found");
});
const transport = new StdioServerTransport();
await server.connect(transport);
Connecting the AI Agent
To connect Claude Code or similar assistants, simply configure the server command in the agent config file:
{
"mcpServers": {
"system-monitor": {
"command": "node",
"args": ["/absolute/path/to/index.js"]
}
}
}
Restart your client, and the agent will now be able to fetch system load statistics on demand!