bearer-mcp-server
# bearer-mcp-server
A **production-style** [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server with **bearer token authentication**, written in TypeScript with the official [`@modelcontextprotocol/sdk`](https://github.com/modelcontextprotocol/typescript-sdk).
It demonstrates all three core MCP primitives — **tools**, **resources**, and **prompts** — themed as a **developer platform API** with mock data (projects, deployments, API keys, metrics, logs, diagnostics).
Compatible with MCP protocol versions **2025-11-25** and **2026-07-28**.
It supports two transports out of the box:
- **stdio** — for desktop clients (Claude Desktop, MCP Inspector launching a subprocess). No auth.
- **Streamable HTTP** — for HTTP-based clients, with session management and bearer token authentication.
---
## What's inside
### Tools (model-controlled actions)
| Tool | Description |
|------|-------------|
| `echo` | Echoes text back — a connectivity and auth check. |
| `search_projects` | Search projects by name, language, status, or tags with pagination. |
| `get_project` | Get a single project by ID with full details including owner info. |
| `create_project` | Create a new project in the platform. |
| `deploy_service` | Trigger a deployment pipeline to a target environment. |
| `list_api_keys` | List API keys for a project (keys are masked). |
| `rotate_api_key` | Rotate (regenerate) an API key — full key shown only here. |
| `get_metrics` | Get 24-hour usage and performance metrics for a project. Returns **structured output**. |
| `search_logs` | Full-text search across simulated log entries with level/project filters. |
| `run_diagnostic` | Run a comprehensive health diagnostic on a project. Returns **structured output**. |
### Resources (application-controlled, read-only data)
| URI | Description |
|-----|-------------|
| `config://server` | Static JSON server config, version, auth mode, and feature flags. |
| `docs://api-reference` | Markdown API reference for the mock developer platform. |
| `projects://{id}` | Templated resource backed by mock project store (20+ projects), with **listing**. |
| `projects://{id}/metrics` | Metrics sub-resource for a project. |
| `users://{id}` | Templated user profile resource, with **listing**. |
| `status://system` | Live system status — services, regions, and active incidents. |
### Prompts (user-controlled message templates)
| Prompt | Arguments | Description |
|--------|-----------|-------------|
| `debug_deployment` | `projectName`, `errorMessage`, `environment` | Ask the model to diagnose a failed deployment. |
| `write_api_docs` | `endpoint`, `language`, `includeExamples` | Ask the model to generate API documentation. |
| `review_config` | `configType`, `configYaml` | Ask the model to review a configuration for security and correctness. |
| `incident_postmortem` | `service`, `severity`, `summary`, `duration` | Ask the model to draft a blameless postmortem. |
---
## Quick start
```bash
# 1. Install dependencies
npm install
# 2. Build the TypeScript
npm run build
# 3a. Run over Streamable HTTP (with bearer auth)
npm start
# 3b. ...or run over stdio for desktop clients
npm run start:stdio
```
> **Requires Node.js >= 18.**
### Development (no build step, auto-reload)
```bash
npm run dev:stdio # stdio transport with tsx watch
npm run dev:http # HTTP transport with tsx watch
```
---
## Authentication
The HTTP transport requires a **Bearer token** on all `/mcp` requests:
```
Authorization: Bearer <token>
```
The `/health` endpoint is exempt from authentication.
### Configuring tokens
**Option 1: Environment variable (simple)**
```bash
# macOS / Linux
MCP_BEARER_TOKENS=sk_abc123,sk_def456 npm start
# Windows PowerShell
$env:MCP_BEARER_TOKENS="sk_abc123,sk_def456"; npm start
```
**Option 2: Token file (rich — with scopes and names)**
```json
[
{ "token": "sk_abc123", "name": "ci-pipeline", "scopes": ["read:*", "write:deployments"] },
{ "token": "sk_def456", "name": "readonly-dashboard", "scopes": ["read:*"] }
]
```
```bash
MCP_TOKEN_FILE=./tokens.json npm start
```
**Option 3: Default dev token (zero-config)**
When neither `MCP_BEARER_TOKENS` nor `MCP_TOKEN_FILE` is set, a single dev token is available:
```
mcp-dev-token-0123456789abcdef
```
### Disabling authentication
```bash
MCP_REQUIRE_AUTH=false npm start
```
> ⚠️ Only disable auth for local testing behind trusted networks.
### stdio transport
Authentication is **not enforced** on the stdio transport — it runs as a local subprocess spawned by the MCP client.
---
## Testing
Run the local smoke test to build the server, start it over stdio, and verify the expected tools, resources, resource templates, and prompts:
```bash
npm run test:smoke
```
### Testing with the MCP Inspector
The [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is the easiest way to explore the server:
```bash
# Launches the Inspector and this server (stdio) together
npm run inspect
```
For the **HTTP** transport, start the server (`npm run start:http`) then open the Inspector and connect with:
- **Transport type:** `Streamable HTTP`
- **URL:** `http://127.0.0.1:3000/mcp`
- **Headers:** Add `Authorization: Bearer mcp-dev-token-0123456789abcdef`
---
## HTTP transport details
| Method | Path | Purpose |
|--------|------|---------|
| `POST` | `/mcp` | JSON-RPC requests (`initialize` + all subsequent calls). Auth required. |
| `GET` | `/mcp` | Server-Sent Events stream for server-to-client notifications. Auth required. |
| `DELETE` | `/mcp` | Terminate a session. Auth required. |
| `GET` | `/health` | Plain health check (not part of MCP). No auth required. |
Sessions are tracked via the `Mcp-Session-Id` response/request header. The HTTP server binds to `127.0.0.1` by default, and the port defaults to **3000**. Both can be overridden:
```bash
PORT=3100 npm run start:http # macOS / Linux
HOST=0.0.0.0 PORT=3100 npm run start:http # macOS / Linux, public interface
$env:PORT=3100; npm run start:http # Windows PowerShell
$env:HOST="0.0.0.0"; npm run start:http # Windows PowerShell, public interface
```
### Example: raw HTTP handshake with `curl`
```bash
curl -i -X POST http://127.0.0.1:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer mcp-dev-token-0123456789abcdef" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'
```
The response includes an `Mcp-Session-Id` header — pass it back as a request header on subsequent calls.
### Testing auth failure
Omitting the token or using an invalid one returns:
```json
{
"jsonrpc": "2.0",
"error": {
"code": -32001,
"message": "Unauthorized: missing Bearer token in Authorization header"
},
"id": null
}
```
---
## Deployment
### Docker / Google Cloud Run
```bash
docker build -t bearer-mcp-server .
docker run -p 8080:8080 \
-e MCP_BEARER_TOKENS=your_token_here \
bearer-mcp-server
```
Cloud Run sets the `PORT` environment variable and requires the container to listen on `0.0.0.0:$PORT`. The server detects Cloud Run via `K_SERVICE` and auto-binds appropriately.
### Vercel
The `api/` directory contains serverless MCP and health handlers. Deploy with the Vercel Git integration or CLI — set the *Framework Preset* to **Other** and leave *Build Command* / *Output Directory* empty.
---
## Using it with Claude Desktop
Add this to your `claude_desktop_config.json` (use the **absolute** path to `dist/stdio.js`):
```json
{
"mcpServers": {
"bearer-mcp-server": {
"command": "node",
"args": ["C:\\Users\\Shylendra\\git\\bearer-mcp-server\\dist\\stdio.js"]
}
}
}
```
Restart Claude Desktop, and the server's tools, resources, and prompts will appear.
---
## Project layout
```text
src/
├── server.ts # createServer() factory + ServerCatalog
├── tools/ # Tool definitions (split by domain)
│ ├── index.ts # registerTools() aggregator
│ ├── projects.ts # search_projects, get_project, create_project
│ ├── deployments.ts # deploy_service
│ ├── api-keys.ts # list_api_keys, rotate_api_key
│ ├── monitoring.ts # get_metrics, search_logs, run_diagnostic
│ └── echo.ts # echo tool
├── resources/
│ └── index.ts # registerResources() — all 6 resources
├── prompts/
│ └── index.ts # registerPrompts() — all 4 prompts
├── auth/
│ ├── middleware.ts # Express bearer-token middleware
│ └── tokens.ts # Token store, validation, loading
├── data/ # Mock data stores
│ ├── projects.ts # 20 mock projects
│ ├── users.ts # 5 mock user profiles
│ ├── api-keys.ts # 8 mock API keys
│ ├── metrics.ts # Deterministic metrics generator
│ ├── logs.ts # Deterministic log generator
│ └── system.ts # System status with incidents
├── stdio.ts # stdio transport entry point
├── http.ts # Streamable HTTP transport entry point (with auth)
├── banner.ts # ANSI startup banner
└── logging.ts # Structured JSON logging with redaction
api/
├── mcp.ts # Vercel serverless MCP handler (with auth)
└── health.ts # Vercel health check
index.ts # Root HTTP router (node:http)
```
## Environment variables
| Variable | Default | Description |
|----------|---------|-------------|
| `PORT` | `3000` | HTTP listen port |
| `HOST` | `127.0.0.1` | Listen address (Cloud Run: auto `0.0.0.0`) |
| `MCP_REQUIRE_AUTH` | `true` | Enforce bearer token auth on HTTP |
| `MCP_BEARER_TOKENS` | — | Comma-separated valid tokens |
| `MCP_TOKEN_FILE` | — | Path to JSON file with token definitions |
| `MCP_CORS_ORIGIN` | `*` | CORS origin for browser access |
| `MCP_LOG_BODY_LIMIT` | `4000` | Max chars for request/response body logging |
## Notes
- **Authentication is enforced on HTTP transport by default.** Use `MCP_REQUIRE_AUTH=false` to disable for local testing.
- When using stdio, **never** write to `stdout` — it is reserved for the JSON-RPC protocol. Diagnostics go to `stderr` (`console.error`).
- Authorization headers are redacted in log output.
## License
MIT
TDQS
Scored across 10 tools
Each tool targets a distinct resource and action: projects (create, get, search), deployments, API keys (list, rotate), metrics, logs, diagnostics, and connectivity. There is no overlap or ambiguity between tool purposes.
Most tools follow a clear verb_noun snake_case pattern (create_project, search_logs, rotate_api_key). The only deviation is 'echo', which lacks a noun object, but this is a minor utility and does not undermine the overall pattern.
With 10 tools, the server is well-scoped for a platform management API. Each tool covers a distinct aspect of project and deployment management, observability, and diagnostics, without unnecessary bloat.
The server covers project creation, retrieval, search, and deployment, but lacks update/delete operations for projects and API key creation/deletion. Deployment status tracking is also missing. These are notable gaps that agents may need to work around.