# MCP Server Template
A production-ready template for building Model Context Protocol (MCP) servers with TypeScript.
## Features
- **MCP SDK 1.24.3** - Latest SDK with 2025-11-25 spec support
- **Dual Transport** - Stdio (Claude Desktop) and HTTP (cloud deployment)
- **OAuth 2.1 Foundations** - Protected resource metadata, bearer token structure
- **SQLite Caching** - TTL-based caching with sql.js (WebAssembly)
- **Observability** - Sentry error tracking + OpenTelemetry tracing
- **Security** - PII sanitization, rate limiting, DNS rebinding protection
- **Type Safety** - Strict TypeScript with Zod validation
## Quick Start
```bash
# Clone and install
git clone <this-repo> my-mcp-server
cd my-mcp-server
npm install
# Development mode (hot reload)
npm run dev
# Build and run
npm run build
npm start
# Test with MCP Inspector
npm run inspector
```
## Project Structure
```
src/
├── index.ts # CLI entry point
├── server.ts # MCP server implementation
├── instrumentation.ts # Sentry + OpenTelemetry setup
├── config/
│ └── index.ts # Environment configuration
├── db/
│ ├── database.ts # SQLite connection (sql.js)
│ └── cache.ts # TTL-based caching
├── tools/
│ ├── registry.ts # Tool registration pattern
│ └── examples.ts # Example tool implementations
├── transport/
│ └── http-transport.ts # HTTP with OAuth foundations
├── shared/
│ ├── logger.ts # Structured logging
│ ├── errors.ts # Custom error classes
│ ├── rate-limiter.ts # Per-source rate limiting
│ ├── pii-sanitizer.ts # PII detection/removal
│ └── tracing.ts # OpenTelemetry utilities
└── types/
└── index.ts # TypeScript type definitions
```
## Configuration
Environment variables (prefix with `MCP_SERVER_`):
| Variable | Default | Description |
|----------|---------|-------------|
| `MCP_SERVER_NAME` | `mcp-server-template` | Server name |
| `MCP_SERVER_VERSION` | `0.1.0` | Server version |
| `MCP_SERVER_LOG_LEVEL` | `info` | Log level: debug, info, warning, error |
| `MCP_SERVER_DB_PATH` | `.data/cache.db` | SQLite database path |
| `MCP_SERVER_CACHE_ENABLED` | `true` | Enable/disable caching |
| `MCP_SERVER_CACHE_TTL` | `3600` | Default cache TTL (seconds) |
| `MCP_SERVER_TIMEOUT` | `30000` | Request timeout (ms) |
| `MCP_SERVER_TRANSPORT` | `stdio` | Transport: `stdio` or `http` |
| `MCP_SERVER_PORT` | `3000` | HTTP port (when transport=http) |
| `MCP_SERVER_HOST` | `127.0.0.1` | HTTP host (when transport=http) |
| `MCP_SERVER_SENTRY_DSN` | - | Sentry DSN for error tracking |
| `OTEL_ENABLED` | `false` | Enable OpenTelemetry tracing |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | - | OTLP collector endpoint |
| `MCP_SERVER_DEBUG` | `false` | Debug mode (skips auth) |
## Creating Tools
Tools are registered with the ToolRegistry using Zod schemas:
```typescript
import { z } from 'zod';
import { getToolRegistry } from './tools/registry.js';
// Define input schema
const MyToolInputSchema = z.object({
query: z.string().min(1).describe('Search query'),
limit: z.number().positive().optional().default(10),
});
type MyToolInput = z.infer<typeof MyToolInputSchema>;
// Implement handler
async function myToolHandler(input: MyToolInput) {
// Your implementation here
return {
success: true,
data: { results: [] },
};
}
// Register tool
const registry = getToolRegistry();
registry.register(
'my_tool',
'Description of what this tool does',
MyToolInputSchema,
myToolHandler
);
```
## Transport Modes
### Stdio (Default)
For Claude Desktop and local integrations:
```bash
npm start
```
Add to Claude Desktop config:
```json
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["/path/to/dist/index.js"]
}
}
}
```
### HTTP
For cloud deployment:
```bash
MCP_SERVER_TRANSPORT=http npm start
```
Endpoints:
- `GET /health` - Health check
- `GET /.well-known/mcp` - MCP server metadata
- `GET /.well-known/oauth-protected-resource` - OAuth metadata (RFC 9728)
- `GET /mcp` - SSE stream for server events
- `POST /mcp` - JSON-RPC requests
- `DELETE /mcp` - Close session
## Security Features
### PII Sanitization
Automatically detects and masks sensitive data:
```typescript
import { sanitizePii } from './shared/pii-sanitizer.js';
const safe = sanitizePii('Contact: user@example.com');
// Output: "Contact: [EMAIL]"
```
### Rate Limiting
Per-source rate limiting with exponential backoff:
```typescript
import { getRateLimiter } from './shared/rate-limiter.js';
const limiter = getRateLimiter();
limiter.configure('external-api', {
requestsPerWindow: 100,
windowMs: 60000,
});
await limiter.waitForSlot('external-api');
// Make request...
```
### DNS Rebinding Protection
HTTP transport validates Host headers against allowlist.
## Observability
### Sentry
Error tracking with PII filtering:
```bash
MCP_SERVER_SENTRY_DSN=https://xxx@sentry.io/xxx npm start
```
### OpenTelemetry
Distributed tracing:
```bash
OTEL_ENABLED=true \
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 \
npm start
```
Use tracing utilities:
```typescript
import { withSpan, createApiSpan } from './shared/tracing.js';
const result = await withSpan('my-operation', async (span) => {
span.setAttribute('custom.attr', 'value');
return doWork();
});
```
## Development
```bash
# Type check
npm run check
# Lint
npm run lint
npm run lint:fix
# Format
npm run format
# Test
npm test
npm run test:coverage
# Validate (all checks)
npm run validate
```
## MCP 2025-11-25 Spec Compliance
| Feature | Status |
|---------|--------|
| Tools | ✅ Implemented |
| Resources | 📝 Scaffolded |
| Prompts | 📝 Scaffolded |
| Streamable HTTP | ✅ Implemented |
| .well-known/mcp | ✅ Implemented |
| OAuth 2.1 Foundations | ✅ Scaffolded |
| Tasks | ❌ Not yet |
| Elicitation | ❌ Not yet |
## OAuth 2.1 Implementation
The template includes foundations for OAuth 2.1 per the MCP spec:
1. **Protected Resource Metadata** (RFC 9728) at `/.well-known/oauth-protected-resource`
2. **Bearer token middleware** structure (implement JWT validation)
3. **WWW-Authenticate** headers with resource_metadata reference
4. **Scope checking** structure for tool authorization
To complete OAuth integration:
1. Choose an authorization server (Auth0, Logto, etc.)
2. Implement JWT validation in `bearerAuthMiddleware`
3. Add JWKS fetching and caching
4. Configure scopes per tool
See [MCP Authorization Spec](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization) for details.
## License
MIT
## References
- [MCP Specification](https://modelcontextprotocol.io/specification/2025-11-25)
- [MCP SDK](https://www.npmjs.com/package/@modelcontextprotocol/sdk)
- [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)