Node.js MCP server exposing a weather tool to an AI agent

Demystifying the Model Context Protocol (MCP): Building Your First Node.js Server (Part 3)

An MCP server lets your AI model call real tools, and in this guide you will build one in Node.js from scratch. By the end, you will have a working get_weather tool that any MCP-compatible agent can discover and run.

In Part 2 of this series, we ran open-source models locally with Ollama and connected to them through the Vercel AI SDK. That gave us a backend that can process chat requests and stream responses.

Also Read: Vercel AI SDK: Run AI Models Free, Cloud or Local (Part 2)

But there is a glaring problem: our AI is isolated. It can write text, but it doesn’t know what time it is, it can’t check a user’s balance in our database, and it can’t trigger a refund API.

Developers used to fix this with custom “glue code” for every LLM, defining functions the model could call (often called Function Calling or Tools). That approach is brittle and hard to scale. The Model Context Protocol solves exactly this problem.

What Is the Model Context Protocol (MCP)?

Anthropic introduced the Model Context Protocol as an open standard. Think of it as a USB port for AI models. It gives AI applications (the Host) a standard way to connect to external data sources and tools (the Servers).

Instead of teaching a model how to talk to your specific database, you build an MCP server. Any MCP-compatible agent can then connect to it, discover the tools you expose, and run them.

How an MCP Server Fits Into the MCP Architecture

MCP has three parts, and it helps to know which one you are building.

Host

The application running the AI model, such as Claude Desktop, Cursor, or your own React app built with the Vercel AI SDK.

Client

The component inside the Host that opens the connection to a server.

Server

Your backend service. In this tutorial it is a Node.js app that exposes tools, resources, and prompts.

Why Node.js Developers Should Learn to Build an MCP Server

If you build full-stack apps, MCP is worth learning now because the same server works across many AI clients. Here is what you get:

  • Standardization: Write a tool once and use it with any compliant LLM or agent.
  • Control: You decide which data the AI can read and which actions it can take. Your database credentials stay on your server and never reach the model.
  • Separation of concerns: Your business logic stays apart from the AI layer.

Also Read: The Full-Stack AI Developer Roadmap: From REST APIs to MCP Servers in 2026

Step 1: Set Up Your Node.js MCP Server Project

Let’s build a small server that gives the AI a tool it badly needs: checking the weather. You need Node.js 18 or newer.

Create a project and install the official SDK. We pin version 1 of the SDK and zod 3 so the code below matches exactly.

bash

mkdir mcp-weather-server
cd mcp-weather-server
npm init -y
npm pkg set type=module
npm install @modelcontextprotocol/sdk@1 zod@3

The type=module line lets you use import statements. We use zod to validate tool arguments, which MCP relies on so the AI passes the right inputs.

Step 2: Initialize the Server

Create an index.js file. First, import the SDK and create the server. For transport, we use stdio (standard input/output). It is ideal for local agents and for apps like Claude Desktop.

mcp-server-project-files.webp
Demystifying the Model Context Protocol (MCP): Building Your First Node.js Server (Part 3) 7

javascript

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: "weather-service",
  version: "1.0.0",
});

Show Image

Step 3: Define a Tool

Tools are the core of any MCP server. A tool is an action the AI can take.

Let’s add a get_weather tool. We give it a name, a clear description (the LLM reads this to decide when to use it), and its arguments described with zod.

javascript

server.registerTool(
  "get_weather",
  {
    description: "Get the current weather for a specific location",
    inputSchema: {
      city: z.string().describe("The city name, e.g. 'New York' or 'London'"),
      unit: z
        .enum(["celsius", "fahrenheit"])
        .default("celsius")
        .describe("The temperature unit"),
    },
  },
  async ({ city, unit }) => {
    // Log to stderr, because stdout is reserved for MCP messages
    console.error(`[Server Logic] Fetching weather for ${city}...`);

    // Mock data for this demo
    let temp = 22;
    if (city.toLowerCase() === "london") temp = 15;
    if (city.toLowerCase() === "dubai") temp = 35;
    if (unit === "fahrenheit") temp = (temp * 9) / 5 + 32;

    // MCP tools must return content in this format
    return {
      content: [
        { type: "text", text: `The weather in ${city} is currently ${temp} degrees ${unit}.` },
      ],
    };
  }
);

In a real app, swap the mock for a live API. Open-Meteo is a free weather API that needs no key, so it is an easy place to start.

Why Descriptions Matter for Your MCP Server

Look at the .describe() calls and the tool description. The AI reads them to work out how to use your tool. Vague descriptions make the model guess, and guessed arguments lead to failed tool calls. Write them like you are explaining the tool to a new teammate.

Note that server.tool() also exists in older tutorials. The SDK docs now recommend the register* methods for new code, which is why we use registerTool here.

Step 4: Start the Server

Now connect the server to a transport so it can listen for requests.

javascript

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("Weather MCP server running on stdio");
}

main().catch((error) => {
  console.error("Fatal error:", error);
  process.exit(1);
});

Always log with console.error. With stdio, anything written to stdout is treated as protocol traffic, and a stray console.log will break the connection.

Step 5: Test Your MCP Server

The fastest way to test is the official MCP Inspector, a web-based tool:

Diagram comparing stdio and Streamable HTTP connections for an MCP server
Demystifying the Model Context Protocol (MCP): Building Your First Node.js Server (Part 3) 8

bash

npx @modelcontextprotocol/inspector node index.js

It opens a browser UI that lists your get_weather tool. Pick the tool, enter a city like Dubai, and run it. The Inspector calls your server directly and shows the result. It does not include an AI model, so you are testing your server, not a chat.

To try it with a real model, add the server to a host like Claude Desktop. Open its MCP config file and add an entry that points to your script:

json

{
  "mcpServers": {
    "weather": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-weather-server/index.js"]
    }
  }
}

Restart the app, then ask, “What is the weather in Dubai?” The model should find your tool, call it, and answer with the result.

Show Image

Taking Your MCP Server Online with HTTP

Stdio is great for local agents. But as a full-stack developer, you will often need a React frontend to talk to a remote MCP server.

Diagram comparing stdio and Streamable HTTP connections for an MCP server
Demystifying the Model Context Protocol (MCP): Building Your First Node.js Server (Part 3) 9

For that, MCP uses Streamable HTTP. It handles requests over HTTP POST and can stream updates back with Server-Sent Events (SSE) when needed. You would add a web framework like Express and use the SDK’s Streamable HTTP transport instead of StdioServerTransport.

One warning if you have read older tutorials: the standalone HTTP+SSE transport is deprecated. The MCP specification changelog says to migrate to Streamable HTTP, and the TypeScript SDK docs recommend it for remote servers. Build new servers on Streamable HTTP.

FAQ: Building an MCP Server in Node.js

What is an MCP server?

An MCP server is a program that exposes tools, data, and prompts to AI applications through the Model Context Protocol. The AI connects, discovers what the server offers, and calls it when needed.

Do I need Claude to use an MCP server?

No. MCP is an open standard, so any compatible host can connect. Claude Desktop and Cursor are two examples, and you can also build your own client.

Should I use stdio or HTTP?

Use stdio for local tools that run on your own machine. Use Streamable HTTP when the server must be reached over a network, such as from a web app.

Why is my tool never called by the AI?

Usually the description is too vague. Rewrite the tool and argument descriptions so they say what the tool does and when to use it.

Can an MCP server replace my REST API?

No. They work as layers. Your REST API serves apps and developers, while an MCP server wraps the same logic for AI agents.

Conclusion

An MCP server turns your business logic into something any compliant AI agent can use, without rewriting integration code for each model. You built one in five steps: set up the project, initialize the server, define a tool, start it, and test it.

Start by swapping the mock weather data for a real API, then add a second tool. In Part 4, we will connect a React frontend to a Node.js MCP backend over HTTP and build the UI that shows when an AI is “thinking” and “using tools.”

Content Protection by DMCA.com
Spread the love
Scroll to Top
×