Skip to main content
Glama
README.md
# runtime-mcp

Drop-in MCP server that lets Claude inspect, debug, and hot-fix your running Bun process through conversation.

One line of code. Claude can now see inside your running Bun server — memory, queries, traffic, errors, everything.

```typescript
import { attachMCP } from 'runtime-mcp';
attachMCP({ port: 3100 }); // that's it
```

Your Bun process now speaks [MCP](https://modelcontextprotocol.io/). Connect Claude Desktop, Cursor, or any MCP client and start asking questions about your live app.

## Why

Debugging a running app today means adding logging, restarting, and hoping you guessed the right thing to log. LLMs can read your source code, but they can't see your runtime state — the variable values, the open connections, the slow queries, the memory growth.

runtime-mcp fixes that. It exposes your process internals as MCP resources and tools, so the LLM examines the live patient instead of guessing from the chart.

## Quick Start

### 1. Install

```bash
bun add runtime-mcp
```

### 2. Attach to your server

```typescript
import { serve } from 'bun';
import { attachMCP } from 'runtime-mcp';

const server = serve({
  port: 3000,
  fetch: () => new Response('Hello'),
});

attachMCP({
  port: 3100,
  bind: { server },
});
```

### 3. Connect Claude Desktop

Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "my-app": {
      "url": "http://localhost:3100/sse"
    }
  }
}
```

Restart Claude Desktop. Ask: *"What is this process doing?"*

## What Claude Can See

### Resources (read-only, always available)

| Resource | URI | Description |
|----------|-----|-------------|
| Process info | `runtime://process/info` | PID, uptime, Bun version, entrypoint, env vars |
| Memory | `runtime://process/memory` | RSS, heap used/total, external, array buffers |
| Event loop | `runtime://process/event-loop` | Pending timers, active handles, loop lag |
| HTTP routes | `runtime://server/routes` | All registered routes, active connections, req/min |
| Request log | `runtime://server/requests` | Recent HTTP requests with status, duration, bodies |
| Errors | `runtime://errors/recent` | Uncaught exceptions and unhandled rejections (deduplicated) |
| DB connections | `runtime://db/connections` | Pool state, recent queries, slow queries |
| Module graph | `runtime://modules/graph` | Full dependency tree from entrypoint |
| WebSockets | `runtime://websockets` | Active connections, message counts |
| Variables | `runtime://variables/{path}` | Inspect any bound variable by dot-path |

### Tools (actions Claude can take)

| Tool | Description |
|------|-------------|
| `inspect` | Deep-inspect any reachable object by expression |
| `eval` | Execute JavaScript in the process context |
| `get_source` | Read source files from the running process |
| `intercept_requests` | Capture HTTP traffic matching a glob pattern |
| `intercept_sql` | Capture SQL queries matching a substring |
| `subscribe_events` | Stream real-time events (requests, errors, queries) |
| `heap_snapshot` | Take a V8 heap snapshot, diff against previous |
| `profile` | CPU profile for N milliseconds* |
| `set_breakpoint` | Conditional breakpoints with state capture* |
| `hot_patch` | Replace a module's code at runtime without restart |
| `shell` | Run read-only shell commands in the process cwd |

*\*Requires `node:inspector` — not yet available in Bun ([tracking issue](https://github.com/oven-sh/bun/issues/2445)).*

### Prompts (guided debugging workflows)

| Prompt | Description |
|--------|-------------|
| `debug-endpoint` | Systematically debug a specific HTTP endpoint |
| `find-memory-leak` | Snapshot, wait, diff, identify growing allocations |
| `explain-process` | Full overview of what the process is doing right now |
| `generate-tests` | Watch live traffic and generate test cases from it |
| `optimize-query` | Find slow queries, explain plans, suggest fixes |

## Configuration

```typescript
attachMCP({
  // Transport
  port: 3100,              // MCP server port (default: 3100)
  host: 'localhost',       // Bind address (default: 'localhost')

  // What to expose
  bind: {                  // Objects the LLM can inspect/eval against
    server,
    db,
    config,
  },

  // Access control
  readOnly: false,         // Disable eval, hot_patch, shell (default: true in production)
  allowedTools: undefined, // Whitelist specific tools
  blockedTools: undefined, // Blacklist specific tools

  // Observation tuning
  requestLog: {
    maxSize: 1000,         // Ring buffer size
    includeBodies: true,   // Capture req/res bodies (default: false in production)
  },
  sqlLog: {
    maxSize: 500,
    includeParams: true,   // Capture query params (default: false in production)
    slowThreshold: 500,    // Slow query threshold in ms
  },

  // Remote access (requires auth)
  auth: 'your-secret-token', // Required when host !== localhost
});
```

### Production Defaults

When `NODE_ENV=production`, runtime-mcp automatically:

- Sets `readOnly: true` — disables `eval`, `hot_patch`, `shell`
- Hides request/response bodies
- Hides SQL query parameters
- All read-only inspection tools remain available

## Binding Objects

Pass objects to `bind` to make them accessible to Claude:

```typescript
import { serve } from 'bun';
import { SQL } from 'bun';
import { attachMCP } from 'runtime-mcp';

const db = new SQL('postgres://localhost/myapp');
const server = serve({ port: 3000, fetch: handleRequest });
const config = { featureFlags: { newCheckout: true }, rateLimit: 100 };

attachMCP({
  port: 3100,
  bind: { server, db, config },
});
```

runtime-mcp auto-detects:
- **Bun.serve() servers** — wraps the fetch handler to intercept HTTP traffic
- **Bun.sql instances** — wraps queries to capture SQL traffic
- **WebSocket handlers** — tracks connections and messages

Everything else is available through `inspect` and `eval` by name.

## Security

- Binds to `localhost` only by default
- Non-localhost binding requires the `auth` option (Bearer token)
- Production mode disables code execution tools
- Shell tool blocks destructive commands (`rm`, `kill`, `shutdown`, etc.)
- Sensitive env vars are filtered from process info

This is a **development tool**. Treat the MCP port like a debugger port — don't expose it to the internet.

## Requirements

- Bun >= 1.0.0
- An MCP client (Claude Desktop, Cursor, or any MCP-compatible tool)

## How It Was Built

This project was built in a single session using [Ralph](https://github.com/williamcotton/ralph), an autonomous AI agent loop. A PRD was written, converted to a task list, and Ralph implemented all 22 user stories sequentially — each one adding a resource, tool, or interceptor layer.

## License

MIT