Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/howto/admin-mcp.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ Clients that support MCP OAuth ask you to sign in with your Context7 account on

### API key

Create a Context7 API key in [the dashboard](https://context7.com/dashboard) with **Management access** ticked, and send it as a bearer token. A key without it gets `403` `management_access_required`, and a key reaches only its own teamspace. See [Management access](/howto/api-keys#management-access).
Create a Context7 API key in [the dashboard](https://context7.com/dashboard) and send it as a bearer token. Every key can use the read tools. To make changes, tick **Write access** when you create the key; a key without it gets `403` `write_access_required` on changes. A key reaches only its own teamspace. See [Write access](/howto/api-keys#write-access).

![Create New API Key dialog with Management access ticked](/images/dashboard/api-key-management-access.png)
![Create New API Key dialog with Write access ticked](/images/dashboard/api-key-write-access.png)

```json
{
Expand Down Expand Up @@ -72,7 +72,7 @@ One OAuth connection reaches every teamspace you are a member of, with your role

## Management API

The same operations are available over the REST API at `/api/v2/teamspaces/{teamspaceId}`, so a script can use them without an MCP client. It takes the same credentials as this server: an API key with **Management access**, which reaches only its own teamspace, or an OAuth token issued for this server. See the [API reference](/api-reference/teamspaces/list-teamspaces) for the routes.
The same operations are available over the REST API at `/api/v2/teamspaces/{teamspaceId}`, so a script can use them without an MCP client. It takes the same credentials as this server: an API key, which reaches only its own teamspace and can make changes only with **Write access**, or an OAuth token issued for this server. See the [API reference](/api-reference/teamspaces/list-teamspaces) for the routes.

## Safety and limits

Expand Down
12 changes: 6 additions & 6 deletions docs/howto/api-keys.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ API keys authenticate your requests to Context7's documentation services. You ca
<Step title="Name the key">
Enter a name (optional but recommended). Descriptive names like "Cursor", "Claude", "VS Code", or "Devin Desktop" help you identify the key later.
</Step>
<Step title="Choose management access">
Tick **Management access** only for a key that manages the teamspace (see [below](#management-access)). Leave it off for keys that only fetch docs.
<Step title="Choose write access">
Every key can read the teamspace through the management API. Tick **Write access** only for a key that must change the teamspace (see [below](#write-access)). Leave it off for keys that only fetch docs or read.
</Step>
<Step title="Copy the key immediately">
Keys are shown only once for security. The format is `ctx7sk-**********************`.
Expand All @@ -36,13 +36,13 @@ API keys authenticate your requests to Context7's documentation services. You ca

<Warning>Store your API key securely. You won't be able to see it again after creation.</Warning>

### Management access
### Write access

The [Context7 Admin MCP](/howto/admin-mcp) and the [management API](/api-reference/teamspaces/list-teamspaces) (`/api/v2/teamspaces/*`) accept an API key only when **Management access** was ticked when the key was created. Such a key can change the teamspace with your role: its members, libraries, rules and policies, usage, and Docs7 and Ask sites. It reaches only its own teamspace.
The [Context7 Admin MCP](/howto/admin-mcp) and the [management API](/api-reference/teamspaces/list-teamspaces) (`/api/v2/teamspaces/*`) accept every API key, but a key is read-only there unless **Write access** was ticked when the key was created. A read-only key can list and read the teamspace with your role. A key with write access can also change it: its members, libraries, rules and policies, usage, and Docs7 and Ask sites. A key reaches only its own teamspace.

![Create New API Key dialog with Management access ticked](/images/dashboard/api-key-management-access.png)
![Create New API Key dialog with Write access ticked](/images/dashboard/api-key-write-access.png)

A key without it gets `403` with the error `management_access_required`. You cannot add management access to an existing key: create a new key with the box ticked. With the Admin MCP you can also sign in with OAuth and use no key.
A read-only key gets `403` with the error `write_access_required` when it tries to make a change. The teamspace invite link also needs write access, because the link lets anyone join. You cannot add write access to an existing key: create a new key with the box ticked. With the Admin MCP you can also sign in with OAuth and use no key.

### Revoking Keys

Expand Down
Binary file removed docs/images/dashboard/api-key-management-access.png
Binary file not shown.
Binary file added docs/images/dashboard/api-key-write-access.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions packages/admin-mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Clients that support MCP OAuth sign in on the first request. The server answers

### API key (CI and scripts)

Create a Context7 API key in [the dashboard](https://context7.com/dashboard) with **Management access** turned on, and send it as a bearer. A key without management access gets 403, and a key reaches only its own teamspace.
Create a Context7 API key in [the dashboard](https://context7.com/dashboard) and send it as a bearer. Every key can read; turn on **Write access** when you create the key to also make changes (a key without it gets 403 on changes). A key reaches only its own teamspace.

```json
{
Expand Down Expand Up @@ -91,7 +91,7 @@ pnpm --filter @upstash/context7-admin-mcp test
cd packages/admin-mcp && CONTEXT7_API_URL=http://localhost:3000/api pnpm dev # http://localhost:3100/mcp; without CONTEXT7_API_URL it calls the production API
```

`pnpm dev` serves the `vercel.json` routes from `api/`, and its OAuth metadata names `http://localhost:3100/mcp`. An OAuth token for it works only against a management API that accepts that audience (a local context7app with `ADMIN_OAUTH_ALLOWED_AUDIENCES`, reached through `CONTEXT7_API_URL`); otherwise send `Authorization: Bearer ctx7sk-…` with a key that has Management access.
`pnpm dev` serves the `vercel.json` routes from `api/`, and its OAuth metadata names `http://localhost:3100/mcp`. An OAuth token for it works only against a management API that accepts that audience (a local context7app with `ADMIN_OAUTH_ALLOWED_AUDIENCES`, reached through `CONTEXT7_API_URL`); otherwise send `Authorization: Bearer ctx7sk-…` with a key (with Write access for changes).

The console page is a React app in `ui/` (Vite, Tailwind), built into one HTML file: `pnpm build:ui` writes `src/ui/console-html.ts`, which is committed because Vercel runs no UI build. Run it after any change under `ui/`. `pnpm demo:ui` serves the page at http://localhost:4174 inside a demo host (ext-apps' `AppBridge` and a fake backend) with theme, display mode (inline, fullscreen, or a host without fullscreen), width, Claude's theme tokens and "opened on" switches, and a log of the page's tool calls and messages.

Expand Down
2 changes: 1 addition & 1 deletion packages/admin-mcp/api/server-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const serverCard = {
{
name: "Authorization",
description:
"Optional. Sign in with OAuth, or send a Context7 API key created with Management access.",
"Optional. Sign in with OAuth, or send a Context7 API key. A key can make changes only when it was created with Write access.",
isRequired: false,
isSecret: true,
value: "Bearer {api_key}",
Expand Down
5 changes: 3 additions & 2 deletions packages/admin-mcp/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,9 @@ <h2>Other clients</h2>
<h2>API key (CI and scripts)</h2>
<p>
Send <code>Authorization: Bearer ctx7sk-…</code> with a key created in the
<a href="https://context7.com/dashboard">dashboard</a> with
<strong>Management access</strong> turned on. A key works on its own teamspace only.
<a href="https://context7.com/dashboard">dashboard</a>. Every key can read; a key created
with <strong>Write access</strong> turned on can also make changes. A key works on its own
teamspace only.
</p>

<h2>Good to know</h2>
Expand Down
4 changes: 2 additions & 2 deletions packages/admin-mcp/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ function withoutNulls(value: unknown): unknown {

/** What the model can do about the usual API refusals. */
const NEXT_STEP: Record<string, string> = {
management_access_required:
"The API key has no management access. Ask the user to create a key with Management access in https://context7.com/dashboard, or to sign in with OAuth.",
write_access_required:
"The API key can only read. To make this change, ask the user to create a key with Write access in https://context7.com/dashboard, or to sign in with OAuth.",
docs7_pro_required:
"This needs Docs7 Pro. The owner can enable it at https://context7.com/docs7.",
paid_plan_required: "This needs a paid plan: https://context7.com/plans.",
Expand Down
Loading