SafetyCard Request a review

Context7

Upstash's MCP server that serves up-to-date, community-indexed library documentation into coding agents' context.

github.com/upstash/context7 › packages/mcp · 2026-10-04 · bfa02ea

Defense-in-depth score

6.5 / 10

Context7's MCP server is a small, read-only surface: two documentation lookups against one fixed API, no code execution, no files, no memory, no plugins. The dominant risk is what it delivers: community-contributed documentation goes into your agent's context as plain text with no provenance or untrusted marking, alongside tool descriptions that themselves direct the model, so any prompt injection in an indexed library reaches an agent that may hold far more powerful tools. It also forwards your API key or OAuth token to the Context7 backend without validating most tokens itself, and it keeps no per-call record of what was asked.

Safest setup

Context7's MCP server exposes just two read-only documentation lookups against one fixed API, with no code execution, files or plugins. What it adds to a session is community-written documentation in the model's context, and it keeps no per-call record, so the safest setup narrows the key and puts the guard rails in the host around it.

SetupHowWhat it gives you
A dedicated Context7 keyCreate a separate Context7 API key for each agent setup and revoke it when that setup is retiredA key that reaches only one Context7 account's documentation reads and can be cut off on its own C1
Local stdio modeWhen you run the server yourself, keep the default --transport of stdioThe server talks only to your own client, with no network port for anyone else to reach C1
The key from the environmentIn stdio mode, pass the key as CONTEXT7_API_KEY in the client's server config rather than with --api-keyThe key stays out of command lines, shell history and process listings C8
Per-call approval elsewhereIn sessions with Context7 connected, keep shell, file-write and messaging tools on per-call approval in your hostDocumentation text in the context can't turn into an action without a person seeing it first C5
A host-side call logTurn on your MCP client's or gateway's tool-call log, stored where the agent can't edit itA record of every lookup and its query, which the server itself keeps only for failures C9

Approving with confidence

  • Read each prompt for the host's other tools and approve calls one at a time, especially right after a documentation lookup.

Handling data

  • Every query the model writes is sent to Context7, so keep secrets and private code out of the questions it asks.
  • Telemetry is content-free and stays local unless you add an exporter; OTEL_SDK_DISABLED=true turns it off.

Key gaps (1)

  1. The server forwards the client's API key or JWT unchanged to the Context7 API (MCP token passthrough), validating tokens only on the /mcp/oauth route; token validation there is not a strict boundary. C1 · Identity & least privilege

Criteria

C1 Identity & least privilege

0.25 / 1.00

The server holds no broad credential of its own: each request carries the user's own Context7 API key (or OAuth token), and the server only ever uses it for two read-only lookups against the Context7 API, so one user's request cannot act as another user. But the server does not validate most tokens itself: on the default /mcp endpoint any key or token is forwarded unchecked to the backend, and token validation on the protected endpoint is not a strict boundary. Forwarding the client's token downstream is the MCP 'token passthrough' pattern, which caps this criterion.

C2 Approval gates

Hardened 1.00 / 1.00

The server exposes exactly two tools, both pure lookups against the Context7 documentation API, and both carry accurate read-only, non-destructive annotations. Neither tool can change state anywhere: the only upstream calls are two HTTP GETs to a fixed host. There is nothing consequential for a host to approve, and the tool set is hard-coded with no way to add tools at runtime.

C3 Tool & action scoping

Strong 0.75 / 1.00

The tools are narrow by design: instead of a generic HTTP fetch, each builds a request to one fixed Context7 endpoint, with the model's arguments placed into encoded query parameters, so the model cannot choose the host or the path. Arguments are only typed as strings, though: there is no length limit and no format check on the library ID, and the server does not cap how much documentation it returns.

C4 Code-execution isolation

N/A · full credit 1.00 / 1.00

The server never interprets model text as code: there is no shell, subprocess, eval, or dynamic code loading anywhere in the MCP package. Arguments only become URL query parameters on a lookup request.

C5 Untrusted input blast radius

0.10 / 1.00

The server's job is to put third-party, community-contributed documentation into the model's context, and it does so as plain text with no provenance marker or untrusted flag that the host could act on. Its own tool descriptions and server instructions also contain directives to the model ('You MUST call this function', 'Use even when you think you know the answer'), so content and instructions are mixed. The server itself cannot take actions, which limits what a hijack can do through it, but every query the model writes is sent to Context7 and there is no no-egress mode.

C6 Memory, context & configuration integrity

N/A · full credit 1.00 / 1.00

The MCP server is stateless: it keeps no memory, writes no files, and loads no workspace instruction or config files. Only operator-scope environment variables configure it. (The Context7 documentation index is a shared, community-written store, but it lives in the private backend and is reached here only as untrusted input, scored under C5.)

C7 Third-party extensions

N/A · full credit 1.00 / 1.00

The server loads no third-party code at runtime: no plugins, no MCP sub-servers, no package installs. Its only dynamic imports load its own telemetry modules.

C8 Secrets & sensitive-data protection

0.42 / 1.00

API keys arrive per request (HTTP) or from an environment variable or command-line flag (stdio) and are kept in memory only. They are never echoed back into tool results, and the telemetry records only tool names and outcomes, never arguments or headers. There is, however, no redaction layer: secrets stay out of logs only because no code path happens to log them, not every error path keeps secrets out of its output, and the keys themselves are long-lived.

C9 Audit & traceability

0.30 / 1.00

In the shipped configuration the server keeps no per-call record of what it was asked: only errors are printed to stderr, and aggregate metrics count calls by tool and outcome. OpenTelemetry spans exist but go nowhere unless the operator installs an exporter, and even then they hold the tool name and outcome, not the arguments or who asked.

C10 Limits & kill switch

0.63 / 1.00

Each upstream lookup has a hard 60-second timeout, OAuth metadata fetches have 10 seconds, SSE keep-alives and notification subscriptions are disabled, and shutdown is bounded. The server itself has no rate limit, no concurrency cap and no output size limit (quotas are enforced by the private backend), and a client's cancellation of a tool call does not abort the in-flight upstream request.