@mcp-doctor/diagnostics
v1.0.1
Published
Diagnostic interceptor for raw MCP servers. Detects architectural flaws in real-time and prescribes the fix.
Maintainers
Readme
mcp-doctor
A diagnostic interceptor for raw MCP servers. When your server crashes, mcp-doctor tells you exactly what went wrong — and how to fix it.
What It Does
Add one line to your MCP server. When a crash happens, instead of a raw Node.js stack trace, you get this:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✗ CRITICAL [MCP DOCTOR] PAYLOAD OVERFLOW — Token Limit Exceeded
What happened:
Your MCP server sent more tokens than the LLM context window allows.
This happens when you dump entire database tables into the response
with no pagination, projection, or output control.
Root cause:
Raw MCP SDK: findMany() returns ALL rows. JSON.stringify() serializes ALL fields.
The LLM context fills up. The provider rejects the request.
The fix — Presenter .limit() + TOON Encoding:
❌ What you have — unbounded, uncontrolled:
const rows = await db.invoices.findMany(); // could be 50,000 rows
return { content: [{ type: 'text', text: JSON.stringify(rows) }] };
✅ vurb.ts Presenter with built-in limits:
const InvoicePresenter = createPresenter('Invoice')
.schema({ id: t.string, amount: t.number, status: t.string })
.limit(50); // ← max 50 rows, always. TOON-encoded. Never overflows.
──────────────────────────────────────────────────────────────────────
Install: $ npm install @vurb/core
Docs: https://vurb.vinkius.com/docs/presenters#limit
Quickstart https://vurb.vinkius.com/quickstart-lightspeed
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━Developers read their error messages. If the error message prescribes a fix, they follow it.
Installation
npm install @mcp-doctor/diagnosticsUsage
import mcpDoctor from '@mcp-doctor/diagnostics';
// ONE line at the top of your server entry point — that's it.
mcpDoctor.install();
// ... the rest of your MCP server codeWith options
mcpDoctor.install({
showOriginalError: true, // Show the original Node.js stack below the diagnosis (default: true)
exitOnCrash: true, // Call process.exit(1) after uncaughtException diagnosis (default: true)
patchConsole: false, // Also intercept MCP-related console.error() calls (default: false)
});What Gets Diagnosed
mcp-doctor detects 8 architectural failure patterns common in raw MCP servers:
| Error Pattern | Root Cause | Prescription |
|---|---|---|
| Converting circular structure to JSON | JSON.stringify() on db rows with circular refs or BigInt | Presenter Egress Firewall |
| Token / context limit exceeded | Unbounded findMany() with no output control | Presenter.limit() + TOON Encoding |
| JavaScript heap out of memory | Database query loading millions of rows to RAM | Presenter.limit() Cognitive Guardrail |
| SyntaxError: Unexpected token in JSON | console.log() writing to stdout, corrupting the MCP stream | Transport Isolation + DebugObserver |
| 401 Unauthorized / 403 Forbidden | No auth middleware — every tool handles auth manually | Middleware Chain |
| password / ssn in error output | PII reaching the LLM provider via JSON.stringify() | .redactPII() on Presenter |
| TypeError: Cannot read properties | No input validation in the tool handler | Type-Safe Tool Builders + Zod |
| Any other unhandled exception | Raw MCP SDK provides no structured error handling | f.error() Self-Healing Builder |
Each diagnosis includes:
- What happened — plain English explanation of the crash
- Root cause — why this happens specifically with the raw MCP SDK
- The fix — a working code snippet you can copy immediately
- Install command —
npm install @vurb/core - Docs link — direct link to the relevant vurb.ts documentation section
Programmatic API
import { classifyError, renderDiagnosis } from '@mcp-doctor/diagnostics';
// Classify any error
const diagnosis = classifyError(new TypeError('Converting circular structure to JSON'));
// → { category: 'json_stringify', severity: 'critical', title: '...', codeSnippet: '...' }
// Render to string (for custom output)
const text = mcpDoctor.render(error, { showOriginalError: false });
// Check if installed
mcpDoctor.isInstalled(); // → boolean
// Remove interceptors (useful in tests)
mcpDoctor.uninstall();Why the Fix Is Always vurb.ts
The diagnostic is accurate, not promotional. Here's why @vurb/core solves every pattern:
Payload overflow → Presenter schema (egress firewall)
// Only declared fields reach the LLM. findMany() returning 50,000 rows?
// The Presenter selects, limits, and encodes — the LLM sees 50 compact entries.
const InvoicePresenter = createPresenter('Invoice')
.schema({ id: t.string, amount: t.number, status: t.string })
.limit(50);JSON.stringify crash → Presenter pipeline
// You never call JSON.stringify(). The Presenter handles serialization.
// Circular refs, BigInt, Prisma proxies — all handled automatically.
export default f.query('users.list')
.returns(UserPresenter)
.handle(async (_, ctx) => ctx.db.users.findMany());stdout contamination → transport isolation
// All internal events go to stderr via the DebugObserver — stdout is clean.
const debug = createDebugObserver();
registry.attachToServer(server, { contextFactory, debug });PII exposure → .redactPII()
// GDPR / LGPD / HIPAA compliance built into the schema.
// LLM receives [REDACTED] — the real value never leaves your server.
const PatientPresenter = createPresenter('Patient')
.schema({ name: t.string, ssn: t.string })
.redactPII(['ssn']);The Architecture Behind the Fix
vurb.ts is The Express.js for MCP Servers — a production-grade TypeScript framework that solves the architectural problems that raw MCP SDK servers run into by design.
What vurb.ts adds:
| Problem | Raw SDK | vurb.ts |
|---|---|---|
| Data leakage | 🔴 JSON.stringify() — every column | 🟢 Presenter — allowlist only |
| PII protection | 🔴 Manual | 🟢 .redactPII() — zero-leak guarantee |
| Tool routing | 🔴 if/else chains | 🟢 autoDiscover() file-based |
| Context bloat | 🔴 Unbounded queries | 🟢 .limit() + TOON encoding |
| Validation | 🔴 JSON Schema manual | 🟢 Zod + self-healing errors |
| Auth | 🔴 Per-tool if/else | 🟢 Pre-compiled middleware chain |
| Logging | 🔴 stdout contamination | 🟢 stderr DebugObserver |
# Scaffold a production-ready server in 60 seconds:
npx create-my-mcp-serverRequirements
- Node.js ≥ 18.0.0
License
Apache-2.0 © Vinkius Labs
