Updated 2026-04-28 — what changes when your MCP server backs a private GraphQL API instead of a public docs index.
Upstash/context7 is the reference MCP server for fetching up-to-date library docs. 53k stars, clean pattern: resolve a library ID, query docs, return MCP-formatted text. Works because the data is public, the schema is stable, and auth is a single API key.
That pattern breaks the moment you point an MCP server at an enterprise GraphQL API — per-tenant auth, schemas that drift, 50-type datamodels, write-side mutations. I learned that while building leanix-mcp-integration, which bridges LeanIX's enterprise-architecture GraphQL platform to Claude.
Five extensions to Context7's pattern that the enterprise case forces:
Context7 takes one CONTEXT7_API_KEY header. Enterprise APIs are per-workspace: you need subdomain + token per tenant, and the MCP server has to route each call to the right workspace.
// .env per-instance
LEANIX_SUBDOMAIN=acme-corp
LEANIX_TOKEN=<workspace-scoped-token>Run one MCP server process per workspace, or make the workspace part of every tool call. No middle ground.
Context7 indexes docs ahead of time. Enterprise GraphQL schemas drift — new fact-sheet types, custom fields, deprecated enums. You can't pre-index.
Approach: resolve field names at query-build time using a cached-but-refreshable schema introspection. Cache for an hour, invalidate on mutation.
Context7 validates inputs with JSON Schema. Enterprise tools need to reject bad input at the MCP boundary — one bad mutation corrupts business data. Use Zod:
import { z } from "zod";
const createFactSheetSchema = z.object({
type: z.enum(FACT_SHEET_TYPES),
name: z.string().min(1).max(200),
state: z.enum(["DRAFT", "APPROVED"]).optional(),
});Validate at the tool handler. Don't let malformed input reach the GraphQL layer.
Context7 is read-only. The moment your MCP server can write, the MCP tool's return value is not enough — you need a human-in-the-loop approval before the mutation executes. This is the same discipline as CLAUDE.md runtime rule 7 (HITL as a first-class step type).
Wrap every write tool to return a preview first, and require a follow-up confirm-mutation call with the preview ID before the GraphQL mutation fires.
Context7 returns the error from the docs service. Enterprise MCP servers must not leak schema details, auth errors, or stack traces back to the model — the model may pass them to the user, and that's a data leak.
async function withErrorHandling(fn) {
try { return await fn(); }
catch (e) {
console.error(e); // internal
return { content: [{ type: "text", text: "Operation failed." }] }; // surface
}
}Same principle as CLAUDE.md runtime rule 10 (log silently).
- Internal GraphQL APIs (LeanIX, Shopify Admin, Contentful, internal platforms)
- Multi-tenant SaaS where auth scope matters
- Any MCP server that can mutate, not just read
- Public docs / OpenAPI / fixed-schema APIs
- Single-tenant personal use
- Read-only tools
Weekly gists on MCP, Claude Code, and automation: follow @renezander030. The reference implementation for this pattern is in leanix-mcp-integration (Node.js, MIT).