Time to get your hands dirty. In this module, you will set up everything you need to build and test MCP servers locally. By the end, you will have a working project directory, the MCP SDK installed, the Inspector running, and Claude Desktop configured to connect to custom servers.
Prerequisites Checklist
Before you start, make sure you have these installed. Open a terminal and run each command. If any fails, install it before proceeding.
# Check Node.js (need 18 or higher)
node --version
# Expected: v18.x.x or higher (v20+ recommended)
# Check npm
npm --version
# Expected: 9.x.x or higher
# Check TypeScript (install globally if missing)
npx tsc --version
# Expected: Version 5.x.x
# Check git (useful for version control)
git --version
# Expected: git version 2.x.xIf Node.js is missing or outdated, install it from nodejs.org or use a version manager like nvm:
# Install nvm (if you don't have it)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
# Install and use Node 20
nvm install 20
nvm use 20Project Setup
Create a fresh project directory. We will use this throughout the course, adding files as we build increasingly complex servers.
# Create the project directory
mkdir mcp-learning && cd mcp-learning
# Initialize a new npm project
npm init -y
# Install TypeScript as a dev dependency
npm install -D typescript
# Install the Node.js types
npm install -D @types/nodeYour package.json should now list typescript and @types/node in devDependencies.
TypeScript Configuration
MCP servers use modern TypeScript features. Create a tsconfig.json in your project root with these settings:
{
"compilerOptions": {
// Target Node.js 18+ runtime
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
// Output directory for compiled JavaScript
"outDir": "./dist",
"rootDir": "./src",
// Strict mode catches bugs before runtime
"strict": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
// Enable source maps for debugging
"sourceMap": true,
"declaration": true,
// Allow JSON imports (useful for config files)
"resolveJsonModule": true,
"esModuleInterop": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}Let us break down the critical settings:
target: "ES2022"— Enables modern features like top-level await, which MCP servers commonly use.module: "Node16"— Uses Node.js's native ESM module system. The MCP SDK is distributed as ESM, so this is required.strict: true— Catches null reference errors, implicit any types, and other common bugs at compile time. Never turn this off.
You also need to tell Node.js your project uses ESM. Open package.json and add the type field:
{
"name": "mcp-learning",
"version": "1.0.0",
"type": "module", // <-- Add this line
"scripts": {
"build": "tsc",
"start": "node dist/index.js"
},
// ... rest of package.json
}Key Takeaway: The
"type": "module"field in package.json is mandatory. Without it, Node.js treats your files as CommonJS and the MCP SDK imports will fail with confusing errors.
Installing the MCP SDK
The official MCP TypeScript SDK provides everything you need: server and client classes, transport implementations, type definitions, and utility functions.
# Install the MCP SDK
npm install @modelcontextprotocol/sdkThat is it. One package. It includes:
McpServer— The class you will use to create servers. Handles initialization, capability registration, and message routing.StdioServerTransport— Connects your server to stdin/stdout for local development.SSEServerTransportandStreamableHTTPServerTransport— For HTTP-based deployments (later in the course).- Full TypeScript types for every MCP message, capability, and primitive.
Create a src directory and a minimal file to verify the import works:
# Create the source directory
mkdir src
# Create a test file: src/index.ts// src/index.ts — Verify the SDK imports correctly
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
// If this compiles without errors, your setup is correct
console.log("MCP SDK imported successfully");
console.log("McpServer:", typeof McpServer);
console.log("StdioServerTransport:", typeof StdioServerTransport);Build and run it:
# Compile TypeScript to JavaScript
npm run build
# Run the compiled output
npm start
# Expected output:
# MCP SDK imported successfully
# McpServer: function
# StdioServerTransport: functionIf you see those three lines, your project is correctly configured. If you get errors, check the Troubleshooting section below.
The MCP Inspector
The MCP Inspector is a developer tool that connects to your server and lets you interact with it visually. Think of it as Postman for MCP — you can list tools, call them, read resources, and see the raw JSON-RPC messages going back and forth.
# Run the inspector (no install needed, npx downloads it)
npx @modelcontextprotocol/inspectorThis launches a web UI (usually at http://localhost:6274) where you can:
- Point it at your server — enter the command to launch your server (e.g.,
node dist/index.js). - See the initialization handshake — watch the capability negotiation happen in real time.
- List and call tools — see every tool the server exposes, fill in parameters, and execute calls.
- Read resources — browse available resources and view their contents.
- View raw messages — see the exact JSON-RPC messages flowing between client and server.
You will use the Inspector constantly throughout this course. Bookmark the command.
Try It Yourself: Run
npx @modelcontextprotocol/inspectornow. You will not have a server to connect yet (we build that in the next module), but familiarize yourself with the UI. Click around, look at the different tabs. When we build our first server, you will already know the tool.
Claude Desktop Configuration
Claude Desktop is an MCP host. You can configure it to connect to your custom MCP servers. The configuration lives in a JSON file:
# macOS
~/Library/Application Support/Claude/claude_desktop_config.json
# Windows
%APPDATA%\Claude\claude_desktop_config.json
# Linux
~/.config/Claude/claude_desktop_config.jsonOpen (or create) this file. The structure looks like this:
{
"mcpServers": {
"my-first-server": {
"command": "node",
"args": ["/absolute/path/to/mcp-learning/dist/index.js"],
"env": {
"SOME_API_KEY": "optional-environment-variables"
}
}
}
}Let us break down each field:
"my-first-server"— A name you choose. It appears in Claude Desktop's server list.command— The executable to run. For TypeScript servers compiled to JavaScript, this isnode.args— Arguments passed to the command. Use the absolute path to your compiled JavaScript file. Relative paths will break.env— Optional. Environment variables passed to the server process. Useful for API keys and configuration.
Do not add this config yet — we do not have a working server. In the next module, you will build one and come back here to wire it up. For now, just know where the file lives and what the format looks like.
Key Takeaway: Claude Desktop uses stdio transport. It spawns your server as a child process and communicates over stdin/stdout. That is why the config specifies a
commandandargs, not a URL. The server runs locally on your machine.
Verify Everything Works
Run through this checklist to confirm your environment is ready. Each step should succeed before you move on.
# 1. TypeScript compiles without errors
cd /path/to/mcp-learning
npm run build
# Expected: No errors. dist/ directory created with index.js
# 2. The compiled server runs
npm start
# Expected: "MCP SDK imported successfully"
# 3. MCP Inspector launches
npx @modelcontextprotocol/inspector
# Expected: Web UI opens at http://localhost:6274
# 4. You know where Claude Desktop config lives
# macOS: ls ~/Library/Application\ Support/Claude/
# Linux: ls ~/.config/Claude/
# Windows: dir %APPDATA%\Claude\If all four pass, you are ready to build your first MCP server in the next module.
Troubleshooting
ERR_MODULE_NOT_FOUND or Cannot find module
This usually means one of two things:
- Missing
"type": "module"in package.json. Without this, Node.js treats.jsfiles as CommonJS and ESM imports fail. - Wrong import path. The MCP SDK requires full subpath imports. You must write
@modelcontextprotocol/sdk/server/mcp.js, not just@modelcontextprotocol/sdk. The.jsextension is required even though the source is TypeScript.
TypeScript errors about module resolution
If you see errors like “Cannot find module” in TypeScript but not at runtime, check that moduleResolution is set to "Node16" in tsconfig.json. The older "node" setting does not understand package.json exports maps, which the MCP SDK uses.
Inspector will not connect to server
- Make sure your server is not writing anything to stdout except MCP messages. Any
console.login a running MCP server will corrupt the stdio transport. Useconsole.errorfor debug logging (writes to stderr, which does not interfere). - Make sure you are pointing the Inspector at the compiled
.jsfile, not the.tssource.
Claude Desktop does not show the server
- Restart Claude Desktop after editing the config file. It only reads the config at startup.
- Use absolute paths in the
argsarray. Relative paths resolve from Claude Desktop's working directory, which is not your project folder. - Check Claude Desktop's logs for error messages. On macOS:
~/Library/Logs/Claude/.
Common Mistakes
- Using
console.login MCP servers. This is the number one beginner mistake. MCP servers communicate over stdout. Aconsole.loginjects random text into the JSON-RPC stream and breaks everything. Always useconsole.errorfor debug output — it goes to stderr, which is separate. - Forgetting the
.jsextension in imports. When using ESM with TypeScript, you writeimport ... from "./myfile.js"even though the source file ismyfile.ts. TypeScript will find the.tsfile during compilation, and Node.js will find the.jsfile at runtime. - Using CommonJS (
require) instead of ESM (import). The MCP SDK is ESM-only. If you seerequire is not defined, you are accidentally in CommonJS mode. Check for"type": "module"in package.json. - Relative paths in Claude Desktop config. Always use absolute paths.
./dist/index.jswill not work because the working directory is not what you expect.
Your development environment is ready. You have Node.js, TypeScript, the MCP SDK, the Inspector, and you know where Claude Desktop's config lives. In the next module, you will write your first MCP server from scratch — a real, working server that registers a tool and handles requests.