Skip to main content
Glama
piyushgithub15

Streamable MCP Server

README.md
# Streamable MCP Server

A [Model Context Protocol](https://modelcontextprotocol.io) server written in TypeScript, exposed over the **Streamable HTTP** transport (the modern replacement for the older HTTP+SSE transport).

## Features

- Streamable HTTP transport at `POST/GET/DELETE /mcp`, with per-session state (via the `mcp-session-id` header)
- Example tools: `echo`, `add`, `get-time`
- Example resource: `info://server`
- `GET /healthz` for container/orchestrator health checks
- Multi-stage, non-root Dockerfile

## Project layout

```
src/
  server.ts   # McpServer factory: tools & resources are registered here
  index.ts    # Express app wiring the Streamable HTTP transport + session management
```

## Local development

```bash
npm install
npm run dev      # tsx watch, restarts on change
```

Or build and run compiled JS:

```bash
npm run build
npm start
```

The server listens on `http://localhost:3000/mcp` by default (override with `PORT`).

## Trying it with curl

Initialize a session (note the `mcp-session-id` response header, needed for follow-up requests):

```bash
curl -i -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl-test","version":"1.0"}}}'
```

Then, using the returned session id:

```bash
SESSION=<mcp-session-id from above>

curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "mcp-session-id: $SESSION" \
  -d '{"jsonrpc":"2.0","method":"notifications/initialized"}'

curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "mcp-session-id: $SESSION" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"add","arguments":{"a":21,"b":21}}}'
```

## Docker

Build the image:

```bash
docker build -t streamable-mcp-server .
```

Run it:

```bash
docker run -d -p 3000:3000 --name mcp-server streamable-mcp-server
```

Check health:

```bash
curl http://localhost:3000/healthz
```

## Adding your own tools

Add new `server.registerTool(...)` calls in `src/server.ts`. Each new session gets a freshly created `McpServer`, so any per-session state should live inside the factory function's closure or be looked up externally (e.g. a database) rather than stored in module-level globals.