> ## Documentation index
> Fetch the complete documentation index at: https://context7.com/docs/llms.txt
> Ask it with GET https://context7.com/docs/ask?q=<keywords or question>. Short keywords rank best.
> Use these to discover all available pages before exploring further.
> Feature requests: https://context7.com/docs/resources/feature-requests.md lists what users asked for and how to vote for a request or add one.
> Page rating: `GET https://context7.com/docs/feedback?path=/docs/resources/developer&helpful=true` (or `false`) records whether this page helped. An optional `comment` (URL-encoded, at most 500 characters) says what was missing or wrong. It is anonymous and needs no key. Comments hold no code, secrets or personal data.

# Developer Guide

> Set up and run Context7 MCP locally for development

This guide covers how to set up the Context7 MCP server locally for development and testing.

## Getting Started

Clone the project and install dependencies:

```bash
git clone https://github.com/upstash/context7.git
cd context7
pnpm i
```

Build:

```bash
pnpm run build
```

Run the server:

```bash
node packages/mcp/dist/index.js
```

## CLI Arguments

`context7-mcp` accepts the following CLI flags:

| Flag                        | Description                                                                           | Default |
| --------------------------- | ------------------------------------------------------------------------------------- | ------- |
| `--transport <stdio\|http>` | Transport to use. Use `http` for remote HTTP server or `stdio` for local integration. | `stdio` |
| `--port <number>`           | Port to listen on when using `http` transport.                                        | `3000`  |
| `--api-key <key>`           | API key for authentication (or set `CONTEXT7_API_KEY` env var).                       | -       |

<Note>
  Get your API key by creating an account at
  [context7.com/dashboard](https://context7.com/dashboard).
</Note>

### Examples

HTTP transport on port 8080:

```bash
node packages/mcp/dist/index.js --transport http --port 8080
```

HTTP transport requires a credential on every request by default. Clients send `Authorization: Bearer YOUR_API_KEY`. Set `MCP_AUTH_ENFORCEMENT=observe` to also accept requests without credentials on `/mcp`.

Opaque OAuth access tokens (`oat_…`) are checked against the Context7 API before each request is served (one check per token per minute on each replica; the cache is in memory, and a rejected token stays rejected for ten minutes). An expired or revoked token gets an HTTP 401 with a `WWW-Authenticate` challenge so MCP clients refresh it. Set `MCP_OAUTH_TOKEN_VALIDATION=off` to skip that check and forward the token unchecked.

OAuth JWT access tokens from the authorization server (`OAUTH_AUTH_SERVER_URL`) are verified locally: signature against its JWKS, issuer, a `typ` of `at+jwt`, and expiry with a minute of clock tolerance. Clerk ID tokens and session JWTs share that issuer but are not access tokens, so they are always rejected. The token's `aud` must name this server (`RESOURCE_URL` origin, `/mcp`, or `/mcp/oauth`; override with a comma-separated `MCP_OAUTH_ALLOWED_AUDIENCES`). The query string of an audience on an allowed host is ignored. `MCP_OAUTH_AUDIENCE_ENFORCEMENT` sets what a mismatch does: `observe` (default) admits a token with a missing or foreign audience; `foreign` answers HTTP 401 to a token issued for another server and still admits one with no `aud`; `required` answers 401 to both. Every mismatch is logged with the OAuth client ID, the audience and the outcome, once per token per hour on each replica.

The HTTP server is stateless — it creates a fresh server instance per request and keeps no session state. Session operations therefore have nothing to attach to: a `GET` or `DELETE` on `/mcp` is answered with `405 Method Not Allowed` rather than opening a standalone Server-Sent Events stream. Server-Sent Events are used only to stream responses to `POST` requests, and keepalive heartbeats are disabled.

Stdio transport with API key:

```bash
node packages/mcp/dist/index.js --transport stdio --api-key YOUR_API_KEY
```

## Environment Variables

You can use the `CONTEXT7_API_KEY` environment variable instead of passing the `--api-key` flag. This is useful for:

- Storing API keys securely in `.env` files
- Integration with MCP server setups that use dotenv
- Tools that prefer environment variable configuration

<Warning>
  The `--api-key` CLI flag takes precedence over the environment variable when both are provided.
</Warning>

### Using .env File

```bash
# .env
CONTEXT7_API_KEY=your_api_key_here
```

### MCP Configuration with Environment Variable

```json
{
  "mcpServers": {
    "context7": {
      "command": "npx",
      "args": ["-y", "@upstash/context7-mcp"],
      "env": {
        "CONTEXT7_API_KEY": "YOUR_API_KEY"
      }
    }
  }
}
```

## Local Development Configuration

When developing locally, use this configuration to run from source:

```json
{
  "mcpServers": {
    "context7": {
      "command": "npx",
      "args": [
        "tsx",
        "/path/to/folder/context7/packages/mcp/src/index.ts",
        "--api-key",
        "YOUR_API_KEY"
      ]
    }
  }
}
```

## Testing with MCP Inspector

Test your setup using the MCP Inspector:

```bash
npx -y @modelcontextprotocol/inspector npx @upstash/context7-mcp
```

This opens an interactive inspector to verify Context7 tools are working correctly.
