mcp-server-typescript-tutorial

AdemolaAri/mcp-server-typescript-tutorial

3.3

If you are the rightful owner of mcp-server-typescript-tutorial and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.

A Model Context Protocol (MCP) server provides a structured interface for models to interact with application resources, execute tools, and follow prompts with specific sampling configurations.

Tools
2
Resources
0
Prompts
0

Building an MCP server with the TypeScript SDK — a short tutorial

This tutorial explains what a Model Context Protocol (MCP) server is, the core concepts that make one useful (resources, tools, prompt, sampling), and how to run and inspect the sample TypeScript server in this repo.

Checklist

  • Explain what an MCP server is and its purpose
  • Describe the four core parts (resources, tools, prompt, sampling)
  • Break down the repository and src/server.ts (where the components are registered)
  • Show how to run the server locally, connect with the MCP Inspector, and run/debug from VS Code using a .vscode/mcp.json setup

What is an MCP server?

An MCP server exposes a structured HTTP/JSON surface that a model (or model-driven agent) can use to: read and update application resources (data), call programmatic tools (actions), and follow a prompt/instruction with specified sampling settings. The server declares the resources and tools the model may access, supplies the prompt templates and sampling configuration used when invoking the model, and optionally logs traces for inspection and debugging.

Why use MCP?

  • Makes model interactions auditable and debuggable.
  • Keeps model-accessible data and actions explicit and typed.
  • Separates domain code (resources/tools) from model prompts and sampling.

Core parts

  • Resources

    • What: structured data endpoints (e.g., users, documents, tickets).
    • Role: let the model query and modify application state in a predictable way.
    • Implementation notes: resources typically implement read/list/create/update handlers and are wired to persistent storage (a JSON file or DB in examples).
  • Tools

    • What: named functions the model can call with structured inputs and receive structured outputs.
    • Role: perform actions the model cannot directly do (send email, call external APIs, run calculations), while keeping them safe and auditable.
  • Prompt / Instruction

    • What: the templates or instruction strings that guide model behavior (when to call tools, how to format outputs).
    • Role: shapes decision-making and output format; often injects resource snapshots or recent context.
  • Sampling / Invocation config

    • What: model invocation parameters (temperature, max tokens, top_p, stop sequences).
    • Role: controls randomness, response length, and determinism of the model.

Repository layout (what to open)

  • src/server.ts — main TypeScript registration file. This is where resources, tools, prompts, and sampling are declared and the HTTP server is started.
  • build/server.js — compiled output (if you run the TypeScript build).
  • src/data/users.json and build/data/users.json — example resource data used by the sample users resource.
  • package.json and tsconfig.json — build and runtime scripts/config.

High-level walkthrough: src/server.ts

Below are the conceptual pieces you will find in src/server.ts. The actual variable and function names may differ, but the mapping is the same.

Resources (example: users)

  • Declaration: a call that registers a resource named users and supplies handlers for CRUD operations.
  • What to look for: a registerResource or server.resource('users', {...}) call, handlers that read/write src/data/users.json, and any validation code.
  • Why it matters: the model will query this resource to get facts about users and will request mutations through the resource contract rather than making arbitrary changes.

Tools (example: sendEmail or lookupProfile)

  • Declaration: a registerTool or server.tool('name', handler) call that exposes a function the model can invoke.
  • What to look for: input shape (type/interface), the handler body, error handling, and whether the tool logs requests instead of performing side effects (recommended for dev).
  • Why it matters: tools are the safe bridge from intent to action — make them explicit and testable.

Prompt / Instruction

  • Declaration: a string or template registered as the server's prompt (often named default or assistant), sometimes with placeholder variables for resource snapshots.
  • What to look for: template text, injected variables, and how the server builds the prompt before model invocation.
  • Why it matters: the prompt dictates whether the model should call a tool, update a resource, or return text directly.

Sampling / Model options

  • Declaration: an object or call that sets temperature, max_tokens, top_p, and similar parameters.
  • What to look for: a sampling or invokeOptions object passed to the SDK's model call.
  • Why it matters: small temperature values (0–0.3) help determinism when you expect the model to choose actions precisely.

How to build and run the server

Install dependencies:

npm install

Build (compile TypeScript):

npm run build    # assumes package.json has a build script that runs tsc

Run the compiled server:

node build/server.js

Quick dev mode (run TypeScript directly):

npm run dev      # recommended to map to ts-node src/server.ts or nodemon

Common port: check src/server.ts for the actual listen port (commonly 3000).

Using the MCP Inspector

  1. Start the server (see commands above).
  2. Open your MCP Inspector UI.
  3. Connect to the server URL (for example http://localhost:3000).

The Inspector should display registered resources, available tools and their input shapes, prompt templates, sampling settings, and recent invocation traces. Use the Inspector to run sample calls and observe how the model interacts with resources and tools.

VS Code integration: .vscode/mcp.json

You can add a small .vscode/mcp.json file to define a local MCP run configuration the MCP extension understands. Adjust fields to match your package.json scripts and port.

Example .vscode/mcp.json:

{
	"name": "local-mcp",
	"command": "npm run dev",
	"cwd": "${workspaceFolder}",
	"port": 3000,
	"inspect": true,
	"env": { "NODE_ENV": "development" }
}

Notes:

  • Set command to a script that starts the dev server (for example a dev script that runs ts-node src/server.ts).
  • Use port to tell the IDE/inspector where the server will be available.

Server component examples and what to inspect in the code

  • users resource

    • What to expect in code: a registration like server.resource('users', { list, read, create, update }) or similar. Handlers will read and write src/data/users.json and perform basic validation.
    • Developer tip: use optimistic locking or simple validation to keep concurrent writes safe for demo servers.
  • sendEmail tool (or equivalent)

    • What to expect: a server.tool('sendEmail', async (args) => { ... }) registration. The handler may log the email instead of sending during development.
    • Developer tip: mock external APIs in dev and log intent instead of sending real messages.
  • prompt template

    • What to expect: a constant or registration that contains the instruction template and injection points for resource snapshots.
    • Developer tip: sanitize and truncate long resource fields when injecting into prompts.
  • sampling options

    • What to expect: an object such as { temperature: 0.2, max_tokens: 512 } used when calling the model SDK.
    • Developer tip: start with low temperature for action-driven flows.

Safety & best practices

  • Keep tools constrained, idempotent, and safe in development.
  • Validate all inputs server-side — do not trust model outputs to be well-formed.
  • Use low temperature for deterministic control flows.
  • Log traces and use the Inspector to replay or step through model decisions.

Quick reference commands

npm install
npm run build
node build/server.js
# or during development
npm run dev