How to Create an MCP Server with Node.js and TypeScript
The Node.js SDK for MCP enables JavaScript and TypeScript developers to build tools and resources that works alongside Claude and other LLMs. This guide walks you through setting up a project, creating your first tool, and testing your server.
What is an MCP Server?
A Model Context Protocol (MCP) server connects Large Language Models (LLMs) like Claude to external systems. Without MCP, integrating AI into your workflow means copying and pasting data into a chat window. An MCP server removes that step, letting the AI query databases, read files, or run code directly within a controlled environment. This solves the "context window" problem. Instead of stuffing everything into a prompt, the AI discovers and pulls in specific information when it needs it. The MCP specification defines three server capabilities:
- Resources: Passive data sources that the AI can read. Think of them as specialized files or database rows that provide background for a task.
- Tools: Executable functions. They let the AI perform actions like sending an email, making an API call, or running a calculation.
- Prompts: Pre-defined templates that shape how the AI interacts with the user or the data. The official TypeScript SDK gives Node.js developers full type safety over the JSON-RPC messages exchanged between client and server. If you need to wire up custom AI tools to existing enterprise systems or npm packages, it's a strong starting point.
Helpful references: Fastio Workspaces, Fastio Collaboration, and Fastio AI.
Related guides
- How to Implement MCP Server Rate LimitingMCP server rate limiting controls how often AI agents can invoke tools through a Model Context Protocol server. Without...
- How to Build an MCP Server in GoGo is a strong fit for MCP servers thanks to its compiled performance, lightweight goroutines, and simple deployment as...
- How to Debug MCP Server IssuesModel Context Protocol server debugging involves diagnosing connection failures, tool execution errors, and transport...
- Fastio MCP Server Integration Guide for DevelopersThe Fastio MCP server is a remote server. Your client connects to it over a URL, which means there is no package to...
- How to Build an MCP Server with FastAPI and PythonGuide to mcp server fastapi python: You can use FastAPI to turn Python code into standardized tools for AI agents like...
- How to Build an MCP Server with Java Spring BootBuilding an MCP server with Java Spring Boot lets you use the Model Context Protocol within the Spring ecosystem....
More on this subject: MCP and Model Context Protocol (195 guides)
Step 1: Project Setup
You'll need Node.js v18 or higher installed. We'll use TypeScript because the MCP protocol relies on structured data, and TypeScript catches schema mismatches at compile time instead of at runtime. First, create a new directory for your project and initialize it with a package.json file:
mkdir my-mcp-server
cd my-mcp-server
npm init -y
Next, install the dependencies. @modelcontextprotocol/sdk handles the protocol, and zod handles runtime schema validation for your tool inputs:
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node tsx
zod matters here because TypeScript types disappear at runtime. LLMs can occasionally send malformed JSON or hallucinated arguments, and zod catches that before your function runs. It verifies that the arguments the AI provides (a and b in our calculator) are actually numbers. If they're not, your server returns a clear error to the model instead of crashing. Create a tsconfig.json in your project root. The MCP SDK requires ESM, so the module settings matter here:
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./dist",
"rootDir": "./src",
"strict": true.
"esModuleInterop": true
},
"include": ["src/**/*"]
}
Step 2: Building Your First Tool
Let's create a server that exposes a tool. We'll build a basic calculator the AI can call. Create src/index.ts:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
// Initialize the server
const server = new Server(
{
name: "example-calculator",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
// Define available tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "calculate_sum",
description: "Add two numbers together",
inputSchema: {
type: "object",
properties: {
a: { type: "number" },
b: { type: "number" },
},
required: ["a", "b"],
},
},
],
};
});
// Handle tool execution
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "calculate_sum") {
const { a, b } = request.params.arguments as { a: number; b: number };
return {
content: [
{
type: "text",
text: String(a + b),
},
],
};
}
throw new Error("Tool not found");
});
// Start the server using stdio transport
const transport = new StdioServerTransport();
await server.connect(transport);
Here's what each piece does:
ListToolsRequestSchema: This handler tells the AI what tools are available. TheinputSchemais the most important part because it's the documentation the AI reads to figure out how to call the tool. Better descriptions and schemas mean fewer bad calls.CallToolRequestSchema: This is the execution engine. When the AI decides to call a tool, this handler receives the request, parses the arguments, and runs your logic.- Stdio Transport: We use standard input/output for the connection. This is the simplest setup: no network configuration needed. The client spawns your process and talks to it through command line pipes.
Need storage for your AI agents?
Fastio gives you usage-based cloud storage built for mcp server nodejs. Get streaming previews, AI-powered search, and unlimited guest sharing. Start with a free account.
Step 3: Testing with Claude Desktop
To test your server, configure Claude Desktop to run the script. Open your Claude config file (~/Library/Application Support/Claude/claude_desktop_config.json on macOS) and add the server:
{
"mcpServers": {
"my-calculator": {
"command": "npx",
"args": ["-y", "tsx", "/absolute/path/to/my-mcp-server/src/index.ts"]
}
}
}
Restart Claude Desktop. You should now see a 🔌 icon indicating the server is connected. Try asking Claude: "Can you use the calculator tool to add 50 and 100?" It should invoke your code and return "150". Consider how this fits into your broader workflow and what matters most for your team. The right choice depends on your specific requirements: file types, team size, security needs, and how you collaborate with external partners. Testing with a free account is the fast way to know if a tool works for you.
Why Build vs. Buy?
Building your own MCP server makes sense for custom internal logic or proprietary APIs, which is exactly what the walkthrough above is for. For standard file operations and cloud storage, though, maintaining your own server is work you probably do not need to take on.
Fastio runs a managed MCP server covering file management, search, and storage through a consolidated MCP toolset. * Nothing to run: the server is remote and hosted, so there is no boilerplate, no stdio wiring, and no deployment of your own. Your client config carries a url, not a command. * Persistent storage: files an agent writes survive the session that created them, instead of vanishing with the process. * Intelligence: when enabled, files are indexed automatically for semantic search and citation-backed chat. * Works with any MCP client: Claude, Cursor, Cline, OpenClaw, and anything else that speaks the protocol. Connecting it takes a URL and a scoped key, which is covered step by step in the Fastio MCP server integration guide.
Advanced: Serving over HTTP
stdio works well for local desktop apps, but cloud-hosted agents need a different transport. The Node.js SDK also supports Server-Sent Events (SSE) over HTTP. To switch, replace StdioServerTransport with SSEServerTransport and wrap it in an Express or Fastify server. Remote agents can then connect to your tools over the web. The way SSE works: the server pushes messages to the client over a persistent HTTP connection, and the client sends requests back via standard HTTP POST. You get real-time updates without the complexity of full WebSockets, and it's firewall-friendly enough to deploy on serverless platforms. Fastio's managed MCP server uses this same architecture for streamable connections to your file storage from anywhere.
Frequently Asked Questions
What is the best language for building MCP servers?
TypeScript is a strong choice for MCP servers because its type safety maps directly to the JSON-RPC protocol schemas, catching errors before runtime. Python is another popular option, especially for data science tools.
Can I run an MCP server on a hosting provider?
Yes, you can deploy MCP servers to any platform that supports Node.js or Docker, such as Railway, Render, or AWS. You will need to use the SSE (Server-Sent Events) transport layer instead of stdio for remote connections.
Is Fastio's MCP server compatible with custom servers?
Yes. MCP is designed to be modular, so you can run Fastio's server for file storage and RAG alongside your custom Node.js server for business logic. Clients connect to both at the same time.
Related Resources
Need storage for your AI agents?
Fastio gives you usage-based cloud storage built for mcp server nodejs. Get streaming previews, AI-powered search, and unlimited guest sharing. Start with a free account.