Project Setup with the TypeScript SDK

+15 Mana ✨

Introduction

The Model Context Protocol (MCP) allows you to build servers that expose tools, resources, and prompts to LLM clients like Claude Desktop. In this lesson, you will install the official TypeScript SDK, create your first MCP server, and connect it to Claude Desktop.

Key Concepts

  • MCP Server: A process that exposes capabilities (tools, resources, prompts) to an MCP client via the Model Context Protocol.
  • McpServer class: The main entry point in the @modelcontextprotocol/sdk package for building servers.
  • Transport: The communication layer that carries MCP messages between server and client.
  • StdioServerTransport: A transport that uses standard input/output, ideal for local server processes managed by a client like Claude Desktop.

Real World Context

When you build an MCP server, you are creating a bridge between an AI assistant and your own tools and data. For example, a DevOps team might build an MCP server that exposes deployment tools, letting Claude trigger deployments or check service status through natural conversation.

Deep Dive

Start by initializing a new Node.js project and installing the required dependencies.

The following command sets up a new project with the MCP SDK and Zod for input validation:

bash
mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod

This creates a minimal project with the two packages you need: the MCP server SDK and Zod for schema definitions.

Now create the server entry point. The following code initializes an MCP server with metadata and connects it to a stdio transport:

typescript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';

const server = new McpServer({
  name: 'my-server',
  version: '1.0.0'
});

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

The McpServer constructor takes a server info object with name and version. These fields identify your server to clients during the initialization handshake. The StdioServerTransport reads from stdin and writes to stdout, which is the standard way Claude Desktop communicates with local MCP servers.

To connect this server to Claude Desktop, you need to edit the Claude Desktop configuration file. On macOS this lives at ~/Library/Application Support/Claude/claude_desktop_config.json, and on Windows at %APPDATA%\Claude\claude_desktop_config.json.

Here is an example configuration that tells Claude Desktop how to launch your server:

json
{
  "mcpServers": {
    "my-server": {
      "command": "node",
      "args": ["path/to/server.js"]
    }
  }
}

Each entry under mcpServers defines a server by name. The command field is the executable to run, and args passes arguments to it. Claude Desktop will spawn this process and communicate with it over stdio.

Common Pitfalls

  • Logging to stdout: Never use console.log() in an MCP server using stdio transport. Stdout is reserved for MCP protocol messages. Use console.error() for debug output instead.
  • Missing await on connect: The server.connect(transport) call is async. Forgetting to await it can cause the server to exit before it starts listening.
  • Wrong path in config: The args path in claude_desktop_config.json must point to the compiled JavaScript file, not the TypeScript source.

Best Practices

  • Always specify a semantic version string in your server metadata so clients can track compatibility.
  • Use TypeScript with strict mode for type safety across your server implementation.
  • Keep your server entry point minimal and import handler logic from separate modules.

Summary

You learned how to install the @modelcontextprotocol/sdk package, create an McpServer instance with name and version metadata, connect it to a StdioServerTransport, and configure Claude Desktop to launch your server. This foundation supports everything you will build in the following lessons.

Code Examples

typescript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';

const server = new McpServer({
  name: 'my-server',
  version: '1.0.0'
});

const transport = new StdioServerTransport();
await server.connect(transport);
json
{
  "mcpServers": {
    "my-server": {
      "command": "node",
      "args": ["path/to/server.js"]
    }
  }
}
✓ Completed