Skip to main content
Glama
Axis-Data-Labs

MCP Server Starter

README.md
# MCP Server Starter

A minimal, production-ready starter for building [Model Context Protocol](https://modelcontextprotocol.io) servers in TypeScript. One server definition runs two ways: over stdio for local clients, and over streamable HTTP when you deploy it, with optional bearer-token auth.

## Features

- **Two transports, one definition.** Runs over stdio locally (Claude Code, Claude Desktop) and switches to streamable HTTP when `PORT` is set. Tools live in one place.
- **Optional auth for HTTP.** A shared bearer token, accepted via the `Authorization` header or a `?token=` query param (some hosted clients can only pass a query param).
- **Typed tools.** Inputs are validated with [zod](https://zod.dev), so the model gets a clear schema and you get type safety.
- **Deploy-ready.** Stateless per request, with a `Dockerfile` included. Runs on any container host.
- **Small and readable.** A handful of files, no framework, easy to fork.

## Quick start

```bash
git clone https://github.com/Axis-Data-Labs/mcp-server-starter
cd mcp-server-starter
npm install
cp .env.example .env
```

Run it locally over stdio:

```bash
npm run dev
```

### Connect it to Claude Code

```bash
claude mcp add my-server -- npx tsx /absolute/path/to/mcp-server-starter/src/index.ts
```

Or add it to your client's MCP config:

```json
{
  "mcpServers": {
    "my-server": {
      "command": "npx",
      "args": ["tsx", "/absolute/path/to/mcp-server-starter/src/index.ts"]
    }
  }
}
```

Ask the model to call `echo` or `add` to confirm it works.

## HTTP mode and deploying

Set `PORT` to run the streamable HTTP transport instead of stdio:

```bash
PORT=3000 MCP_AUTH_TOKEN=your-secret npm start
```

The server listens on `POST /mcp`. Point a remote MCP client at `https://your-host/mcp` and send the token as `Authorization: Bearer your-secret` (or `?token=your-secret`). A `Dockerfile` is included, and most container platforms set `PORT` for you, so deploying is usually just pushing the repo.

## Adding a tool

1. Create `src/tools/<name>.ts` and export a `register<Name>Tools(server)` function.
2. Register tools with `server.tool(name, description, zodSchema, handler)`.
3. Call your `register…Tools(server)` from `src/server.ts`.

```ts
server.tool(
  "greet",
  "Greet someone by name.",
  { name: z.string().describe("Who to greet") },
  async ({ name }) => ({ content: [{ type: "text", text: `Hello, ${name}` }] }),
);
```

## Project structure

```
src/
  index.ts        picks the transport (stdio vs HTTP) at startup
  server.ts       builds the server and registers tools
  http.ts         streamable HTTP transport and optional auth
  tools/
    example.ts    example tools, replace with your own
```

## License

MIT. See [LICENSE](LICENSE).

Built and maintained by [Axis Data Labs](https://axisdatalabs.com).