diff --git a/docs/howto/admin-mcp.mdx b/docs/howto/admin-mcp.mdx index 36ae506a7..9fe098763 100644 --- a/docs/howto/admin-mcp.mdx +++ b/docs/howto/admin-mcp.mdx @@ -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 { @@ -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 diff --git a/docs/howto/api-keys.mdx b/docs/howto/api-keys.mdx index 3686a36e3..d492d990b 100644 --- a/docs/howto/api-keys.mdx +++ b/docs/howto/api-keys.mdx @@ -18,8 +18,8 @@ API keys authenticate your requests to Context7's documentation services. You ca Enter a name (optional but recommended). Descriptive names like "Cursor", "Claude", "VS Code", or "Devin Desktop" help you identify the key later. - - Tick **Management access** only for a key that manages the teamspace (see [below](#management-access)). Leave it off for keys that only fetch docs. + + 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. Keys are shown only once for security. The format is `ctx7sk-**********************`. @@ -36,13 +36,13 @@ API keys authenticate your requests to Context7's documentation services. You ca Store your API key securely. You won't be able to see it again after creation. -### 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 diff --git a/docs/images/dashboard/api-key-management-access.png b/docs/images/dashboard/api-key-management-access.png deleted file mode 100644 index 86e786461..000000000 Binary files a/docs/images/dashboard/api-key-management-access.png and /dev/null differ diff --git a/docs/images/dashboard/api-key-write-access.png b/docs/images/dashboard/api-key-write-access.png new file mode 100644 index 000000000..9d2931a86 Binary files /dev/null and b/docs/images/dashboard/api-key-write-access.png differ diff --git a/packages/admin-mcp/README.md b/packages/admin-mcp/README.md index 5553a4acc..6afe2f371 100644 --- a/packages/admin-mcp/README.md +++ b/packages/admin-mcp/README.md @@ -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 { @@ -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. diff --git a/packages/admin-mcp/api/server-card.ts b/packages/admin-mcp/api/server-card.ts index 020f9a55a..a88139884 100644 --- a/packages/admin-mcp/api/server-card.ts +++ b/packages/admin-mcp/api/server-card.ts @@ -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}", diff --git a/packages/admin-mcp/public/index.html b/packages/admin-mcp/public/index.html index 430a684e8..3dc82c86d 100644 --- a/packages/admin-mcp/public/index.html +++ b/packages/admin-mcp/public/index.html @@ -121,8 +121,9 @@

Other clients

API key (CI and scripts)

Send Authorization: Bearer ctx7sk-… with a key created in the - dashboard with - Management access turned on. A key works on its own teamspace only. + dashboard. Every key can read; a key created + with Write access turned on can also make changes. A key works on its own + teamspace only.

Good to know

diff --git a/packages/admin-mcp/src/server.ts b/packages/admin-mcp/src/server.ts index d595dc9df..7e5d03b79 100644 --- a/packages/admin-mcp/src/server.ts +++ b/packages/admin-mcp/src/server.ts @@ -133,8 +133,8 @@ function withoutNulls(value: unknown): unknown { /** What the model can do about the usual API refusals. */ const NEXT_STEP: Record = { - 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.",