TypeScript MCP Server — Railway Deployment
A production-ready TypeScript MCP server template built with Express and the official MCP SDK. Ships with API key authentication, structured logging, health monitoring, and Railway deployment config.
What's Included
- MCP Streamable HTTP transport via
@modelcontextprotocol/sdk(stateless mode) - API key authentication — checks
X-API-Keyheader - Environment validation with Zod — exits on bad config
- Pino structured logging — pretty in dev, JSON in production
- Health endpoint at
GET /health - 3 example MCP tools:
analyzeText,fetchUrlMetadata,markdownToText - Multi-stage Dockerfile — production image omits dev deps
- Docker Compose with health check
- Railway deployment ready — set
MCP_API_KEYand push
Project Structure
├── src/
│ ├── tools/
│ │ ├── analyzeText.ts
│ │ ├── fetchUrlMetadata.ts
│ │ └── markdownToText.ts
│ ├── auth.ts
│ ├── config.ts
│ ├── health.ts
│ ├── logger.ts
│ └── server.ts
├── tests/
│ ├── analyzeText.test.ts
│ ├── auth.test.ts
│ ├── health.test.ts
│ └── markdownToText.test.ts
├── .env.example
├── .gitignore
├── Dockerfile
├── docker-compose.yml
├── jest.config.ts
├── package.json
├── tsconfig.json
└── tsconfig.test.json
Quick Start
cp .env.example .env
# Set MCP_API_KEY to a strong secret (min 16 chars)
npm install
npm run dev
Server starts at http://localhost:3000/mcp.
Deploy to Railway
- Push repo to GitHub
- New Railway project → Deploy from GitHub repo
- Set
MCP_API_KEYin Railway Variables - Railway detects Dockerfile and deploys automatically
Your endpoint: https://<project>.up.railway.app/mcp
Authentication
X-API-Key: your-api-key-here
Requests without a valid key return 401 Unauthorized.
Configuration
| Variable | Required | Default | Description |
|---|---|---|---|
MCP_API_KEY | ✅ | — | API key, min 16 chars |
PORT | 3000 | Server port | |
NODE_ENV | development | Environment | |
LOG_LEVEL | info | Pino log level | |
REQUEST_TIMEOUT_MS | 30000 | Outbound HTTP timeout |
Adding a New Tool
- Create
src/tools/myTool.ts - Export your tool function with Zod schema
- Register in
src/server.ts
Testing
npm test
npm run test:coverage
Production Checklist
-
MCP_API_KEYis cryptographically random (min 32 chars) -
NODE_ENV=productionset in deployment - Server behind TLS-terminating proxy
-
/healthwired to load balancer health checks - Docker image built from
runnerstage express typescript utilities typescript mcp railway express http-transport api-key-auth pino zod docker