Recommended resources
The freely available resources this lesson will direct you to.
Welcome back! In our last session, we mapped out the API for a Model Context Protocol (MCP) server, defining the key JSON-RPC methods like resources/list and resources/read that allow a client to discover and retrieve context. You now have the blueprint for what an MCP server needs to do.
Today, we transition from blueprint to construction. You will take the API specification we've studied and bring it to life by implementing your first, basic MCP server. We'll use the official Node.js SDK, which aligns well with your JavaScript expertise, to build a server that responds to a context request with simple, hard-coded data. This is the "Hello, World!" of MCP server development—a foundational step that makes the protocol tangible and sets the stage for more complex integrations.
By the end of this lesson, you will have a running MCP server on your local machine that you can inspect and test, turning the abstract protocol into a concrete piece of software.
Part 1: Setting Up Your Environment
As a software engineer, you know that any project begins with setting up the right environment. We will use Node.js and TypeScript, leveraging the official @modelcontextprotocol/sdk. This SDK provides high-level abstractions that handle the low-level complexities of the JSON-RPC communication, letting you focus on the logic of what your server provides.
To begin, create a new project directory and initialize a Node.js project. The following guide will walk you through setting up the necessary files and dependencies.
MCPs Part 1: Building a Hello World MCP Server - fka.dev
This article provides a clear, step-by-step guide to creating a Node.js MCP server. We'll use its setup instructions as our starting point.
Follow the guide under the Setting Up Your Environment section. This involves: Creating a project directory and running npm init. Installing the required dependencies: @modelcontextprotocol/sdk, zod, and express. While we won't use express in this lesson, it will be useful for HTTP transports later. Installing the necessary development dependencies for TypeScript: @types/node, @types/express, and typescript. Creating the package.json and tsconfig.json files as shown in the article. These configurations are standard for a modern Node.js/TypeScript project.
After completing these steps, you will have a project structure ready for your server code, typically within a src/index.ts file.
Part 2: The Barebones Server
With the environment ready, let's write the minimum code required to start an MCP server. This involves two key components from the SDK:
McpServer: The main class representing your server. You instantiate it with metadata like its name and version.StdioServerTransport: The communication layer. This transport uses standard input/output (stdio), which is ideal for local development where the client (like an IDE extension or the MCP Inspector tool) runs on the same machine and can communicate with your server process directly.
The following code initializes the server and tells it to start listening for connections over the stdio transport.
MCPs Part 1: Building a Hello World MCP Server - fka.dev
We will use the basic server setup from the article as our boilerplate.
In your src/index.ts file, add the code from the section Setting Up the Basic Server. This snippet does three things: Imports McpServer and StdioServerTransport from the SDK. Creates a new McpServer instance with a name and version. Initializes a StdioServerTransport and connects the server to it, effectively "turning on" the server to listen for client connections.
This snippet does three things:
- Imports
McpServerandStdioServerTransportfrom the SDK. - Creates a new
McpServerinstance with a name and version. - Initializes a
StdioServerTransportand connects the server to it, effectively "turning on" the server to listen for client connections.
At this point, you have a running, albeit empty, MCP server. It can handle the initial handshake (initialize message) but doesn't offer any tools, prompts, or the resources we're aiming to implement.
Part 3: Implementing a Static Resource
Now for the main event: making our server provide some context. In MCP, read-only context is exposed via resources. We will implement a resource that serves a simple, hard-coded "Hello, World!" string when requested. This directly satisfies our learning goal.
To do this, we use the server.resource() method from the SDK. This method registers a new resource, making it discoverable and readable by connected clients.

Let's add the code to define our static resource.
MCPs Part 1: Building a Hello World MCP Server - fka.dev
This section of the article shows exactly how to define a static resource, which is the core of today's lesson.
Add the code from the subsection <tf start="Implementing a Hello World Resource" end="This is my first MCP resource. "}]}));">Implementing a Hello World Resource to your src/index.ts file, placing it before the transport connection logic. Let's break down the server.resource() call: "hello-world": This is the human-readable name of the resource. "hello://world": This is the unique resource identifier (URI). Clients use this URI to request this specific resource. The hello:// scheme is custom, demonstrating that URIs can be anything that uniquely identifies the resource within your server's context. async (uri) => ({...}): This is the handler function. It's called when a client performs a resources/read operation on this URI. The function returns a contents object containing the data—in our case, a simple hard-coded text string. The structure of this returned object directly corresponds to the JSON response for a resources/read request that we studied in the previous lesson.
Let's break down the server.resource() call:
"hello-world": This is the human-readable name of the resource."hello://world": This is the unique resource identifier (URI). Clients use this URI to request this specific resource. Thehello://scheme is custom, demonstrating that URIs can be anything that uniquely identifies the resource within your server's context.async (uri) => ({...}): This is the handler function. It's called when a client performs aresources/readoperation on this URI. The function returns acontentsobject containing the data—in our case, a simple hard-coded text string. The structure of this returned object directly corresponds to the JSON response for aresources/readrequest that we studied in the previous lesson.
With this addition, your server is no longer empty. It now advertises and serves a single, static resource.
Part 4: Testing with MCP Inspector
You've written the code, but how do you know it works? You need a client to connect to your server and request the resource. The MCP team provides a perfect tool for this: MCP Inspector. Think of it as Postman or Insomnia, but specifically designed for interacting with MCP servers.
Let's install and run the Inspector to test your server.
The Ultimate MCP Crash Course - Build From Scratch
This video provides an excellent visual demonstration of setting up and using the MCP Inspector to test a Node.js server, very similar to the one you just built.
First, install the inspector as a development dependency by running npm install -D @modelcontextprotocol/inspector. Next, add a script to your package.json to run it, as shown in the video from this segment. A simple script would look like this:
"scripts": {
...
"inspect": "mcp-inspector 'npm run start'"
}
This command tells the inspector to launch your server using your npm run start script.
Now, run npm run inspect. This will start your server and open a web UI for the inspector. Watch the video from stdio server.
Once connected, you can test your resource:
- Navigate to the Resources tab in the Inspector UI.
- Click the List Resources button. You should see your "hello-world" resource appear in the list. This confirms your server correctly handled the
resources/listrequest. - Click on the "hello-world" resource in the list. The inspector will then make a
resources/readrequest. - You should see the content
"Hello, World! This is my first MCP resource."displayed. This confirms your resource handler is working as expected.
The textual guide MCPs Part 1: Building a Hello World MCP Server also describes these testing steps in its section "Testing Different Capabilities with MCP Inspector" if you prefer a written reference.
Conclusion
Congratulations! You have successfully built, run, and tested a compliant MCP server. While simple, this exercise is a significant milestone. You've moved from theoretical knowledge of the protocol to practical implementation, creating a tangible piece of software that correctly responds to standardized client requests.
Key Takeaways:
- SDKs Simplify Development: The official MCP SDKs handle the protocol's boilerplate, allowing you to focus on defining your server's capabilities.
- Server Core: A basic server consists of an
McpServerinstance and aTransport(likeStdioServerTransportfor local development). - Defining Resources: The
server.resource()method is used to expose data. You provide a name, a URI, and a handler function that returns the content. - Testing is Crucial: Tools like
MCP Inspectorare essential for debugging and verifying that your server behaves as expected, acting as a reference client.
We've laid the foundation by serving static data. In our next lesson, we will build upon this by connecting our server to a local data source—a simple file—to serve context dynamically. This will bring us one step closer to building the powerful, real-world AI integrations you're aiming for.