Skip to main content
An MCP server exposes capabilities — tools, resources, and prompts — that any compliant client or AI model can discover and use. In this lesson you build a simple calculator server and verify it works using the MCP Inspector.
If you build AI apps, you know that you can add tools and other resources to your LLM to make it more knowledgeable. When you place those tools on a server, any client — with or without an LLM — can use them.

Learning objectives

By the end of this lesson you will be able to:
  • Set up an MCP development environment in your chosen language
  • Build a basic MCP server that exposes tools and resources
  • Inspect and test your server using the MCP Inspector
  • Understand the three MCP server primitives: tools, resources, and prompts

What an MCP server can do

An MCP server can:
  • Access local files and databases
  • Connect to remote APIs
  • Perform computations
  • Integrate with other tools and services
  • Expose user-facing prompts

Basic server structure

Every MCP server has the same three building blocks:
PrimitivePurposeExample
ToolsFunctions the LLM can calladd(a, b)
ResourcesData the LLM can readfile://{path}
PromptsReusable message templatesreview-code

Exercise: Creating a server

1

Create the project

mkdir calculator-server
cd calculator-server
npm init -y
2

Install dependencies

npm install @modelcontextprotocol/sdk zod
npm install -D @types/node typescript
3

Write the server code

Create src/index.ts:
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({
  name: "Calculator MCP Server",
  version: "1.0.0"
});

// Add an addition tool
server.tool(
  "add",
  { a: z.number(), b: z.number() },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a + b) }]
  })
);

// Add a dynamic greeting resource
server.resource(
  "greeting",
  new ResourceTemplate("greeting://{name}", { list: undefined }),
  async (uri, { name }) => ({
    contents: [{ uri: uri.href, text: `Hello, ${name}!` }]
  })
);

// Add a code review prompt
server.prompt(
  "review-code",
  { code: z.string() },
  ({ code }) => ({
    messages: [{
      role: "user",
      content: { type: "text", text: `Please review this code:\n\n${code}` }
    }]
  })
);

const transport = new StdioServerTransport();
server.connect(transport);
4

Build and run

npm run build
5

Run the MCP Inspector

npx @modelcontextprotocol/inspector node build/index.js
The Inspector opens a browser UI. Connect to your server, click Tools → listTools, select add, fill in two numbers, and run it. You should see the result returned immediately.

Common setup issues

IssueSolution
Connection refusedCheck that the server is running and the port is correct
Tool execution errorsReview parameter validation and error handling
Authentication failuresVerify API keys and permissions
Schema validation errorsEnsure parameters match the defined schema
Server not startingCheck for port conflicts or missing dependencies

Assignment

Create a simple MCP server with a tool of your choice:
  1. Implement the tool in your preferred language.
  2. Define input parameters and return values.
  3. Run the Inspector tool to ensure the server works as intended.
  4. Test the implementation with various inputs.

Key takeaways

  • Setting up an MCP development environment is straightforward with language-specific SDKs.
  • Building MCP servers involves creating and registering tools with clear schemas.
  • Use the MCP Inspector to discover capabilities and test tool execution interactively.

Build docs developers (and LLMs) love