Skip to main content
Glama
README.md
# mcp-lab

A hands-on lab for learning the **Model Context Protocol (MCP)** in TypeScript.

MCP is an open standard that lets AI apps (like Claude Code or Claude Desktop)
connect to external programs in a uniform way — think of it as **"USB-C for AI
tools"**: one protocol, many pluggable capabilities.

---

## The mental model

```
┌─────────────┐        ┌──────────────┐        ┌─────────────────┐
│    HOST     │        │   CLIENT     │        │     SERVER      │
│ (Claude     │◄──────►│ (one per     │◄──────►│  (this repo:    │
│  Code, etc.)│        │  server, in  │        │   mcp-lab)      │
│             │        │  the host)   │        │                 │
└─────────────┘        └──────────────┘        └─────────────────┘
     the AI app          speaks the             exposes tools,
                         protocol               resources, prompts
```

- **Host** — the AI application the user interacts with.
- **Client** — the connector the host spins up for each server.
- **Server** — a program (this repo) that exposes capabilities.
- **Transport** — how client and server talk. This lab uses **stdio**
  (the host launches the server and pipes JSON-RPC over stdin/stdout).
  The other common transport is **HTTP**.

## The three things a server can expose

| Capability    | Who triggers it | Analogy            | Example here            |
|---------------|-----------------|--------------------|-------------------------|
| **Tool**      | the model       | a POST / an action | `add`, `greet`          |
| **Resource**  | the app/model   | a GET / a file     | `lab://about`           |
| **Prompt**    | the user        | a slash command    | `explain-like-im-five`  |

---

## Setup

```bash
npm install
```

Requires **Node 18+** (you have v22 ✅).

## Run it

**Option A — the MCP Inspector (best for learning).** A web UI that connects to
your server so you can click every tool, resource, and prompt by hand:

```bash
npm run inspect
```

Then open the URL it prints. Try the `add` tool — pass `a: 2`, `b: 3`.

**Option B — connect it to Claude Code.** Register the server so Claude can use
its tools directly. From this folder:

```bash
claude mcp add mcp-lab -- npx tsx src/server.ts
```

Then ask Claude: *"Use the add tool to add 21 and 21."*

**Option C — connect it to Claude Desktop.** Add this to your
`claude_desktop_config.json` (Settings → Developer → Edit Config), using an
**absolute path**, then restart Claude Desktop:

```json
{
  "mcpServers": {
    "mcp-lab": {
      "command": "npx",
      "args": ["tsx", "C:\\CLAUDE\\Project\\mcp-lab\\src\\server.ts"]
    }
  }
}
```

---

## What's in here

- `src/server.ts` — the core server, heavily commented. Read it top to bottom.
  Exposes `add`, `multiply`, `greet`, the `lab://about` resource, and the
  `explain-like-im-five` prompt.
- `src/weather-server.ts` — a second server that calls a **real web API**
  (free, no key). Shows `fetch()` inside a tool and clean error handling with
  `isError: true`. Inspect it with:

  ```bash
  npx @modelcontextprotocol/inspector tsx src/weather-server.ts
  ```

## The golden rule of stdio servers

**Never use `console.log()`** in a stdio MCP server — stdout is the protocol
channel and logging there corrupts messages. Use `console.error()` (stderr) for
debugging instead.

---

## Exercises (learn by extending)

1. **Add a `multiply` tool.** Copy the `add` block, change the math.
2. **Add a tool that calls a real API** (e.g. fetch the weather) — this is where
   MCP gets powerful. Use `fetch()` inside the handler.
3. **Make a dynamic resource** whose content depends on the URI (look up
   `ResourceTemplate` in the SDK).
4. **Return an error** from a tool by setting `isError: true` in the result and
   see how the host reacts.

## Where to go next

- Spec & docs: https://modelcontextprotocol.io
- TypeScript SDK: https://github.com/modelcontextprotocol/typescript-sdk
- Inspector: https://github.com/modelcontextprotocol/inspector