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).