Jesse A. Green / notebook

Context7 Admin & Developer Guide

Generated June 2026 from upstash/context7 at c436700

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

This guide is for administrators, DevOps engineers, and developers who need to self-host the Context7 MCP server, integrate Context7's libraries into production systems, or understand how this monorepo is built. It is the exhaustive, source-derived companion to the User Guide.

Important

This repository hosts the MCP server, CLI, SDKs, and integrations only. The Context7 API backend, parsing engine, and crawling engine that build and serve the documentation index are private and not part of this repository. Self-hosting the MCP server still relies on the hosted Context7 API at context7.com/api (overridable via CONTEXT7_API_URL).


1. Executive Summary

Context7 is an up-to-date documentation retrieval system for AI coding agents. It exposes two capabilities — resolve a library name to a canonical ID, and fetch version-specific documentation — through five distinct delivery surfaces published from one monorepo.

Package Version Role Runtime
ctx7 0.4.5 CLI: agent setup, doc queries, skill management Node >=18
@upstash/context7-mcp 3.1.0 MCP server (stdio + HTTP) — the one deployable Node >=18 (HTTP needs Redis)
@upstash/context7-sdk 0.3.0 Typed HTTP client for the Context7 API Node / browser
@upstash/context7-tools-ai-sdk 0.2.3 Vercel AI SDK tools + agent Node, AI SDK >=6
@upstash/context7-pi 0.1.0 pi coding-agent extension pi runtime, Node >=22.19

Key architectural facts:

  • The MCP server is a thin, stateless-per-request proxy in front of the private Context7 API. It holds no documentation itself — it forwards resolve and query calls and formats results for LLM consumption.
  • HTTP mode tracks MCP sessions in Upstash Redis purely for spec compliance and log correlation; sessions are not an auth primitive, and the store fails open.
  • Authentication is bearer API keys (prefix ctx7sk) or JWTs validated against Clerk or Microsoft Entra ID. The CLI obtains tokens via OAuth 2.0 + PKCE.
  • All five surfaces ultimately call the same two backend endpoints: GET /v2/libs/search and GET /v2/context.

2. Architecture

2.1 System overview

                          ┌─────────────────────────────────────────────┐
   AI coding agent        │            Context7 delivery surfaces        │
   (Claude, Cursor, …)    │                                             │
        │                 │   ctx7 CLI ──┐                              │
        │  MCP protocol    │   MCP server ─┤                              │
        ├─────────────────►│   SDK ────────┼──►  HTTPS  ──► Context7 API │
        │                 │   AI-SDK tools ┤      (private backend)      │
   your code              │   pi extension ┘      context7.com/api       │
        └─────────────────►│                                             │
                          └───────────────────┬─────────────────────────┘
                                              │
                                  GET /v2/libs/search   (resolve)
                                  GET /v2/context        (fetch docs)

Every surface is a different client of the same backend API. The backend (crawling, parsing, indexing, ranking) is closed-source; this repo is the client/edge layer.

2.2 MCP server request flow (HTTP)

Client ──POST /mcp──► Express app
                        │
                        ├─ CORS + header normalization
                        ├─ extract API key (Authorization / X-API-Key / Context7-API-Key …)
                        ├─ /mcp        → anonymous allowed
                        │  /mcp/oauth  → JWT required (Clerk or Entra)
                        ├─ session: create on initialize / refresh otherwise (Redis)
                        ├─ arg-aliasing hook (rewrites hallucinated tool-arg names)
                        ├─ StreamableHTTPServerTransport (SSE response, per-request server)
                        └─ tool call → lib/api.ts → Context7 API → formatted text

A fresh McpServer and transport are constructed per request and torn down when the response closes. The Express layer owns session lifecycle; the MCP SDK transport does not (sessionIdGenerator: undefined).

2.3 Component inventory

Component Source Responsibility
MCP entrypoint packages/mcp/src/index.ts CLI parsing, transport setup, Express routes, tool registration
MCP API client packages/mcp/src/lib/api.ts Calls /v2/libs/search and /v2/context; proxy/CA handling
Header builder packages/mcp/src/lib/encryption.ts Builds API headers; AES-256-CBC client-IP encryption
JWT validation packages/mcp/src/lib/jwt.ts Validates Clerk and Microsoft Entra v2 tokens via JWKS
Redis client packages/mcp/src/lib/redis.ts Lazy Upstash Redis client from env
Session store packages/mcp/src/lib/sessionStore.ts Create/refresh/delete MCP sessions (TTL 7d)
Result formatting packages/mcp/src/lib/utils.ts Formats search results for LLM consumption
CLI entrypoint packages/cli/src/index.ts Commander program, command registration, upgrade notice
CLI commands packages/cli/src/commands/*.ts auth, docs, setup, remove, upgrade, skill, generate
CLI auth packages/cli/src/utils/auth.ts OAuth PKCE flow, token storage, refresh
SDK client packages/sdk/src/client.ts Context7 class, searchLibrary/getContext
SDK HTTP layer packages/sdk/src/http/index.ts Fetch wrapper with retry/backoff

2.4 The "duplicate-but-aligned" pattern

The pi package deliberately copies the API client, formatting, and type definitions from the MCP package (see the header comments in packages/pi/lib/*). This keeps pi's wire format and LLM-facing tool descriptions identical to the MCP server's while letting pi control its own HTTP runtime.

Important

When changing tool descriptions, result formatting, or error messages, update both packages/mcp/src/lib/ and packages/pi/lib/ together. They are intentionally kept in lockstep and there is no shared module enforcing it.


3. Requirements

3.1 Runtime

Use case Requirement
CLI / stdio MCP Node.js >=18, a package runner (npx/pnpm/bun)
HTTP MCP server Node.js >=18, Upstash Redis (REST), outbound HTTPS to context7.com
Building from source pnpm (Corepack), TypeScript ^5.8, the repo's lockfile
AI-SDK tools Vercel AI SDK >=6.0.0, zod >=4.0.0, @upstash/context7-sdk >=0.3.0
pi extension pi coding-agent runtime, Node >=22.19

3.2 Build tooling

The monorepo uses pnpm workspaces (packages/*). Per-package build tools: tsup (CLI, SDK, AI-SDK tools), tsc (MCP), and vitest for tests. Releases are managed by Changesets.

pnpm install          # install all workspace deps
pnpm -r run build     # build every package
pnpm -r run test      # run all test suites
pnpm typecheck        # typecheck all packages
pnpm lint             # eslint across packages

4. Deploying the HTTP MCP Server

Self-hosting is appropriate when you want the MCP edge inside your own network, behind your own auth, or co-located with corporate proxies/CAs. The server still forwards to the hosted Context7 API unless you point CONTEXT7_API_URL at a private deployment.

The repo ships a production Dockerfile at packages/mcp/Dockerfile. It is a two-stage build that compiles the MCP package and ships a production-only image:

# Build stage compiles @upstash/context7-mcp, production stage runs it
EXPOSE 8080
CMD ["node", "dist/index.js", "--transport", "http", "--port", "8080"]

Build and run:

# From the repo root (Dockerfile copies the monorepo manifests + packages/mcp)
docker build -f packages/mcp/Dockerfile -t context7-mcp .

docker run -d --name context7-mcp \
  -p 8080:8080 \
  -e UPSTASH_REDIS_REST_URL="https://<your-db>.upstash.io" \
  -e UPSTASH_REDIS_REST_TOKEN="<token>" \
  -e CLIENT_IP_ENCRYPTION_KEY="<64-hex-chars>" \
  context7-mcp
Context7 Documentation MCP Server v3.1.0 running on HTTP at http://localhost:8080/mcp

Note

The image exposes 8080, while the server's own default port is 3000. The Docker CMD overrides it with --port 8080. Match your reverse-proxy upstream to whichever you run.

4.2 Smithery

packages/mcp/smithery.yaml declares an HTTP start command with no required configuration, so the server can be deployed via Smithery as @upstash/context7-mcp.

4.3 Running from source

pnpm install --frozen-lockfile
pnpm --filter @upstash/context7-mcp build
node packages/mcp/dist/index.js --transport http --port 3000

4.4 Deployment checklist

  • [ ] Provision an Upstash Redis database; set UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN.
  • [ ] Set a real CLIENT_IP_ENCRYPTION_KEY (64 hex characters). Do not ship the built-in default.
  • [ ] If behind a proxy, set HTTPS_PROXY (and NODE_EXTRA_CA_CERTS for custom CAs).
  • [ ] Put the server behind TLS via a reverse proxy (the server speaks plain HTTP).
  • [ ] Forward client IPs via X-Forwarded-For at the proxy so rate-limiting works.
  • [ ] Decide auth posture: /mcp (anonymous) vs /mcp/oauth (JWT-required).
  • [ ] If using Entra SSO, ensure the backend has the tenant/audience config registered.
  • [ ] Health-check GET /ping.
  • [ ] Confirm clients use POST (a GET /mcp correctly returns 405).

5. Configuration Reference

5.1 MCP server CLI flags

Flag Default Notes
--transport <stdio|http> stdio Invalid values exit with an error
--port <number> 3000 HTTP only; rejected with --transport stdio
--api-key <key> — stdio only; rejected with --transport http
-v, --version — Prints SERVER_VERSION (from package.json)

Unknown flags are tolerated (allowUnknownOption) so MCP Inspector and wrappers can pass extras through. On EADDRINUSE, HTTP mode auto-increments the port up to +10 before giving up.

5.2 Environment variables

These are consumed across the MCP server, SDK, CLI, and pi. The repo's .env.example is the authoritative list.

Variable Used by Purpose Default
CONTEXT7_API_KEY all Bearer key for the Context7 API —
CONTEXT7_API_URL MCP, SDK*, pi* Backend base URL https://context7.com/api
UPSTASH_REDIS_REST_URL MCP (HTTP) Upstash Redis REST URL — (required for HTTP)
UPSTASH_REDIS_REST_TOKEN MCP (HTTP) Upstash Redis REST token — (required for HTTP)
RESOURCE_URL MCP (HTTP) OAuth protected-resource URL advertised in metadata https://mcp.context7.com
AUTH_SERVER_URL MCP (HTTP) OAuth authorization server https://context7.com
OPENAI_APPS_CHALLENGE_TOKEN MCP (HTTP) Serves the OpenAI Apps domain-verification challenge — (404 if unset)
CLIENT_IP_ENCRYPTION_KEY MCP 64-hex-char AES-256-CBC key for client-IP encryption insecure built-in default
HTTPS_PROXY / HTTP_PROXY MCP Outbound proxy for API calls —
NODE_EXTRA_CA_CERTS MCP Path to extra CA certificates —
GITHUB_TOKEN / GH_TOKEN CLI Token for fetching skills from private GitHub repos —
CTX7_TELEMETRY_DISABLED CLI Disable anonymous CLI usage events —
EDITOR CLI Editor for reviewing generated skills open
CLAUDE_CONFIG_DIR CLI Override Claude config location during setup —

* The hosted SDK base URL (https://context7.com/api) and pi base URL are compiled in; the MCP server reads CONTEXT7_API_URL. The CLI talks to https://context7.com (overridable with --base-url).

Caution

CLIENT_IP_ENCRYPTION_KEY has a hard-coded default value in encryption.ts. It is a placeholder, not a secret — always set your own 64-hex-character key in any real deployment. If the key is malformed, the server logs an error and falls back to sending the client IP unencrypted.

5.3 HTTP endpoints exposed by the MCP server

Method Path Auth Purpose
POST /mcp None Anonymous MCP protocol endpoint
POST /mcp/oauth JWT required Authenticated MCP endpoint
DELETE /mcp, /mcp/oauth — Terminate an MCP session (needs Mcp-Session-Id)
GET /mcp* — Returns 405 (server sends no SSE/server-initiated notifications)
GET /ping None Health check → { "status": "ok", "message": "pong" }
GET /.well-known/oauth-protected-resource None RFC 9728 resource metadata
GET /.well-known/oauth-authorization-server None Proxies the auth server's metadata
GET /.well-known/openai-apps-challenge None OpenAI Apps verification (404 unless token set)
* (any other) — Catch-all 404

Accepted API-key headers (HTTP mode, checked in order): Authorization: Bearer …, Context7-API-Key, X-API-Key, Context7_API_Key, X_API_Key.


6. Security

6.1 Authentication & authorization

API keys. Keys carry the ctx7sk prefix and are sent as bearer tokens to the backend. The SDK warns (but does not fail) if a key lacks the prefix; the backend returns a 401 with guidance if a key is invalid.

JWT validation (lib/jwt.ts). On the /mcp/oauth endpoint, if the presented credential is a JWT (three dot-separated segments), it is verified:

  • Clerk tokens (issuer https://clerk.context7.com) are verified against Clerk's JWKS.
  • Microsoft Entra v2 tokens (issuer https://login.microsoftonline.com/<tenant>/v2.0) are verified against the tenant's JWKS. The server fetches per-audience Entra config (tenant ID, required scope) from the backend, caches it for 5 minutes, and enforces the required scope if configured.

Validation failures return spec-compliant JSON-RPC errors with messages like Token expired, Invalid signature, or Missing required scope.

OAuth (CLI). The CLI uses OAuth 2.0 Authorization Code + PKCE (S256):

  • Authorize: GET /api/oauth/authorize, token exchange: POST /api/oauth/token.
  • Client ID 2veBSofhicRBguUT, scope profile email, response_type=code.
  • A local callback server listens on 127.0.0.1:52417 (/callback) with a 5-minute timeout and validates the state parameter to prevent CSRF.
  • Tokens are stored in ~/.context7/credentials.json (directory mode 0700, file mode 0600) and refreshed automatically using the refresh token when expired.

6.2 Client-IP encryption

The MCP server encrypts the caller's IP (used for backend rate-limiting/abuse signals) with AES-256-CBC before sending it as the mcp-client-ip header. A random 16-byte IV is prepended. Private/internal ranges (10., 192.168., 172.16–31.) are skipped when parsing X-Forwarded-For so the first public IP is used.

6.3 Session handling

  • Sessions live in Redis under #mcp#session#<uuid>, TTL 7 days, refreshed (sliding) only when under the 1-day threshold.
  • Sessions are not an authentication or authorization mechanism — just opaque identifiers for log correlation and StreamableHTTP spec compliance.
  • The store fails open: Redis errors are logged and the request proceeds. Ghost sessions self-heal — a missing key returns 404 and the client re-initializes.

6.4 Input-safety guards (CLI)

The CLI installs files into agent directories, so it hardens against path traversal:

  • assertSkillNameInRoot / isSafeSkillName reject skill names with .., null bytes, or characters outside [a-zA-Z0-9._-], and ensure the resolved path stays directly under the skills root.
  • installSkillFiles rejects any file whose resolved path escapes the target directory (this is the source of the … resolves outside the target directory error fixed for Windows in issue #2361).
  • Skills fetched from GitHub skip files whose relative path contains ...
  • Skill content flagged for prompt injection by the backend is blocked from install and reported, not silently dropped.

6.5 Data handling & disclosure

Tool descriptions explicitly instruct agents not to include secrets, credentials, personal data, or proprietary code in queries — only the question and library name are sent to the API. The project's SECURITY.md directs vulnerability reports to GitHub private advisories or [email removed], with a 48-hour acknowledgment target and a 30-day resolution goal for critical issues.

Warning

Anonymous /mcp access means anyone who can reach your self-hosted server can consume your backend quota under whatever key/identity the server forwards. If you self-host, front it with your own gateway or require /mcp/oauth.


7. Operations

7.1 Health & monitoring

  • Liveness: GET /ping returns 200 with {"status":"ok","message":"pong"}.
  • Logs: the server logs to stderr (so stdout stays clean for the stdio transport). Watch for Error handling MCP request, OAuth upstream errors, and Redis session errors.
  • Startup banner: confirms transport, version, and bound port.

7.2 Scaling

The HTTP server is effectively stateless — all shared state lives in Redis, and a new MCP server/transport is created per request. You can run multiple replicas behind a load balancer without sticky sessions, since session validation is a Redis lookup, not in-process state.

7.3 Networking

  • Outbound HTTPS to context7.com (or your CONTEXT7_API_URL) is required.
  • Corporate proxies: set HTTPS_PROXY; for TLS interception, set NODE_EXTRA_CA_CERTS to your CA bundle path. The API client wires these into an undici ProxyAgent/Agent at module load.
  • CORS is wide open (Access-Control-Allow-Origin: *) to support browser-based MCP clients; restrict at your proxy if needed.

7.4 Backups & state

There is no durable application data to back up — Redis holds only ephemeral, self-healing session keys. Treat the deployment as cattle.


8. Repository Structure (Developer Reference)

context7/
├── packages/
│   ├── cli/                 ctx7 — Commander CLI
│   │   └── src/
│   │       ├── index.ts            program + command registration
│   │       ├── commands/           auth, docs, setup, remove, upgrade, skill, generate
│   │       ├── setup/              agents.ts, mcp-writer.ts, templates.ts
│   │       └── utils/              api, auth, deps, github, ide, installer, update-check, tracking
│   ├── mcp/                 @upstash/context7-mcp — MCP server
│   │   ├── src/index.ts            transports + Express + tool registration
│   │   ├── src/lib/                api, jwt, redis, sessionStore, encryption, utils
│   │   └── Dockerfile, smithery.yaml
│   ├── sdk/                 @upstash/context7-sdk — typed client
│   │   └── src/                    client.ts, http/, error/, commands/
│   ├── tools-ai-sdk/        @upstash/context7-tools-ai-sdk — Vercel AI SDK
│   │   └── src/                    tools/, agents/, prompts/
│   └── pi/                  @upstash/context7-pi — pi extension
│       └── lib/, extensions/, skills/, prompts/
├── plugins/                 Claude Code, Cursor, context7-power, gemini-extension
├── skills/                  find-docs, context7-mcp, context7-cli (installable skills)
├── rules/                   context7-cli.md, context7-mcp.md (agent rules)
├── docs/                    MkDocs/Mintlify documentation site (.mdx)
└── i18n/                    Translated READMEs (15 languages)

8.1 CLI internals

  • Commander drives the program. Two preAction hooks handle --base-url overrides and the once-a-day upgrade notice.
  • setup/agents.ts defines each agent's MCP config path/key, rule type, and skill directory. setup/mcp-writer.ts reads/merges/writes JSON and TOML MCP configs idempotently. setup/templates.ts renders the rule and skill content per agent.
  • utils/update-check.ts polls registry.npmjs.org/<pkg>/latest (1.5 s timeout), caches result and notification state in ~/.context7/cli-state.json (24 h TTL), and computes an install-method-aware upgrade plan (npm/pnpm/bun, global vs ephemeral runner).
  • utils/tracking.ts posts anonymous events to /api/v2/cli/events unless CTX7_TELEMETRY_DISABLED is set.

8.2 SDK internals

  • Context7 wraps an HttpClient (baseUrl=https://context7.com/api, retry 5×, exponential backoff exp(n)*50 ms, cache: no-store).
  • Commands subclass a generic Command<TResult>; SearchLibraryCommand → GET v2/libs/search, GetContextCommand → GET v2/context. Both support type: "json" | "txt"; JSON responses are mapped into Library[] / Documentation[], text passes through. Errors throw Context7Error.

8.3 Backend API endpoints (consumed by these clients)

Endpoint Method Used by
/v2/libs/search GET MCP, SDK, CLI (library), pi
/v2/context GET MCP, SDK, CLI (docs), pi
/api/v2/skills, /skills/suggest, /skills/quota, /skills/questions, /skills/generate GET/POST CLI skills + generate
/api/v2/cli/events POST CLI telemetry
/api/oauth/authorize, /api/oauth/token GET/POST CLI OAuth
/api/dashboard/whoami, /api/dashboard/api-keys GET/POST CLI whoami, key generation
/v2/entra/config/<audience> GET MCP Entra JWT validation

9. Testing Strategy

Each package ships a Vitest suite (*.test.ts), run via pnpm test (or pnpm -r run test at the root).

Package Test focus
cli auth utils/commands, installer, remove, setup, skill-list, update-check, upgrade
mcp JWT validation, certificate handling
sdk client constructor, searchLibrary/getContext (live API), error handling, type inference
tools-ai-sdk tool structure, multi-step flows via Amazon Bedrock, Context7Agent behavior
pi extension registration

Note

SDK and AI-SDK tests hit the live Context7 API and a live model (Bedrock), so they need CONTEXT7_API_KEY and AWS credentials. They are integration tests, not hermetic unit tests — keep that in mind in CI.

Lint/format is ESLint (flat config) + Prettier, enforced per package (lint:check, format:check).


10. Code Patterns & Conventions

  • ES modules throughout, .js import specifiers in TypeScript (NodeNext resolution).
  • Per-package path aliases (@commands, @http, @tools, @agents, @prompts) resolved by tsup/vitest.
  • Fail-open infrastructure: Redis, telemetry, and update checks never block the primary operation.
  • LLM-robustness hook: the MCP server rewrites hallucinated tool-argument names (userQuery→query, libraryID/context7CompatibleLibraryID→libraryId) before Zod validation, so minor model deviations don't fail tool calls.
  • Shared-by-copy: pi mirrors MCP's client/format/types verbatim (documented in file headers) rather than depending on the MCP package.
  • Changesets for versioning and publishing; each package is versioned independently.

11. Potential Improvements & Tech Debt

These are observable from the source and the issue tracker — actionable items for maintainers:

  • ctx7 skills deprecation. The Skill Hub command tree (install/search/info/suggest) is marked for removal (TODO(deprecate-skills-phase-2)), with deprecation warnings already live. Plan the phase-2 deletion and migrate users to setup + generate.
  • XDG compliance. Config currently lives in ~/.context7/ (credentials.json, cli-state.json). Issue #2638 requests XDG-base-directory support.
  • Credential storage. Tokens sit in a 0600 JSON file. Issue #2639 requests OS keyring storage with JSON fallback.
  • Insecure default encryption key. CLIENT_IP_ENCRYPTION_KEY ships with a placeholder default; consider failing fast (or warning loudly) when the default is detected in HTTP mode.
  • Remote-login UX. The fixed localhost:52417 callback breaks headless/SSH logins (issues #2242, #2693). A device-code flow would remove the need for port-forwarding.
  • Monorepo dependency discovery. ctx7 skills suggest misses subpackage deps in pnpm monorepos (issue #1860) — detectProjectDependencies only reads the CWD's manifest.
  • pi/MCP drift risk. The copy-paste alignment between packages/pi/lib and packages/mcp/src/lib is enforced only by comments; a shared internal package would prevent silent divergence.

12. Quick Reference

Run the server

# stdio (local agent)
npx @upstash/context7-mcp --api-key ctx7sk-...

# HTTP (self-hosted), Redis required
UPSTASH_REDIS_REST_URL=... UPSTASH_REDIS_REST_TOKEN=... \
  node packages/mcp/dist/index.js --transport http --port 3000

Build & test

pnpm install
pnpm -r run build
pnpm -r run test
pnpm --filter @upstash/context7-mcp build   # single package

Health check

curl -s http://localhost:8080/ping
# {"status":"ok","message":"pong"}

Minimum HTTP-server env

Variable Required Notes
UPSTASH_REDIS_REST_URL yes Sessions throw without it
UPSTASH_REDIS_REST_TOKEN yes —
CLIENT_IP_ENCRYPTION_KEY strongly 64 hex chars; default is insecure
CONTEXT7_API_URL no Defaults to hosted backend

Further reading