From 54d55568705922facdc535406c46bf6076aec81a Mon Sep 17 00:00:00 2001 From: wehub-resource-sync Date: Mon, 13 Jul 2026 13:04:05 +0800 Subject: [PATCH] chore: import upstream snapshot with attribution --- .agents/plugins/marketplace.json | 20 + .changeset/README.md | 8 + .changeset/bump-jose-6-2-3.md | 5 + .changeset/config.json | 15 + .claude-plugin/marketplace.json | 14 + .env.example | 24 + .github/ISSUE_TEMPLATE/bug_report.yml | 127 + .github/ISSUE_TEMPLATE/documentation.yml | 50 + .github/ISSUE_TEMPLATE/feature_request.yml | 51 + .github/dependabot.yml | 18 + .github/plugin/marketplace.json | 18 + .github/workflows/canary-release.yml | 46 + .github/workflows/ecr-deploy.yml | 57 + .github/workflows/mcp-registry.yml | 54 + .github/workflows/release.yml | 50 + .github/workflows/test.yml | 72 + .github/workflows/triage-library-report.yml | 40 + .gitignore | 187 + .prettierignore | 31 + LICENSE | 21 + README.md | 163 + README.wehub.md | 7 + SECURITY.md | 44 + docs/adding-libraries.mdx | 62 + .../ai-sdk/agents/context7-agent.mdx | 202 + docs/agentic-tools/ai-sdk/getting-started.mdx | 162 + .../agentic-tools/ai-sdk/tools/query-docs.mdx | 196 + .../ai-sdk/tools/resolve-library-id.mdx | 174 + docs/agentic-tools/overview.mdx | 139 + docs/api-guide.mdx | 204 + docs/clients/claude-code.mdx | 178 + docs/clients/cli.mdx | 251 + docs/clients/codex.mdx | 129 + docs/clients/copilot-cli.mdx | 125 + docs/clients/cursor.mdx | 125 + docs/clients/opencode.mdx | 76 + docs/clients/pi.mdx | 90 + docs/clients/vscode.mdx | 76 + docs/contact.mdx | 4 + docs/docs.json | 297 + docs/enterprise.mdx | 96 + docs/enterprise/api/authentication.mdx | 64 + .../api/context/get-documentation-context.mdx | 5 + .../enterprise/api/parse/get-parse-status.mdx | 5 + .../enterprise/api/parse/import-libraries.mdx | 5 + .../api/parse/parse-a-git-repository.mdx | 5 + docs/enterprise/api/parse/parse-a-website.mdx | 5 + .../parse/parse-an-openapi-spec-by-url.mdx | 5 + .../api/parse/refresh-a-library.mdx | 5 + .../api/parse/upload-an-openapi-spec-file.mdx | 5 + .../api/search/search-for-libraries.mdx | 5 + docs/enterprise/backup-restore.mdx | 151 + docs/enterprise/deployment/docker.mdx | 131 + docs/enterprise/deployment/kubernetes.mdx | 341 + .../enterprise-managed-auth/entra.mdx | 751 ++ .../enterprise-managed-auth/okta.mdx | 129 + docs/enterprise/gitops.mdx | 148 + docs/enterprise/integrations/confluence.mdx | 84 + docs/enterprise/integrations/github.mdx | 107 + docs/enterprise/library-import.mdx | 183 + docs/enterprise/on-premise.mdx | 229 + docs/enterprise/security/entra-sso.mdx | 239 + docs/enterprise/security/oidc-sso.mdx | 172 + docs/howto/api-keys.mdx | 50 + docs/howto/chat-widget.mdx | 211 + docs/howto/claiming-libraries.mdx | 289 + docs/howto/oauth.mdx | 43 + docs/howto/policies.mdx | 62 + docs/howto/private-sources.mdx | 97 + docs/howto/rules.mdx | 42 + docs/howto/teamspace.mdx | 67 + docs/howto/usage.mdx | 40 + docs/howto/verification.mdx | 153 + .../clients/claude-code/mcp-details.png | Bin 0 -> 50376 bytes docs/images/clients/claude-code/mcp-list.png | Bin 0 -> 30130 bytes .../claude-code/mcp-unauthenticated.png | Bin 0 -> 38798 bytes docs/images/clients/cursor/logo.png | Bin 0 -> 40415 bytes docs/images/clients/cursor/mcp-settings.png | Bin 0 -> 69202 bytes docs/images/clients/cursor/rules.png | Bin 0 -> 126692 bytes docs/images/dashboard/add-payment-method.png | Bin 0 -> 611888 bytes .../dashboard/admin/claim-library-button.png | Bin 0 -> 170672 bytes docs/images/dashboard/admin/claim-modal.png | Bin 0 -> 283206 bytes .../dashboard/admin/config-overview.png | Bin 0 -> 285112 bytes .../dashboard/admin/library-manage-button.png | Bin 0 -> 385672 bytes .../dashboard/admin/library-metrics.png | Bin 0 -> 194639 bytes .../dashboard/admin/managing-versions.png | Bin 0 -> 199167 bytes docs/images/dashboard/api-keys-card.png | Bin 0 -> 437054 bytes docs/images/dashboard/billing-page.png | Bin 0 -> 620497 bytes docs/images/dashboard/chat-widget.png | Bin 0 -> 408090 bytes docs/images/dashboard/manage-cards.png | Bin 0 -> 295197 bytes docs/images/dashboard/members-tab.png | Bin 0 -> 432342 bytes .../images/dashboard/private-sources-card.png | Bin 0 -> 542440 bytes .../dashboard/public-repository-filters.png | Bin 0 -> 262159 bytes docs/images/dashboard/source-type-access.png | Bin 0 -> 225607 bytes .../images/dashboard/teamspace-management.png | Bin 0 -> 300993 bytes docs/images/dashboard/usage-stats.png | Bin 0 -> 311385 bytes docs/images/dashboard/user-dropdown.png | Bin 0 -> 598314 bytes .../api-keys/api-keys-create-dialog.png | Bin 0 -> 361656 bytes .../enterprise/api-keys/api-keys-created.png | Bin 0 -> 373780 bytes .../enterprise/api-keys/api-keys-empty.png | Bin 0 -> 127982 bytes .../context7-ema-config.png | Bin 0 -> 236211 bytes .../okta-assignments.png | Bin 0 -> 122038 bytes .../okta-enable-feature.png | Bin 0 -> 219072 bytes .../okta-manage-connections.png | Bin 0 -> 141040 bytes .../okta-requesting-app.png | Bin 0 -> 86287 bytes .../okta-resource-app.png | Bin 0 -> 74592 bytes .../enterprise/entra-sso/01-register-app.png | Bin 0 -> 400247 bytes .../enterprise/entra-sso/02-app-overview.png | Bin 0 -> 593643 bytes .../enterprise/entra-sso/03-client-secret.png | Bin 0 -> 493574 bytes .../enterprise/entra-sso/04-app-roles.png | Bin 0 -> 469869 bytes .../entra-sso/05-assignment-required.png | Bin 0 -> 536302 bytes .../entra-sso/06-assign-user-role.png | Bin 0 -> 344497 bytes .../entra-sso/07-context7-settings-card.png | Bin 0 -> 369557 bytes .../entra-sso/08-filled-credentials.png | Bin 0 -> 435636 bytes .../enterprise/entra-sso/10-login-page.png | Bin 0 -> 232473 bytes .../enterprise/entra-sso/11-users-tab.png | Bin 0 -> 330347 bytes docs/images/enterprise/entra-sso/README.md | 188 + .../enterprise/gitops/gitops-settings.png | Bin 0 -> 187278 bytes .../integrations/confluence-add.png | Bin 0 -> 150245 bytes .../integrations/confluence-settings.png | Bin 0 -> 102444 bytes .../integrations/confluence-source.png | Bin 0 -> 66431 bytes .../enterprise/integrations/git-tokens.png | Bin 0 -> 64220 bytes .../enterprise/integrations/github-app.png | Bin 0 -> 38424 bytes .../integrations/github-permissions.png | Bin 0 -> 96151 bytes .../integrations/github-webhook.png | Bin 0 -> 43398 bytes .../enterprise/library-import/export-menu.png | Bin 0 -> 126029 bytes .../library-import/export-select.png | Bin 0 -> 108729 bytes .../library-import/import-source.png | Bin 0 -> 58999 bytes .../library-import/import-upload.png | Bin 0 -> 77290 bytes .../library-import/imported-badge.png | Bin 0 -> 76133 bytes .../enterprise/oidc-sso/01-login-page.png | Bin 0 -> 52359 bytes .../enterprise/oidc-sso/02-sso-card-oidc.png | Bin 0 -> 214116 bytes .../enterprise/oidc-sso/03-group-mapping.png | Bin 0 -> 41917 bytes .../enterprise/oidc-sso/04-password-card.png | Bin 0 -> 60105 bytes .../enterprise/oidc-sso/05-users-tab.png | Bin 0 -> 165257 bytes .../howto/verification/apply-button.png | Bin 0 -> 49050 bytes .../images/howto/verification/apply-modal.png | Bin 0 -> 73218 bytes .../howto/verification/verification-badge.png | Bin 0 -> 45180 bytes .../coderabbit/add-server-modal.png | Bin 0 -> 593193 bytes .../coderabbit/integrations-tab.png | Bin 0 -> 568068 bytes .../coderabbit/server-connected.png | Bin 0 -> 584276 bytes .../coderabbit/update-mcp-settings.png | Bin 0 -> 357125 bytes .../integrations/tembo/integrations-page.png | Bin 0 -> 449146 bytes .../integrations/tembo/server-connected.png | Bin 0 -> 226669 bytes docs/images/on-premise-architecture.png | Bin 0 -> 121457 bytes docs/images/security/classifier_pipeline.png | Bin 0 -> 35744 bytes docs/installation.mdx | 5 + docs/integrations/code-rabbit.mdx | 62 + docs/integrations/factory-ai.mdx | 50 + docs/integrations/github-actions.mdx | 81 + docs/integrations/mastra.mdx | 68 + docs/integrations/tembo.mdx | 36 + docs/library-owners.mdx | 147 + docs/library-updates.mdx | 60 + docs/openapi-enterprise.json | 926 +++ docs/openapi.json | 2795 ++++++++ docs/overview.mdx | 51 + docs/plans-pricing.mdx | 5 + docs/public/favicon.ico | Bin 0 -> 1489 bytes docs/public/logo/logo-dark.svg | 8 + docs/public/logo/logo.png | Bin 0 -> 9380 bytes docs/public/logo/logo.svg | 8 + docs/resources/all-clients.mdx | 1337 ++++ docs/resources/developer.mdx | 116 + docs/resources/troubleshooting.mdx | 363 + docs/sdks/ts/commands/get-context.mdx | 154 + docs/sdks/ts/commands/search-library.mdx | 152 + docs/sdks/ts/getting-started.mdx | 136 + docs/security/auth-and-access-control.mdx | 38 + docs/security/best-practices.mdx | 31 + docs/security/compliance-and-reporting.mdx | 35 + docs/security/data-privacy.mdx | 148 + docs/security/data-safety.mdx | 19 + docs/security/infrastructure.mdx | 56 + docs/security/overview.mdx | 59 + docs/tips.mdx | 38 + eslint.config.js | 37 + gemini-extension.json | 18 + i18n/README.ar.md | 318 + i18n/README.de.md | 330 + i18n/README.es.md | 257 + i18n/README.fr.md | 359 + i18n/README.id-ID.md | 918 +++ i18n/README.it.md | 331 + i18n/README.ja.md | 673 ++ i18n/README.ko.md | 227 + i18n/README.pt-BR.md | 1032 +++ i18n/README.ru.md | 381 + i18n/README.tr.md | 301 + i18n/README.uk.md | 825 +++ i18n/README.vi.md | 909 +++ i18n/README.zh-CN.md | 155 + i18n/README.zh-TW.md | 245 + package.json | 61 + packages/cli/.gitignore | 3 + packages/cli/CHANGELOG.md | 270 + packages/cli/README.md | 158 + packages/cli/eslint.config.js | 47 + packages/cli/package.json | 69 + .../cli/src/__tests__/auth-commands.test.ts | 320 + packages/cli/src/__tests__/auth-utils.test.ts | 430 ++ .../find-docs-skill-alignment.test.ts | 35 + packages/cli/src/__tests__/installer.test.ts | 159 + packages/cli/src/__tests__/library-id.test.ts | 44 + packages/cli/src/__tests__/remove.test.ts | 357 + packages/cli/src/__tests__/setup.test.ts | 1313 ++++ packages/cli/src/__tests__/skill-list.test.ts | 75 + .../cli/src/__tests__/storage-paths.test.ts | 70 + .../cli/src/__tests__/update-check.test.ts | 301 + .../cli/src/__tests__/upgrade-command.test.ts | 319 + packages/cli/src/commands/auth.ts | 266 + packages/cli/src/commands/docs.ts | 241 + packages/cli/src/commands/generate.ts | 563 ++ packages/cli/src/commands/remove.ts | 527 ++ packages/cli/src/commands/setup.ts | 550 ++ packages/cli/src/commands/skill.ts | 1026 +++ packages/cli/src/commands/upgrade.ts | 190 + packages/cli/src/constants.ts | 10 + packages/cli/src/index.ts | 83 + packages/cli/src/setup/agents.ts | 303 + packages/cli/src/setup/mcp-writer.ts | 340 + packages/cli/src/setup/templates.ts | 95 + packages/cli/src/types.ts | 252 + packages/cli/src/utils/api.ts | 361 + packages/cli/src/utils/auth.ts | 239 + packages/cli/src/utils/deps.ts | 102 + packages/cli/src/utils/github.ts | 311 + packages/cli/src/utils/ide.ts | 289 + packages/cli/src/utils/installer.ts | 49 + packages/cli/src/utils/library-id.ts | 22 + packages/cli/src/utils/logger.ts | 37 + packages/cli/src/utils/parse-input.ts | 25 + packages/cli/src/utils/prompts.ts | 134 + packages/cli/src/utils/selectOrInput.ts | 111 + packages/cli/src/utils/skill-name.ts | 24 + packages/cli/src/utils/storage-paths.ts | 129 + packages/cli/src/utils/tracking.ts | 10 + packages/cli/src/utils/update-check.ts | 300 + packages/cli/tsconfig.json | 21 + packages/cli/tsup.config.ts | 20 + packages/cli/vitest.config.ts | 9 + packages/mcp/.prettierignore | 12 + packages/mcp/CHANGELOG.md | 217 + packages/mcp/Dockerfile | 29 + packages/mcp/LICENSE | 21 + packages/mcp/README.md | 1611 +++++ packages/mcp/eslint.config.js | 47 + packages/mcp/mcpb/.mcpbignore | 25 + packages/mcp/mcpb/context7.mcpb | Bin 0 -> 20484 bytes packages/mcp/mcpb/manifest.json | 49 + packages/mcp/package.json | 62 + packages/mcp/prettier.config.mjs | 13 + packages/mcp/schema/context7.json | 130 + packages/mcp/smithery.yaml | 9 + packages/mcp/src/index.ts | 655 ++ packages/mcp/src/lib/api.ts | 175 + packages/mcp/src/lib/auth/auth-prompt.ts | 91 + packages/mcp/src/lib/client-ip.ts | 78 + packages/mcp/src/lib/constants.ts | 22 + packages/mcp/src/lib/encryption.ts | 62 + packages/mcp/src/lib/jwt.ts | 120 + packages/mcp/src/lib/redis.ts | 17 + packages/mcp/src/lib/sessionStore.ts | 49 + packages/mcp/src/lib/types.ts | 47 + packages/mcp/src/lib/utils.ts | 98 + packages/mcp/test/certificate.test.ts | 41 + packages/mcp/test/client-ip.test.ts | 96 + packages/mcp/test/jwt.test.ts | 193 + packages/mcp/tsconfig.json | 12 + packages/mcp/tsconfig.test.json | 9 + packages/pi/.prettierignore | 9 + packages/pi/CHANGELOG.md | 13 + packages/pi/LICENSE | 21 + packages/pi/README.md | 46 + packages/pi/__tests__/extension.test.ts | 56 + packages/pi/eslint.config.js | 41 + packages/pi/extensions/context7.ts | 10 + packages/pi/lib/api.ts | 65 + packages/pi/lib/format.ts | 61 + packages/pi/lib/prompts.ts | 60 + packages/pi/lib/result.ts | 8 + packages/pi/lib/tools/query-docs.ts | 26 + packages/pi/lib/tools/resolve-library-id.ts | 30 + packages/pi/lib/types.ts | 26 + packages/pi/package.json | 69 + packages/pi/prompts/c7-docs.md | 12 + packages/pi/skills/context7-docs/SKILL.md | 45 + packages/pi/tsconfig.json | 24 + packages/pi/vitest.config.ts | 13 + packages/sdk/CHANGELOG.md | 34 + packages/sdk/LICENSE | 21 + packages/sdk/README.md | 94 + packages/sdk/eslint.config.js | 47 + packages/sdk/package.json | 56 + packages/sdk/prettier.config.mjs | 13 + packages/sdk/src/client.test.ts | 179 + packages/sdk/src/client.ts | 132 + packages/sdk/src/commands/command.ts | 39 + .../src/commands/get-context/index.test.ts | 67 + .../sdk/src/commands/get-context/index.ts | 49 + .../sdk/src/commands/get-context/types.ts | 21 + packages/sdk/src/commands/index.ts | 2 + .../src/commands/search-library/index.test.ts | 45 + .../sdk/src/commands/search-library/index.ts | 47 + .../sdk/src/commands/search-library/types.ts | 13 + packages/sdk/src/commands/types.ts | 57 + packages/sdk/src/error/index.ts | 6 + packages/sdk/src/http/index.test.ts | 81 + packages/sdk/src/http/index.ts | 212 + packages/sdk/src/utils/format.ts | 94 + packages/sdk/src/utils/test-utils.ts | 21 + packages/sdk/tsconfig.json | 24 + packages/sdk/tsup.config.ts | 8 + packages/sdk/vitest.config.ts | 22 + packages/tools-ai-sdk/CHANGELOG.md | 54 + packages/tools-ai-sdk/README.md | 101 + packages/tools-ai-sdk/eslint.config.js | 47 + packages/tools-ai-sdk/package.json | 69 + packages/tools-ai-sdk/src/agents/context7.ts | 64 + packages/tools-ai-sdk/src/agents/index.ts | 1 + packages/tools-ai-sdk/src/index.test.ts | 228 + packages/tools-ai-sdk/src/index.ts | 21 + packages/tools-ai-sdk/src/prompts/index.ts | 6 + packages/tools-ai-sdk/src/prompts/system.ts | 82 + packages/tools-ai-sdk/src/tools/index.ts | 3 + packages/tools-ai-sdk/src/tools/query-docs.ts | 68 + .../src/tools/resolve-library-id.ts | 67 + packages/tools-ai-sdk/src/tools/types.ts | 9 + packages/tools-ai-sdk/tsconfig.json | 25 + packages/tools-ai-sdk/tsup.config.ts | 18 + packages/tools-ai-sdk/vitest.config.ts | 20 + .../context7/.claude-plugin/plugin.json | 7 + plugins/claude/context7/.mcp.json | 11 + plugins/claude/context7/README.md | 84 + .../claude/context7/agents/docs-researcher.md | 41 + plugins/claude/context7/commands/docs.md | 45 + .../context7/skills/context7-mcp/SKILL.md | 56 + .../codex/context7/.codex-plugin/plugin.json | 32 + plugins/codex/context7/.mcp.json | 8 + plugins/codex/context7/README.md | 77 + .../context7/skills/context7-mcp/SKILL.md | 56 + plugins/context7-power/POWER.md | 78 + plugins/context7-power/mcp.json | 7 + plugins/copilot/context7/.mcp.json | 11 + plugins/copilot/context7/README.md | 84 + .../context7/agents/docs-researcher.agent.md | 40 + plugins/copilot/context7/commands/docs.md | 44 + plugins/copilot/context7/plugin.json | 15 + .../context7/skills/context7-mcp/SKILL.md | 56 + plugins/cursor/context7/.cursor/plugin.json | 13 + plugins/cursor/context7/README.md | 53 + .../cursor/context7/agents/docs-researcher.md | 40 + plugins/cursor/context7/mcp.json | 5 + .../cursor/context7/rules/use-context7.mdc | 18 + .../context7/skills/context7-mcp/SKILL.md | 56 + pnpm-lock.yaml | 6249 +++++++++++++++++ pnpm-workspace.yaml | 7 + prettier.config.mjs | 13 + public/context7-icon-green.svg | 7 + public/context7-icon.svg | 7 + public/context7-logo.svg | 8 + public/cover.png | Bin 0 -> 688329 bytes public/icon.png | Bin 0 -> 9380 bytes rules/context7-cli.md | 16 + rules/context7-mcp.md | 10 + server.json | 67 + skills/context7-cli/SKILL.md | 72 + skills/context7-cli/references/docs.md | 114 + skills/context7-cli/references/setup.md | 43 + skills/context7-cli/references/skills.md | 118 + skills/context7-mcp/SKILL.md | 56 + skills/find-docs/SKILL.md | 159 + tsconfig.json | 13 + 373 files changed, 47482 insertions(+) create mode 100644 .agents/plugins/marketplace.json create mode 100644 .changeset/README.md create mode 100644 .changeset/bump-jose-6-2-3.md create mode 100644 .changeset/config.json create mode 100644 .claude-plugin/marketplace.json create mode 100644 .env.example create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/documentation.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/dependabot.yml create mode 100644 .github/plugin/marketplace.json create mode 100644 .github/workflows/canary-release.yml create mode 100644 .github/workflows/ecr-deploy.yml create mode 100644 .github/workflows/mcp-registry.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/test.yml create mode 100644 .github/workflows/triage-library-report.yml create mode 100644 .gitignore create mode 100644 .prettierignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 README.wehub.md create mode 100644 SECURITY.md create mode 100644 docs/adding-libraries.mdx create mode 100644 docs/agentic-tools/ai-sdk/agents/context7-agent.mdx create mode 100644 docs/agentic-tools/ai-sdk/getting-started.mdx create mode 100644 docs/agentic-tools/ai-sdk/tools/query-docs.mdx create mode 100644 docs/agentic-tools/ai-sdk/tools/resolve-library-id.mdx create mode 100644 docs/agentic-tools/overview.mdx create mode 100644 docs/api-guide.mdx create mode 100644 docs/clients/claude-code.mdx create mode 100644 docs/clients/cli.mdx create mode 100644 docs/clients/codex.mdx create mode 100644 docs/clients/copilot-cli.mdx create mode 100644 docs/clients/cursor.mdx create mode 100644 docs/clients/opencode.mdx create mode 100644 docs/clients/pi.mdx create mode 100644 docs/clients/vscode.mdx create mode 100644 docs/contact.mdx create mode 100644 docs/docs.json create mode 100644 docs/enterprise.mdx create mode 100644 docs/enterprise/api/authentication.mdx create mode 100644 docs/enterprise/api/context/get-documentation-context.mdx create mode 100644 docs/enterprise/api/parse/get-parse-status.mdx create mode 100644 docs/enterprise/api/parse/import-libraries.mdx create mode 100644 docs/enterprise/api/parse/parse-a-git-repository.mdx create mode 100644 docs/enterprise/api/parse/parse-a-website.mdx create mode 100644 docs/enterprise/api/parse/parse-an-openapi-spec-by-url.mdx create mode 100644 docs/enterprise/api/parse/refresh-a-library.mdx create mode 100644 docs/enterprise/api/parse/upload-an-openapi-spec-file.mdx create mode 100644 docs/enterprise/api/search/search-for-libraries.mdx create mode 100644 docs/enterprise/backup-restore.mdx create mode 100644 docs/enterprise/deployment/docker.mdx create mode 100644 docs/enterprise/deployment/kubernetes.mdx create mode 100644 docs/enterprise/enterprise-managed-auth/entra.mdx create mode 100644 docs/enterprise/enterprise-managed-auth/okta.mdx create mode 100644 docs/enterprise/gitops.mdx create mode 100644 docs/enterprise/integrations/confluence.mdx create mode 100644 docs/enterprise/integrations/github.mdx create mode 100644 docs/enterprise/library-import.mdx create mode 100644 docs/enterprise/on-premise.mdx create mode 100644 docs/enterprise/security/entra-sso.mdx create mode 100644 docs/enterprise/security/oidc-sso.mdx create mode 100644 docs/howto/api-keys.mdx create mode 100644 docs/howto/chat-widget.mdx create mode 100644 docs/howto/claiming-libraries.mdx create mode 100644 docs/howto/oauth.mdx create mode 100644 docs/howto/policies.mdx create mode 100644 docs/howto/private-sources.mdx create mode 100644 docs/howto/rules.mdx create mode 100644 docs/howto/teamspace.mdx create mode 100644 docs/howto/usage.mdx create mode 100644 docs/howto/verification.mdx create mode 100644 docs/images/clients/claude-code/mcp-details.png create mode 100644 docs/images/clients/claude-code/mcp-list.png create mode 100644 docs/images/clients/claude-code/mcp-unauthenticated.png create mode 100644 docs/images/clients/cursor/logo.png create mode 100644 docs/images/clients/cursor/mcp-settings.png create mode 100644 docs/images/clients/cursor/rules.png create mode 100644 docs/images/dashboard/add-payment-method.png create mode 100644 docs/images/dashboard/admin/claim-library-button.png create mode 100644 docs/images/dashboard/admin/claim-modal.png create mode 100644 docs/images/dashboard/admin/config-overview.png create mode 100644 docs/images/dashboard/admin/library-manage-button.png create mode 100644 docs/images/dashboard/admin/library-metrics.png create mode 100644 docs/images/dashboard/admin/managing-versions.png create mode 100644 docs/images/dashboard/api-keys-card.png create mode 100644 docs/images/dashboard/billing-page.png create mode 100644 docs/images/dashboard/chat-widget.png create mode 100644 docs/images/dashboard/manage-cards.png create mode 100644 docs/images/dashboard/members-tab.png create mode 100644 docs/images/dashboard/private-sources-card.png create mode 100644 docs/images/dashboard/public-repository-filters.png create mode 100644 docs/images/dashboard/source-type-access.png create mode 100644 docs/images/dashboard/teamspace-management.png create mode 100644 docs/images/dashboard/usage-stats.png create mode 100644 docs/images/dashboard/user-dropdown.png create mode 100644 docs/images/enterprise/api-keys/api-keys-create-dialog.png create mode 100644 docs/images/enterprise/api-keys/api-keys-created.png create mode 100644 docs/images/enterprise/api-keys/api-keys-empty.png create mode 100644 docs/images/enterprise/enterprise-managed-auth/context7-ema-config.png create mode 100644 docs/images/enterprise/enterprise-managed-auth/okta-assignments.png create mode 100644 docs/images/enterprise/enterprise-managed-auth/okta-enable-feature.png create mode 100644 docs/images/enterprise/enterprise-managed-auth/okta-manage-connections.png create mode 100644 docs/images/enterprise/enterprise-managed-auth/okta-requesting-app.png create mode 100644 docs/images/enterprise/enterprise-managed-auth/okta-resource-app.png create mode 100644 docs/images/enterprise/entra-sso/01-register-app.png create mode 100644 docs/images/enterprise/entra-sso/02-app-overview.png create mode 100644 docs/images/enterprise/entra-sso/03-client-secret.png create mode 100644 docs/images/enterprise/entra-sso/04-app-roles.png create mode 100644 docs/images/enterprise/entra-sso/05-assignment-required.png create mode 100644 docs/images/enterprise/entra-sso/06-assign-user-role.png create mode 100644 docs/images/enterprise/entra-sso/07-context7-settings-card.png create mode 100644 docs/images/enterprise/entra-sso/08-filled-credentials.png create mode 100644 docs/images/enterprise/entra-sso/10-login-page.png create mode 100644 docs/images/enterprise/entra-sso/11-users-tab.png create mode 100644 docs/images/enterprise/entra-sso/README.md create mode 100644 docs/images/enterprise/gitops/gitops-settings.png create mode 100644 docs/images/enterprise/integrations/confluence-add.png create mode 100644 docs/images/enterprise/integrations/confluence-settings.png create mode 100644 docs/images/enterprise/integrations/confluence-source.png create mode 100644 docs/images/enterprise/integrations/git-tokens.png create mode 100644 docs/images/enterprise/integrations/github-app.png create mode 100644 docs/images/enterprise/integrations/github-permissions.png create mode 100644 docs/images/enterprise/integrations/github-webhook.png create mode 100644 docs/images/enterprise/library-import/export-menu.png create mode 100644 docs/images/enterprise/library-import/export-select.png create mode 100644 docs/images/enterprise/library-import/import-source.png create mode 100644 docs/images/enterprise/library-import/import-upload.png create mode 100644 docs/images/enterprise/library-import/imported-badge.png create mode 100644 docs/images/enterprise/oidc-sso/01-login-page.png create mode 100644 docs/images/enterprise/oidc-sso/02-sso-card-oidc.png create mode 100644 docs/images/enterprise/oidc-sso/03-group-mapping.png create mode 100644 docs/images/enterprise/oidc-sso/04-password-card.png create mode 100644 docs/images/enterprise/oidc-sso/05-users-tab.png create mode 100644 docs/images/howto/verification/apply-button.png create mode 100644 docs/images/howto/verification/apply-modal.png create mode 100644 docs/images/howto/verification/verification-badge.png create mode 100644 docs/images/integrations/coderabbit/add-server-modal.png create mode 100644 docs/images/integrations/coderabbit/integrations-tab.png create mode 100644 docs/images/integrations/coderabbit/server-connected.png create mode 100644 docs/images/integrations/coderabbit/update-mcp-settings.png create mode 100644 docs/images/integrations/tembo/integrations-page.png create mode 100644 docs/images/integrations/tembo/server-connected.png create mode 100644 docs/images/on-premise-architecture.png create mode 100644 docs/images/security/classifier_pipeline.png create mode 100644 docs/installation.mdx create mode 100644 docs/integrations/code-rabbit.mdx create mode 100644 docs/integrations/factory-ai.mdx create mode 100644 docs/integrations/github-actions.mdx create mode 100644 docs/integrations/mastra.mdx create mode 100644 docs/integrations/tembo.mdx create mode 100644 docs/library-owners.mdx create mode 100644 docs/library-updates.mdx create mode 100644 docs/openapi-enterprise.json create mode 100644 docs/openapi.json create mode 100644 docs/overview.mdx create mode 100644 docs/plans-pricing.mdx create mode 100644 docs/public/favicon.ico create mode 100644 docs/public/logo/logo-dark.svg create mode 100644 docs/public/logo/logo.png create mode 100644 docs/public/logo/logo.svg create mode 100644 docs/resources/all-clients.mdx create mode 100644 docs/resources/developer.mdx create mode 100644 docs/resources/troubleshooting.mdx create mode 100644 docs/sdks/ts/commands/get-context.mdx create mode 100644 docs/sdks/ts/commands/search-library.mdx create mode 100644 docs/sdks/ts/getting-started.mdx create mode 100644 docs/security/auth-and-access-control.mdx create mode 100644 docs/security/best-practices.mdx create mode 100644 docs/security/compliance-and-reporting.mdx create mode 100644 docs/security/data-privacy.mdx create mode 100644 docs/security/data-safety.mdx create mode 100644 docs/security/infrastructure.mdx create mode 100644 docs/security/overview.mdx create mode 100644 docs/tips.mdx create mode 100644 eslint.config.js create mode 100644 gemini-extension.json create mode 100644 i18n/README.ar.md create mode 100644 i18n/README.de.md create mode 100644 i18n/README.es.md create mode 100644 i18n/README.fr.md create mode 100644 i18n/README.id-ID.md create mode 100644 i18n/README.it.md create mode 100644 i18n/README.ja.md create mode 100644 i18n/README.ko.md create mode 100644 i18n/README.pt-BR.md create mode 100644 i18n/README.ru.md create mode 100644 i18n/README.tr.md create mode 100644 i18n/README.uk.md create mode 100644 i18n/README.vi.md create mode 100644 i18n/README.zh-CN.md create mode 100644 i18n/README.zh-TW.md create mode 100644 package.json create mode 100644 packages/cli/.gitignore create mode 100644 packages/cli/CHANGELOG.md create mode 100644 packages/cli/README.md create mode 100644 packages/cli/eslint.config.js create mode 100644 packages/cli/package.json create mode 100644 packages/cli/src/__tests__/auth-commands.test.ts create mode 100644 packages/cli/src/__tests__/auth-utils.test.ts create mode 100644 packages/cli/src/__tests__/find-docs-skill-alignment.test.ts create mode 100644 packages/cli/src/__tests__/installer.test.ts create mode 100644 packages/cli/src/__tests__/library-id.test.ts create mode 100644 packages/cli/src/__tests__/remove.test.ts create mode 100644 packages/cli/src/__tests__/setup.test.ts create mode 100644 packages/cli/src/__tests__/skill-list.test.ts create mode 100644 packages/cli/src/__tests__/storage-paths.test.ts create mode 100644 packages/cli/src/__tests__/update-check.test.ts create mode 100644 packages/cli/src/__tests__/upgrade-command.test.ts create mode 100644 packages/cli/src/commands/auth.ts create mode 100644 packages/cli/src/commands/docs.ts create mode 100644 packages/cli/src/commands/generate.ts create mode 100644 packages/cli/src/commands/remove.ts create mode 100644 packages/cli/src/commands/setup.ts create mode 100644 packages/cli/src/commands/skill.ts create mode 100644 packages/cli/src/commands/upgrade.ts create mode 100644 packages/cli/src/constants.ts create mode 100644 packages/cli/src/index.ts create mode 100644 packages/cli/src/setup/agents.ts create mode 100644 packages/cli/src/setup/mcp-writer.ts create mode 100644 packages/cli/src/setup/templates.ts create mode 100644 packages/cli/src/types.ts create mode 100644 packages/cli/src/utils/api.ts create mode 100644 packages/cli/src/utils/auth.ts create mode 100644 packages/cli/src/utils/deps.ts create mode 100644 packages/cli/src/utils/github.ts create mode 100644 packages/cli/src/utils/ide.ts create mode 100644 packages/cli/src/utils/installer.ts create mode 100644 packages/cli/src/utils/library-id.ts create mode 100644 packages/cli/src/utils/logger.ts create mode 100644 packages/cli/src/utils/parse-input.ts create mode 100644 packages/cli/src/utils/prompts.ts create mode 100644 packages/cli/src/utils/selectOrInput.ts create mode 100644 packages/cli/src/utils/skill-name.ts create mode 100644 packages/cli/src/utils/storage-paths.ts create mode 100644 packages/cli/src/utils/tracking.ts create mode 100644 packages/cli/src/utils/update-check.ts create mode 100644 packages/cli/tsconfig.json create mode 100644 packages/cli/tsup.config.ts create mode 100644 packages/cli/vitest.config.ts create mode 100644 packages/mcp/.prettierignore create mode 100644 packages/mcp/CHANGELOG.md create mode 100644 packages/mcp/Dockerfile create mode 100644 packages/mcp/LICENSE create mode 100644 packages/mcp/README.md create mode 100644 packages/mcp/eslint.config.js create mode 100644 packages/mcp/mcpb/.mcpbignore create mode 100644 packages/mcp/mcpb/context7.mcpb create mode 100644 packages/mcp/mcpb/manifest.json create mode 100644 packages/mcp/package.json create mode 100644 packages/mcp/prettier.config.mjs create mode 100644 packages/mcp/schema/context7.json create mode 100644 packages/mcp/smithery.yaml create mode 100644 packages/mcp/src/index.ts create mode 100644 packages/mcp/src/lib/api.ts create mode 100644 packages/mcp/src/lib/auth/auth-prompt.ts create mode 100644 packages/mcp/src/lib/client-ip.ts create mode 100644 packages/mcp/src/lib/constants.ts create mode 100644 packages/mcp/src/lib/encryption.ts create mode 100644 packages/mcp/src/lib/jwt.ts create mode 100644 packages/mcp/src/lib/redis.ts create mode 100644 packages/mcp/src/lib/sessionStore.ts create mode 100644 packages/mcp/src/lib/types.ts create mode 100644 packages/mcp/src/lib/utils.ts create mode 100644 packages/mcp/test/certificate.test.ts create mode 100644 packages/mcp/test/client-ip.test.ts create mode 100644 packages/mcp/test/jwt.test.ts create mode 100644 packages/mcp/tsconfig.json create mode 100644 packages/mcp/tsconfig.test.json create mode 100644 packages/pi/.prettierignore create mode 100644 packages/pi/CHANGELOG.md create mode 100644 packages/pi/LICENSE create mode 100644 packages/pi/README.md create mode 100644 packages/pi/__tests__/extension.test.ts create mode 100644 packages/pi/eslint.config.js create mode 100644 packages/pi/extensions/context7.ts create mode 100644 packages/pi/lib/api.ts create mode 100644 packages/pi/lib/format.ts create mode 100644 packages/pi/lib/prompts.ts create mode 100644 packages/pi/lib/result.ts create mode 100644 packages/pi/lib/tools/query-docs.ts create mode 100644 packages/pi/lib/tools/resolve-library-id.ts create mode 100644 packages/pi/lib/types.ts create mode 100644 packages/pi/package.json create mode 100644 packages/pi/prompts/c7-docs.md create mode 100644 packages/pi/skills/context7-docs/SKILL.md create mode 100644 packages/pi/tsconfig.json create mode 100644 packages/pi/vitest.config.ts create mode 100644 packages/sdk/CHANGELOG.md create mode 100644 packages/sdk/LICENSE create mode 100644 packages/sdk/README.md create mode 100644 packages/sdk/eslint.config.js create mode 100644 packages/sdk/package.json create mode 100644 packages/sdk/prettier.config.mjs create mode 100644 packages/sdk/src/client.test.ts create mode 100644 packages/sdk/src/client.ts create mode 100644 packages/sdk/src/commands/command.ts create mode 100644 packages/sdk/src/commands/get-context/index.test.ts create mode 100644 packages/sdk/src/commands/get-context/index.ts create mode 100644 packages/sdk/src/commands/get-context/types.ts create mode 100644 packages/sdk/src/commands/index.ts create mode 100644 packages/sdk/src/commands/search-library/index.test.ts create mode 100644 packages/sdk/src/commands/search-library/index.ts create mode 100644 packages/sdk/src/commands/search-library/types.ts create mode 100644 packages/sdk/src/commands/types.ts create mode 100644 packages/sdk/src/error/index.ts create mode 100644 packages/sdk/src/http/index.test.ts create mode 100644 packages/sdk/src/http/index.ts create mode 100644 packages/sdk/src/utils/format.ts create mode 100644 packages/sdk/src/utils/test-utils.ts create mode 100644 packages/sdk/tsconfig.json create mode 100644 packages/sdk/tsup.config.ts create mode 100644 packages/sdk/vitest.config.ts create mode 100644 packages/tools-ai-sdk/CHANGELOG.md create mode 100644 packages/tools-ai-sdk/README.md create mode 100644 packages/tools-ai-sdk/eslint.config.js create mode 100644 packages/tools-ai-sdk/package.json create mode 100644 packages/tools-ai-sdk/src/agents/context7.ts create mode 100644 packages/tools-ai-sdk/src/agents/index.ts create mode 100644 packages/tools-ai-sdk/src/index.test.ts create mode 100644 packages/tools-ai-sdk/src/index.ts create mode 100644 packages/tools-ai-sdk/src/prompts/index.ts create mode 100644 packages/tools-ai-sdk/src/prompts/system.ts create mode 100644 packages/tools-ai-sdk/src/tools/index.ts create mode 100644 packages/tools-ai-sdk/src/tools/query-docs.ts create mode 100644 packages/tools-ai-sdk/src/tools/resolve-library-id.ts create mode 100644 packages/tools-ai-sdk/src/tools/types.ts create mode 100644 packages/tools-ai-sdk/tsconfig.json create mode 100644 packages/tools-ai-sdk/tsup.config.ts create mode 100644 packages/tools-ai-sdk/vitest.config.ts create mode 100644 plugins/claude/context7/.claude-plugin/plugin.json create mode 100644 plugins/claude/context7/.mcp.json create mode 100644 plugins/claude/context7/README.md create mode 100644 plugins/claude/context7/agents/docs-researcher.md create mode 100644 plugins/claude/context7/commands/docs.md create mode 100644 plugins/claude/context7/skills/context7-mcp/SKILL.md create mode 100644 plugins/codex/context7/.codex-plugin/plugin.json create mode 100644 plugins/codex/context7/.mcp.json create mode 100644 plugins/codex/context7/README.md create mode 100644 plugins/codex/context7/skills/context7-mcp/SKILL.md create mode 100644 plugins/context7-power/POWER.md create mode 100644 plugins/context7-power/mcp.json create mode 100644 plugins/copilot/context7/.mcp.json create mode 100644 plugins/copilot/context7/README.md create mode 100644 plugins/copilot/context7/agents/docs-researcher.agent.md create mode 100644 plugins/copilot/context7/commands/docs.md create mode 100644 plugins/copilot/context7/plugin.json create mode 100644 plugins/copilot/context7/skills/context7-mcp/SKILL.md create mode 100644 plugins/cursor/context7/.cursor/plugin.json create mode 100644 plugins/cursor/context7/README.md create mode 100644 plugins/cursor/context7/agents/docs-researcher.md create mode 100644 plugins/cursor/context7/mcp.json create mode 100644 plugins/cursor/context7/rules/use-context7.mdc create mode 100644 plugins/cursor/context7/skills/context7-mcp/SKILL.md create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 prettier.config.mjs create mode 100644 public/context7-icon-green.svg create mode 100644 public/context7-icon.svg create mode 100644 public/context7-logo.svg create mode 100644 public/cover.png create mode 100644 public/icon.png create mode 100644 rules/context7-cli.md create mode 100644 rules/context7-mcp.md create mode 100644 server.json create mode 100644 skills/context7-cli/SKILL.md create mode 100644 skills/context7-cli/references/docs.md create mode 100644 skills/context7-cli/references/setup.md create mode 100644 skills/context7-cli/references/skills.md create mode 100644 skills/context7-mcp/SKILL.md create mode 100644 skills/find-docs/SKILL.md create mode 100644 tsconfig.json diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json new file mode 100644 index 0000000..a017b9b --- /dev/null +++ b/.agents/plugins/marketplace.json @@ -0,0 +1,20 @@ +{ + "name": "context7-marketplace", + "interface": { + "displayName": "Context7 Marketplace" + }, + "plugins": [ + { + "name": "context7", + "source": { + "source": "local", + "path": "./plugins/codex/context7" + }, + "policy": { + "installation": "AVAILABLE", + "authentication": "ON_USE" + }, + "category": "Developer Tools" + } + ] +} diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 0000000..e5b6d8d --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,8 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works +with multi-package repos, or single-package repos to help you version and publish your code. You can +find the full documentation for it [in our repository](https://github.com/changesets/changesets) + +We have a quick list of common questions to get you started engaging with this project in +[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/.changeset/bump-jose-6-2-3.md b/.changeset/bump-jose-6-2-3.md new file mode 100644 index 0000000..4abefa7 --- /dev/null +++ b/.changeset/bump-jose-6-2-3.md @@ -0,0 +1,5 @@ +--- +"@upstash/context7-mcp": patch +--- + +Bump jose from 6.1.3 to 6.2.3. diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 0000000..938f047 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [], + "linked": [], + "access": "public", + "baseBranch": "master", + "updateInternalDependencies": "patch", + "ignore": [], + "snapshot": { + "useCalculatedVersion": true, + "prereleaseTemplate": "{tag}-{datetime}" + } +} diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 0000000..9a32fe7 --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,14 @@ +{ + "name": "context7-marketplace", + "owner": { + "name": "Upstash" + }, + "plugins": [ + { + "name": "context7", + "source": "./plugins/claude/context7", + "description": "Up-to-date documentation lookup. Pull version-specific documentation and code examples directly from source repositories into your LLM context.", + "version": "1.0.2" + } + ] +} diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..3c7ccc0 --- /dev/null +++ b/.env.example @@ -0,0 +1,24 @@ +# Context7 API +CONTEXT7_API_KEY= +CONTEXT7_API_URL=https://context7.com/api + +# MCP HTTP server +UPSTASH_REDIS_REST_URL= +UPSTASH_REDIS_REST_TOKEN= +RESOURCE_URL= +AUTH_SERVER_URL= +OPENAI_APPS_CHALLENGE_TOKEN= +CLIENT_IP_ENCRYPTION_KEY= + +# Network / certificates +HTTPS_PROXY= +NODE_EXTRA_CA_CERTS= + +# GitHub integration +GITHUB_TOKEN= +GH_TOKEN= + +# CLI behavior +CLAUDE_CONFIG_DIR= +CTX7_TELEMETRY_DISABLED= +EDITOR= diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..c265cc3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,127 @@ +name: Bug Report +description: Report a bug or issue with Context7 MCP +title: "[Bug]: " +labels: ["bug", "needs-triage"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to report this issue! Please fill out the form below to help us investigate. + + - type: dropdown + id: client + attributes: + label: MCP Client + description: Which MCP client are you using? + options: + - Cursor + - Claude Desktop + - Claude Code + - Devin Desktop + - VS Code + - Cline + - Zed + - Other (specify in description) + validations: + required: true + + - type: input + id: version + attributes: + label: Context7 MCP Version + description: Which version of Context7 MCP are you using? (Check package.json or npm list) + placeholder: e.g., 1.0.21 + validations: + required: true + + - type: textarea + id: description + attributes: + label: Bug Description + description: A clear description of what the bug is + placeholder: When I try to... + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to Reproduce + description: Steps to reproduce the behavior + placeholder: | + 1. Install Context7 MCP via... + 2. Run the command... + 3. See error... + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Expected Behavior + description: What you expected to happen + validations: + required: true + + - type: textarea + id: actual + attributes: + label: Actual Behavior + description: What actually happened + validations: + required: true + + - type: textarea + id: logs + attributes: + label: Error Messages / Logs + description: Please copy and paste any relevant error messages or logs + render: shell + + - type: dropdown + id: transport + attributes: + label: Transport Method + description: Which transport method are you using? + options: + - stdio (default) + - http + - SSE (deprecated) + validations: + required: true + + - type: input + id: node-version + attributes: + label: Node.js Version + description: Output of `node --version` + placeholder: e.g., v20.10.0 + + - type: input + id: os + attributes: + label: Operating System + description: Which OS are you running? + placeholder: e.g., macOS 14.2, Windows 11, Ubuntu 22.04 + + - type: textarea + id: config + attributes: + label: Configuration + description: Your Context7 MCP configuration (remove any API keys!) + render: json + placeholder: | + { + "mcpServers": { + "context7": { + "command": "npx", + "args": ["-y", "@upstash/context7-mcp"] + } + } + } + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Any other context about the problem (proxy settings, firewalls, etc.) diff --git a/.github/ISSUE_TEMPLATE/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml new file mode 100644 index 0000000..447af35 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.yml @@ -0,0 +1,50 @@ +name: Documentation Issue +description: Report incorrect or missing documentation +title: "[Docs]: " +labels: ["documentation"] +body: + - type: markdown + attributes: + value: | + Found an issue with Context7 documentation? Let us know! + + - type: dropdown + id: doc-type + attributes: + label: Documentation Type + description: Where is the issue? + options: + - README + - Installation instructions + - API documentation + - Library-specific docs + - Configuration examples + validations: + required: true + + - type: textarea + id: issue + attributes: + label: Issue Description + description: What's wrong or missing? + validations: + required: true + + - type: input + id: location + attributes: + label: Documentation Location + description: Link or section name where the issue exists + placeholder: e.g., README.md line 45, or "Installation via Smithery" section + + - type: textarea + id: suggestion + attributes: + label: Suggested Fix + description: How should it be corrected or what should be added? + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Any other relevant information diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..6f7055a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,51 @@ +name: Feature Request +description: Suggest a new feature or improvement +title: "[Feature]: " +labels: ["enhancement"] +body: + - type: markdown + attributes: + value: | + Thanks for suggesting a feature! We appreciate your input. + + - type: textarea + id: problem + attributes: + label: Problem Description + description: Is your feature request related to a problem? Please describe. + placeholder: I'm frustrated when... + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Proposed Solution + description: Describe the solution you'd like + placeholder: I would like Context7 to... + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives Considered + description: Describe any alternative solutions or features you've considered + + - type: dropdown + id: priority + attributes: + label: Priority + description: How important is this feature to you? + options: + - Nice to have + - Would improve my workflow + - Blocking my usage + validations: + required: true + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Add any other context, screenshots, or examples about the feature request diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..d3a1ced --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,18 @@ +version: 2 +updates: + - package-ecosystem: npm + directory: / + schedule: + interval: monthly + - package-ecosystem: bun + directory: / + schedule: + interval: monthly + - package-ecosystem: docker + directory: / + schedule: + interval: monthly + - package-ecosystem: github-actions + directory: / + schedule: + interval: monthly diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json new file mode 100644 index 0000000..7342e15 --- /dev/null +++ b/.github/plugin/marketplace.json @@ -0,0 +1,18 @@ +{ + "name": "context7-marketplace", + "owner": { + "name": "Upstash" + }, + "metadata": { + "description": "Official Upstash marketplace for the Context7 documentation-lookup plugin on GitHub Copilot CLI.", + "version": "1.0.0" + }, + "plugins": [ + { + "name": "context7", + "source": "./plugins/copilot/context7", + "description": "Up-to-date documentation lookup. Pull version-specific documentation and code examples directly from source repositories into your LLM context.", + "version": "1.0.2" + } + ] +} diff --git a/.github/workflows/canary-release.yml b/.github/workflows/canary-release.yml new file mode 100644 index 0000000..b11fe8d --- /dev/null +++ b/.github/workflows/canary-release.yml @@ -0,0 +1,46 @@ +name: Canary Release + +on: + workflow_dispatch: + inputs: + branch: + description: "Branch to release from (defaults to current branch)" + required: false + type: string + +jobs: + canary-release: + name: Canary Release + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout Repo + uses: actions/checkout@v7 + with: + ref: ${{ inputs.branch || github.ref }} + + - name: Setup Node + uses: actions/setup-node@v6 + with: + node-version: "20" + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + + - name: Configure npm authentication + run: | + echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc + + - name: Install Dependencies + run: pnpm install --frozen-lockfile + + - name: Build all packages + run: pnpm build + + - name: Publish Snapshot + run: pnpm release:snapshot + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/ecr-deploy.yml b/.github/workflows/ecr-deploy.yml new file mode 100644 index 0000000..6e84938 --- /dev/null +++ b/.github/workflows/ecr-deploy.yml @@ -0,0 +1,57 @@ +name: Deploy to AWS ECR + +on: + workflow_dispatch: + inputs: + version: + description: "Docker image version tag (e.g., v0.0.22)" + required: true + type: string + +jobs: + build-and-push: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v7 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v6 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ secrets.AWS_REGION }} + + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push Docker image + id: build-push + uses: docker/build-push-action@v6 + with: + context: . + file: packages/mcp/Dockerfile + platforms: linux/amd64,linux/arm64 + push: true + tags: | + ${{ secrets.ECR_REGISTRY }}/${{ secrets.ECR_REPOSITORY }}:${{ inputs.version }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Create GitHub Summary + run: | + echo "## Docker Image Deployed Successfully" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Image Tag:** \`${{ inputs.version }}\`" >> $GITHUB_STEP_SUMMARY + echo "**Platforms:** \`linux/amd64\`, \`linux/arm64\`" >> $GITHUB_STEP_SUMMARY + echo "**Digest:** \`${{ steps.build-push.outputs.digest }}\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Status:** ✅ Image pushed to AWS ECR" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/mcp-registry.yml b/.github/workflows/mcp-registry.yml new file mode 100644 index 0000000..b5adecf --- /dev/null +++ b/.github/workflows/mcp-registry.yml @@ -0,0 +1,54 @@ +name: Publish to MCP Registry + +on: + workflow_dispatch: + inputs: + version: + description: "Version to publish (defaults to package.json version)" + required: false + type: string + +jobs: + publish-mcp: + name: Publish to MCP Registry + runs-on: ubuntu-latest + permissions: + id-token: write # Required for OIDC authentication with MCP Registry + contents: read + steps: + - name: Checkout Repo + uses: actions/checkout@v7 + + - name: Setup Node + uses: actions/setup-node@v6 + with: + node-version: lts/* + + - name: Set version + run: | + if [ -n "${{ inputs.version }}" ]; then + VERSION="${{ inputs.version }}" + # Remove 'v' prefix if it exists + VERSION="${VERSION#v}" + else + VERSION=$(node -p "require('./packages/mcp/package.json').version") + fi + echo "VERSION=$VERSION" >> $GITHUB_ENV + echo "Publishing version: $VERSION" + + - name: Update package version in server.json + run: | + echo $(jq --arg v "${{ env.VERSION }}" '.version = $v | .packages[0].version = $v' server.json) > server.json + + - name: Validate server.json + run: npx mcp-registry-validator validate server.json + + - name: Install MCP Publisher + run: | + curl -L "https://github.com/modelcontextprotocol/registry/releases/download/v1.4.0/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher + + - name: Login to MCP Registry + run: ./mcp-publisher login github-oidc + + - name: Publish to MCP Registry + run: ./mcp-publisher publish diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..dd7e22e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,50 @@ +name: Release + +on: + push: + branches: + - master + +concurrency: ${{ github.workflow }}-${{ github.ref }} + +jobs: + release: + name: Release + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - name: Checkout Repo + uses: actions/checkout@v7 + + - name: Setup Node + uses: actions/setup-node@v6 + with: + node-version: "20" + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + + - name: Configure npm authentication + run: | + echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc + + - name: Install Dependencies + run: pnpm install --frozen-lockfile + + - name: Build all packages + run: pnpm build + + - name: Create Release PR or Publish + id: changesets + uses: changesets/action@v1 + with: + publish: pnpm release + commit: "chore(release): version packages" + title: "chore(release): version packages" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..3100bea --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,72 @@ +name: Test + +on: + pull_request: + paths: + - "packages/**" + - "package.json" + - "pnpm-lock.yaml" + - "pnpm-workspace.yaml" + - "tsconfig.json" + - "eslint.config.js" + - "prettier.config.mjs" + - ".github/workflows/test.yml" + push: + branches: [master] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + - name: Setup Node + uses: actions/setup-node@v6 + with: + node-version: "20" + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + + - name: Cache pnpm dependencies + uses: actions/cache@v6 + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install Dependencies + run: pnpm install --frozen-lockfile + + - name: Lint + run: pnpm lint:check + + - name: Format + run: pnpm format:check + + - name: Build + run: pnpm build + + - name: Typecheck + run: pnpm typecheck + + - name: Test + run: pnpm test + env: + AWS_REGION: ${{ secrets.AWS_REGION }} + AWS_BEARER_TOKEN_BEDROCK: ${{ secrets.AWS_BEARER_TOKEN_BEDROCK }} + CONTEXT7_API_KEY: ${{ secrets.CONTEXT7_API_KEY }} diff --git a/.github/workflows/triage-library-report.yml b/.github/workflows/triage-library-report.yml new file mode 100644 index 0000000..f19a44a --- /dev/null +++ b/.github/workflows/triage-library-report.yml @@ -0,0 +1,40 @@ +name: Triage library report + +# When a "Library Report" issue is opened, forward it to the triage service so the agent can +# analyze it and post its findings as a comment. +# +# Cross-repo note: this issue lives here (upstash/context7) but the triage agent + its secrets +# (Redis/Vector/model creds + a token that can comment on this repo) live in the context7app +# deployment. A GitHub Action here cannot run the agent, so it only forwards the issue number to +# the app's endpoint with a shared secret; the app runs the read-only agent and posts the comment. +# +# Required repo secrets (Settings → Secrets and variables → Actions): +# TRIAGE_WEBHOOK_URL https:///api/triage/analyze +# TRIAGE_WEBHOOK_SECRET same value as TRIAGE_WEBHOOK_SECRET in the context7app environment + +on: + issues: + types: [opened] + +permissions: {} # no GITHUB_TOKEN needed — the app comments with its own token + +jobs: + triage: + if: contains(github.event.issue.title, 'Library Report') + runs-on: ubuntu-latest + steps: + - name: Forward to triage service + env: + TRIAGE_WEBHOOK_URL: ${{ secrets.TRIAGE_WEBHOOK_URL }} + TRIAGE_WEBHOOK_SECRET: ${{ secrets.TRIAGE_WEBHOOK_SECRET }} + ISSUE_NUMBER: ${{ github.event.issue.number }} + run: | + if [ -z "$TRIAGE_WEBHOOK_URL" ]; then + echo "TRIAGE_WEBHOOK_URL not configured; skipping triage." + exit 0 + fi + echo "Triaging issue #$ISSUE_NUMBER" + curl -fsS --max-time 180 -X POST "$TRIAGE_WEBHOOK_URL" \ + -H "Authorization: Bearer $TRIAGE_WEBHOOK_SECRET" \ + -H "Content-Type: application/json" \ + -d "{\"issueNumber\": $ISSUE_NUMBER}" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cec4734 --- /dev/null +++ b/.gitignore @@ -0,0 +1,187 @@ +# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore + +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Caches + +.cache + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +*.lcov + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) + +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# IntelliJ based IDEs +.idea + +.cursor +!plugins/cursor/context7/.cursor +.opencode +.claude + +# Finder (MacOS) folder config +.DS_Store +package-lock.json + +prompt.txt + +reports +reports-old +src/test/questions* diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..7fd6ada --- /dev/null +++ b/.prettierignore @@ -0,0 +1,31 @@ +# Dependencies +node_modules + +# Lock files +pnpm-lock.yaml +package-lock.json +yarn.lock +bun.lockb + +# Build outputs +dist +build +.next +out + +# Logs +*.log + +# Environment files +.env +.env.* + +# IDE +.vscode +.idea + +# Changesets +.changeset/*.md + +# Documentation +docs diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..17900de --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2021 Upstash, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8a01c35 --- /dev/null +++ b/README.md @@ -0,0 +1,163 @@ +![Cover](https://github.com/upstash/context7/blob/master/public/cover.png?raw=true) + +[![Install MCP Server](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=context7&config=eyJ1cmwiOiJodHRwczovL21jcC5jb250ZXh0Ny5jb20vbWNwIn0%3D) + +# Context7 Platform - Up-to-date Code Docs For Any Prompt + +[![Website](https://img.shields.io/badge/Website-context7.com-blue)](https://context7.com) [![smithery badge](https://smithery.ai/badge/@upstash/context7-mcp)](https://smithery.ai/server/@upstash/context7-mcp) [![NPM Version](https://img.shields.io/npm/v/%40upstash%2Fcontext7-mcp?color=red)](https://www.npmjs.com/package/@upstash/context7-mcp) [![MIT licensed](https://img.shields.io/npm/l/%40upstash%2Fcontext7-mcp)](./LICENSE) + +[![繁體中文](https://img.shields.io/badge/docs-繁體中文-yellow)](./i18n/README.zh-TW.md) [![简体中文](https://img.shields.io/badge/docs-简体中文-yellow)](./i18n/README.zh-CN.md) [![日本語](https://img.shields.io/badge/docs-日本語-b7003a)](./i18n/README.ja.md) [![한국어 문서](https://img.shields.io/badge/docs-한국어-green)](./i18n/README.ko.md) [![Documentación en Español](https://img.shields.io/badge/docs-Español-orange)](./i18n/README.es.md) [![Documentation en Français](https://img.shields.io/badge/docs-Français-blue)](./i18n/README.fr.md) [![Documentação em Português (Brasil)]()](./i18n/README.pt-BR.md) [![Documentazione in italiano](https://img.shields.io/badge/docs-Italian-red)](./i18n/README.it.md) [![Dokumentasi Bahasa Indonesia](https://img.shields.io/badge/docs-Bahasa%20Indonesia-pink)](./i18n/README.id-ID.md) [![Dokumentation auf Deutsch](https://img.shields.io/badge/docs-Deutsch-darkgreen)](./i18n/README.de.md) [![Документация на русском языке](https://img.shields.io/badge/docs-Русский-darkblue)](./i18n/README.ru.md) [![Українська документація](https://img.shields.io/badge/docs-Українська-lightblue)](./i18n/README.uk.md) [![Türkçe Doküman](https://img.shields.io/badge/docs-Türkçe-blue)](./i18n/README.tr.md) [![Arabic Documentation](https://img.shields.io/badge/docs-Arabic-white)](./i18n/README.ar.md) [![Tiếng Việt](https://img.shields.io/badge/docs-Tiếng%20Việt-red)](./i18n/README.vi.md) + +## ❌ Without Context7 + +LLMs rely on outdated or generic information about the libraries you use. You get: + +- ❌ Code examples are outdated and based on year-old training data +- ❌ Hallucinated APIs that don't even exist +- ❌ Generic answers for old package versions + +## ✅ With Context7 + +Context7 pulls up-to-date, version-specific documentation and code examples straight from the source — and places them directly into your prompt. + +```txt +Create a Next.js middleware that checks for a valid JWT in cookies +and redirects unauthenticated users to `/login`. use context7 +``` + +```txt +Configure a Cloudflare Worker script to cache +JSON API responses for five minutes. use context7 +``` + +```txt +Show me the Supabase auth API for email/password sign-up. +``` + +Context7 fetches up-to-date code examples and documentation right into your LLM's context. No tab-switching, no hallucinated APIs that don't exist, no outdated code generation. + +Works in two modes: + +- **CLI + Skills** — installs a skill that guides your agent to fetch docs using `ctx7` CLI commands (no MCP required) +- **MCP** — registers a Context7 MCP server so your agent can call documentation tools natively + +## Installation + +> [!NOTE] +> **API Key Recommended**: Get a free API key at [context7.com/dashboard](https://context7.com/dashboard) for higher rate limits. + +Set up Context7 for your coding agents with a single command. The `ctx7` CLI requires Node.js 18 or newer. + +```bash +npx ctx7 setup +``` + +Authenticates via OAuth, generates an API key, and installs the appropriate skill. You can choose between CLI + Skills or MCP mode. Use `--cursor`, `--claude`, or `--opencode` to target a specific agent. + +To remove the generated setup later, run `npx ctx7 remove`. If you globally installed the CLI with `npm install -g ctx7`, remove that package separately with `npm uninstall -g ctx7`. + +To configure manually, use the Context7 server URL `https://mcp.context7.com/mcp` with your MCP client and pass your API key via the `CONTEXT7_API_KEY` header. See the link below for client-specific setup instructions. + +**[Manual Installation / Other Clients →](https://context7.com/docs/resources/all-clients)** + +## Important Tips + +### Use Library Id + +If you already know exactly which library you want to use, add its Context7 ID to your prompt. That way, Context7 can skip the library-matching step and directly retrieve docs. + +```txt +Implement basic authentication with Supabase. use library /supabase/supabase for API and docs. +``` + +The slash syntax tells Context7 exactly which library to load docs for. + +### Specify a Version + +To get documentation for a specific library version, just mention the version in your prompt: + +```txt +How do I set up Next.js 14 middleware? use context7 +``` + +Context7 will automatically match the appropriate version. + +### Add a Rule + +If you installed via `ctx7 setup`, a skill is configured automatically that triggers Context7 for library-related questions. To set up a rule manually instead, add one to your coding agent: + +- **Cursor**: `Cursor Settings > Rules` +- **Claude Code**: `CLAUDE.md` +- Or the equivalent in your coding agent + +**Example rule:** + +```txt +Always use Context7 when I need library/API documentation, code generation, setup or configuration steps without me having to explicitly ask. +``` + +## Available Tools + +### CLI Commands + +- `ctx7 library `: Searches the Context7 index by library name and returns matching libraries with their IDs. +- `ctx7 docs `: Retrieves documentation for a library using a Context7-compatible library ID (e.g., `/mongodb/docs`, `/vercel/next.js`). + +### MCP Tools + +- `resolve-library-id`: Resolves a general library name into a Context7-compatible library ID. + - `query` (required): The user's question or task (used to rank results by relevance) + - `libraryName` (required): The name of the library to search for +- `query-docs`: Retrieves documentation for a library using a Context7-compatible library ID. + - `libraryId` (required): Exact Context7-compatible library ID (e.g., `/mongodb/docs`, `/vercel/next.js`) + - `query` (required): The question or task to get relevant documentation for + +## More Documentation + +- [CLI Reference](https://context7.com/docs/clients/cli) - Full CLI documentation +- [MCP Clients](https://context7.com/docs/resources/all-clients) - Manual MCP installation for 30+ clients +- [Adding Libraries](https://context7.com/docs/adding-libraries) - Submit your library to Context7 +- [Troubleshooting](https://context7.com/docs/resources/troubleshooting) - Common issues and solutions +- [API Reference](https://context7.com/docs/api-guide) - REST API documentation +- [Developer Guide](https://context7.com/docs/resources/developer) - Run Context7 MCP locally + +## Packages + +- [`@upstash/context7-mcp`](https://www.npmjs.com/package/@upstash/context7-mcp) - MCP server +- [`ctx7`](https://www.npmjs.com/package/ctx7) - CLI +- [`@upstash/context7-sdk`](https://www.npmjs.com/package/@upstash/context7-sdk) - TypeScript SDK +- [`@upstash/context7-tools-ai-sdk`](https://www.npmjs.com/package/@upstash/context7-tools-ai-sdk) - Vercel AI SDK tools +- [`@upstash/context7-pi`](https://www.npmjs.com/package/@upstash/context7-pi) - pi.dev extension + +## Disclaimer + +1- Context7 projects are community-contributed and while we strive to maintain high quality, we cannot guarantee the accuracy, completeness, or security of all library documentation. Projects listed in Context7 are developed and maintained by their respective owners, not by Context7. If you encounter any suspicious, inappropriate, or potentially harmful content, please use the "Report" button on the project page to notify us immediately. We take all reports seriously and will review flagged content promptly to maintain the integrity and safety of our platform. By using Context7, you acknowledge that you do so at your own discretion and risk. + +2- This repository hosts the MCP server’s source code. The supporting components — API backend, parsing engine, and crawling engine — are private and not part of this repository. + +## 🤝 Connect with Us + +Stay updated and join our community: + +- 📢 Follow us on [X](https://x.com/context7ai) for the latest news and updates +- 🌐 Visit our [Website](https://context7.com) +- 💬 Join our [Discord Community](https://upstash.com/discord) + +## 📺 Context7 In Media + +- [Better Stack: "Free Tool Makes Cursor 10x Smarter"](https://youtu.be/52FC3qObp9E) +- [Cole Medin: "This is Hands Down the BEST MCP Server for AI Coding Assistants"](https://www.youtube.com/watch?v=G7gK8H6u7Rs) +- [Income Stream Surfers: "Context7 + SequentialThinking MCPs: Is This AGI?"](https://www.youtube.com/watch?v=-ggvzyLpK6o) +- [Julian Goldie SEO: "Context7: New MCP AI Agent Update"](https://www.youtube.com/watch?v=CTZm6fBYisc) +- [JeredBlu: "Context 7 MCP: Get Documentation Instantly + VS Code Setup"](https://www.youtube.com/watch?v=-ls0D-rtET4) +- [Income Stream Surfers: "Context7: The New MCP Server That Will CHANGE AI Coding"](https://www.youtube.com/watch?v=PS-2Azb-C3M) +- [AICodeKing: "Context7 + Cline & RooCode: This MCP Server Makes CLINE 100X MORE EFFECTIVE!"](https://www.youtube.com/watch?v=qZfENAPMnyo) +- [Sean Kochel: "5 MCP Servers For Vibe Coding Glory (Just Plug-In & Go)"](https://www.youtube.com/watch?v=LqTQi8qexJM) + +## ⭐ Star History + +[![Star History Chart](https://api.star-history.com/svg?repos=upstash/context7&type=Date)](https://www.star-history.com/#upstash/context7&Date) + +## 📄 License + +MIT diff --git a/README.wehub.md b/README.wehub.md new file mode 100644 index 0000000..787832c --- /dev/null +++ b/README.wehub.md @@ -0,0 +1,7 @@ +# WeHub 来源说明 + +- 原始项目:`upstash/context7` +- 原始仓库:https://github.com/upstash/context7 +- 导入方式:上游默认分支的最新快照 +- 原作者、版权和许可证信息以原始仓库及本仓库 LICENSE 为准 +- 本文件仅用于记录来源,不代表 WeHub 是原项目作者 diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..2a16d1b --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,44 @@ +# Security Policy + +## Supported Versions + +The following versions of Context7 MCP are currently supported with security updates: + +| Version | Supported | +| ------- | ------------------ | +| 1.0.x | :white_check_mark: | + +We recommend always using the latest version (`@upstash/context7-mcp@latest`) to ensure you have the most recent security patches and features. + +## Reporting a Vulnerability + +We take the security of Context7 seriously. If you discover a security vulnerability, please report it responsibly. + +### How to Report + +- Please use GitHub's [private vulnerability reporting](https://github.com/upstash/context7/security/advisories/new) feature to submit your report +- Alternatively, you can email security concerns to [context7@upstash.com](mailto:context7@upstash.com) + +### What to Include + +- A description of the vulnerability +- Steps to reproduce the issue +- Potential impact of the vulnerability +- Any suggested fixes (optional) + +### What to Expect + +- **Initial Response**: We aim to acknowledge your report within 48 hours +- **Status Updates**: You can expect updates on the progress every 5-7 business days +- **Resolution Timeline**: We strive to resolve critical vulnerabilities within 30 days + +### After Reporting + +- If the vulnerability is accepted, we will work on a fix and coordinate disclosure with you +- We will credit reporters in our release notes (unless you prefer to remain anonymous) +- If the report is declined, we will provide an explanation + +### Please Do Not + +- Disclose the vulnerability publicly before we have addressed it +- Exploit the vulnerability beyond what is necessary to demonstrate it diff --git a/docs/adding-libraries.mdx b/docs/adding-libraries.mdx new file mode 100644 index 0000000..9520490 --- /dev/null +++ b/docs/adding-libraries.mdx @@ -0,0 +1,62 @@ +--- +title: Adding Libraries +description: Add a public library to Context7 so AI coding assistants get up-to-date docs for it +--- + +Context7 indexes public libraries from their source repositories so developers get current, version-specific documentation inside their coding tools. Anyone can add a public library — you don't need to own it. + +## Add a Library + +The fastest way to add a library is through the web interface: + +**[Add a Library →](https://context7.com/add-library)** + + + + Go to [context7.com/add-library](https://context7.com/add-library) and select the **GitHub** tab. + + + Paste the public GitHub repository URL for the library you want to add. + + + Optionally narrow what gets indexed by setting included folders and exclusions. For finer control — committed to the repository itself — add a `context7.json` file (see [Library Owners](/library-owners)). + + + Submit the repository. Context7 parses and indexes the documentation, then makes it available by its [library ID](/api-guide) (format: `/org/project`). + + + + + This page is for **public** libraries. To add internal or private documentation, see the [Private Sources](/howto/private-sources) guide (requires a Pro or Enterprise plan). + + +## What Gets Indexed + +Context7 parses documentation files — `.md`, `.mdx`, `.markdown`, `.rst`, `.txt`, and `.ipynb` — and extracts the code examples and explanations they contain. Raw source code files (`.py`, `.ts`, `.go`, and so on) are not indexed when documentation is present; a library's docs are expected to show the important usage examples. + +If a repository contains little or no documentation content, Context7 falls back to generating examples from the source code itself. For public repositories this fallback is automatic — there is no setting to turn it on or off. For [private repositories](/howto/private-sources), generating docs from source code is opt-in: check **Generate docs** when adding the source, or pass the `generateDocs` flag via the [API](/api-guide). + +To control which folders and files are scanned, set included folders when submitting, or commit a `context7.json` file to the repository (see [Library Owners](/library-owners)). + +## Maintain the Library? + +If you own or maintain the library, you can take control of how it appears in Context7 — configure parsing with `context7.json`, manage versions through a web admin panel, and get higher refresh limits. + + + + Control parsing and presentation with `context7.json` + + + Verify ownership and unlock the admin panel + + + +## Keeping Docs Fresh + +Once a library is added, Context7 [refreshes its documentation automatically](/library-updates) based on popularity, so developers keep receiving up-to-date docs without any manual work. + +For tighter control, add the [Context7 GitHub Action](/integrations/github-actions) to trigger a refresh on every push to your default branch — so a new release's docs are indexed as soon as you ship it. + +## Need Help? + +If you encounter issues or need assistance adding a library, please [open an issue](https://github.com/upstash/context7/issues/new/choose) or reach out to our community. diff --git a/docs/agentic-tools/ai-sdk/agents/context7-agent.mdx b/docs/agentic-tools/ai-sdk/agents/context7-agent.mdx new file mode 100644 index 0000000..7af48ab --- /dev/null +++ b/docs/agentic-tools/ai-sdk/agents/context7-agent.mdx @@ -0,0 +1,202 @@ +--- +title: "Context7Agent" +sidebarTitle: "Context7Agent" +description: "Pre-built AI agent for documentation lookup workflows" +--- + +The `Context7Agent` class is a pre-configured AI agent that handles the complete documentation lookup workflow automatically. It combines both `resolveLibraryId` and `queryDocs` tools with an optimized system prompt. + +## Usage + +```typescript +import { Context7Agent } from "@upstash/context7-tools-ai-sdk"; +import { anthropic } from "@ai-sdk/anthropic"; + +const agent = new Context7Agent({ + model: anthropic("claude-sonnet-4-20250514"), +}); + +const { text } = await agent.generate({ + prompt: "How do I use React Server Components?", +}); + +console.log(text); +``` + +## Configuration + +```typescript +new Context7Agent(config?: Context7AgentConfig) +``` + +### Parameters + + + Configuration options for the agent. + + + + Language model to use. Must be a LanguageModel instance from an AI SDK provider. + + Examples: + - `anthropic('claude-sonnet-4-20250514')` + - `openai('gpt-5.2')` + - `google('gemini-1.5-pro')` + + + Context7 API key. If not provided, uses the `CONTEXT7_API_KEY` environment variable. + + + Custom system prompt. Overrides the default `AGENT_PROMPT`. + + + Condition for when the agent should stop. Defaults to stopping after 5 steps. + + + + + +### Returns + +`Context7Agent` extends the AI SDK `Agent` class and provides `generate()` and `stream()` methods. + +## Agent Workflow + +The agent follows a structured multi-step workflow: + +```mermaid +flowchart TD + A[User Query] --> B[Extract Library Name] + B --> C[Call resolveLibraryId] + C --> D{Results Found?} + D -->|Yes| E[Select Best Match] + D -->|No| F[Report No Results] + E --> G[Call queryDocs] + G --> H{Sufficient Context?} + H -->|Yes| I[Generate Response] + H -->|No| J[Fetch More Docs] + J --> H + I --> K[Return Answer with Examples] +``` + +### Step-by-Step + +1. **Extract library name** - Identifies the library/framework from the user's query +2. **Resolve library** - Calls `resolveLibraryId` to find the Context7 library ID +3. **Select best match** - Analyzes results based on reputation, coverage, and relevance +4. **Fetch documentation** - Calls `queryDocs` with the selected library ID and user's query +5. **Query if needed** - Makes additional queries if initial context is insufficient +6. **Generate response** - Provides an answer with code examples from the documentation + +## Examples + +### Basic Usage + +```typescript +import { Context7Agent } from "@upstash/context7-tools-ai-sdk"; +import { anthropic } from "@ai-sdk/anthropic"; + +const agent = new Context7Agent({ + model: anthropic("claude-sonnet-4-20250514"), +}); + +const { text } = await agent.generate({ + prompt: "How do I set up authentication in Next.js?", +}); + +console.log(text); +``` + +### With OpenAI + +```typescript +import { Context7Agent } from "@upstash/context7-tools-ai-sdk"; +import { openai } from "@ai-sdk/openai"; + +const agent = new Context7Agent({ + model: openai("gpt-5.2"), +}); + +const { text } = await agent.generate({ + prompt: "Explain Tanstack Query's useQuery hook", +}); +``` + +### Streaming Responses + +```typescript +import { Context7Agent } from "@upstash/context7-tools-ai-sdk"; +import { anthropic } from "@ai-sdk/anthropic"; + +const agent = new Context7Agent({ + model: anthropic("claude-sonnet-4-20250514"), +}); + +const { textStream } = await agent.stream({ + prompt: "How do I create a Supabase Edge Function?", +}); + +for await (const chunk of textStream) { + process.stdout.write(chunk); +} +``` + +### Custom Configuration + +```typescript +import { Context7Agent } from "@upstash/context7-tools-ai-sdk"; +import { anthropic } from "@ai-sdk/anthropic"; +import { stepCountIs } from "ai"; + +const agent = new Context7Agent({ + model: anthropic("claude-sonnet-4-20250514"), + apiKey: process.env.CONTEXT7_API_KEY, + stopWhen: stepCountIs(8), // Allow more steps for complex queries +}); +``` + +### Custom System Prompt + +```typescript +import { Context7Agent, AGENT_PROMPT } from "@upstash/context7-tools-ai-sdk"; +import { openai } from "@ai-sdk/openai"; + +const agent = new Context7Agent({ + model: openai("gpt-5.2"), + system: `${AGENT_PROMPT} + +Additional instructions: +- Always include TypeScript examples +- Mention version compatibility when relevant +- Suggest related documentation topics`, +}); +``` + +## Comparison: Agent vs Tools + +| Feature | Context7Agent | Individual Tools | +| ------------- | -------------------- | -------------------- | +| Setup | Single configuration | Configure each tool | +| Workflow | Automatic multi-step | Manual orchestration | +| System prompt | Optimized default | You provide | +| Customization | Limited | Full control | +| Best for | Quick integration | Custom workflows | + +### When to Use the Agent + +- Rapid prototyping +- Standard documentation lookup use cases +- When you want sensible defaults + +### When to Use Individual Tools + +- Custom agentic workflows +- Integration with other tools +- Fine-grained control over the process +- Custom system prompts with specific behavior + +## Related + +- [resolveLibraryId](/agentic-tools/ai-sdk/tools/resolve-library-id) - The library search tool used by the agent +- [queryDocs](/agentic-tools/ai-sdk/tools/query-docs) - The documentation fetch tool used by the agent +- [Getting Started](/agentic-tools/ai-sdk/getting-started) - Overview of the AI SDK integration diff --git a/docs/agentic-tools/ai-sdk/getting-started.mdx b/docs/agentic-tools/ai-sdk/getting-started.mdx new file mode 100644 index 0000000..dc9c57f --- /dev/null +++ b/docs/agentic-tools/ai-sdk/getting-started.mdx @@ -0,0 +1,162 @@ +--- +title: "Getting Started" +sidebarTitle: "Getting Started" +description: "Add Context7 documentation tools to your Vercel AI SDK applications" +--- + +`@upstash/context7-tools-ai-sdk` provides [Vercel AI SDK](https://sdk.vercel.ai/) compatible tools and agents that give your AI applications access to up-to-date library documentation. + +When building AI-powered applications with the Vercel AI SDK, your models often need accurate information about libraries and frameworks. Instead of relying on potentially outdated training data, Context7 tools let your AI fetch current documentation on-demand, ensuring responses include correct API usage, current best practices, and working code examples. + +The package gives you two ways to integrate: + +1. **Individual tools** (`resolveLibraryId` and `queryDocs`) that you add to your existing `generateText` or `streamText` calls +2. **A pre-built agent** (`Context7Agent`) that handles the entire documentation lookup workflow automatically + +Both approaches work with any AI provider supported by the Vercel AI SDK, including OpenAI, Anthropic, Google, and others. + +## Installation + + +```bash npm +npm install @upstash/context7-tools-ai-sdk +``` + +```bash pnpm +pnpm add @upstash/context7-tools-ai-sdk +``` + +```bash yarn +yarn add @upstash/context7-tools-ai-sdk +``` + +```bash bun +bun add @upstash/context7-tools-ai-sdk +``` + + + +## Prerequisites + +You'll need: + +1. A Context7 API key from the [Context7 Dashboard](https://context7.com/dashboard) +2. An AI provider SDK (e.g., `@ai-sdk/openai`, `@ai-sdk/anthropic`) + +## Configuration + +Set your Context7 API key as an environment variable: + +```bash +CONTEXT7_API_KEY=ctx7sk-... +``` + +The tools and agents will automatically use this key. + +## Quick Start + +### Using Tools with generateText + +The simplest way to add documentation lookup to your AI application: + +```typescript +import { resolveLibraryId, queryDocs } from "@upstash/context7-tools-ai-sdk"; +import { generateText, stepCountIs } from "ai"; +import { openai } from "@ai-sdk/openai"; + +const { text } = await generateText({ + model: openai("gpt-5.2"), + prompt: "How do I create a server action in Next.js?", + tools: { + resolveLibraryId: resolveLibraryId(), + queryDocs: queryDocs(), + }, + stopWhen: stepCountIs(5), +}); + +console.log(text); +``` + +### Using the Context7 Agent + +For a more streamlined experience, use the pre-configured agent: + +```typescript +import { Context7Agent } from "@upstash/context7-tools-ai-sdk"; +import { anthropic } from "@ai-sdk/anthropic"; + +const agent = new Context7Agent({ + model: anthropic("claude-sonnet-4-20250514"), +}); + +const { text } = await agent.generate({ + prompt: "How do I use React Server Components?", +}); + +console.log(text); +``` + +### Using Tools with streamText + +For streaming responses: + +```typescript +import { resolveLibraryId, queryDocs } from "@upstash/context7-tools-ai-sdk"; +import { streamText, stepCountIs } from "ai"; +import { openai } from "@ai-sdk/openai"; + +const { textStream } = streamText({ + model: openai("gpt-5.2"), + prompt: "Explain how to use Tanstack Query for data fetching", + tools: { + resolveLibraryId: resolveLibraryId(), + queryDocs: queryDocs(), + }, + stopWhen: stepCountIs(5), +}); + +for await (const chunk of textStream) { + process.stdout.write(chunk); +} +``` + +## Explicit Configuration + +You can also pass the API key directly if needed: + +```typescript +import { resolveLibraryId, queryDocs } from "@upstash/context7-tools-ai-sdk"; + +const tools = { + resolveLibraryId: resolveLibraryId({ apiKey: "your-api-key" }), + queryDocs: queryDocs({ apiKey: "your-api-key" }), +}; +``` + +## How It Works + +The tools follow a two-step workflow: + +1. **`resolveLibraryId`** - Searches Context7's database to find the correct library ID for a given query (e.g., "react" → `/reactjs/react.dev`) + +2. **`queryDocs`** - Fetches documentation for the resolved library using the user's query to retrieve relevant content + +The AI model orchestrates these tools automatically based on the user's prompt, fetching relevant documentation before generating a response. + +## Next Steps + + + + Search for libraries and get Context7-compatible IDs + + + Fetch documentation for a specific library + + + Use the pre-built documentation agent + + diff --git a/docs/agentic-tools/ai-sdk/tools/query-docs.mdx b/docs/agentic-tools/ai-sdk/tools/query-docs.mdx new file mode 100644 index 0000000..046315e --- /dev/null +++ b/docs/agentic-tools/ai-sdk/tools/query-docs.mdx @@ -0,0 +1,196 @@ +--- +title: "queryDocs" +sidebarTitle: "queryDocs" +description: "Fetch up-to-date documentation for a specific library" +--- + +The `queryDocs` tool fetches documentation for a library using its Context7-compatible library ID and a query. This tool is typically called after `resolveLibraryId` has identified the correct library. + +## Usage + +```typescript +import { resolveLibraryId, queryDocs } from "@upstash/context7-tools-ai-sdk"; +import { generateText, stepCountIs } from "ai"; +import { openai } from "@ai-sdk/openai"; + +const { text } = await generateText({ + model: openai("gpt-5.2"), + prompt: "How do I use React Server Components?", + tools: { + resolveLibraryId: resolveLibraryId(), + queryDocs: queryDocs(), + }, + stopWhen: stepCountIs(5), +}); +``` + +## Configuration + +```typescript +queryDocs(config?: Context7ToolsConfig) +``` + +### Parameters + + + Configuration options for the tool. + + + + Context7 API key. If not provided, uses the `CONTEXT7_API_KEY` environment variable. + + + + +### Returns + +Returns an AI SDK `tool` that can be used with `generateText`, `streamText`, or agents. + +## Tool Behavior + +When the AI model calls this tool, it: + +1. Takes a library ID and query from the model +2. Fetches documentation from Context7's API +3. Returns the documentation content + +### Input Schema + +The tool accepts the following inputs from the AI model: + + + Context7-compatible library ID (e.g., `/reactjs/react.dev`, `/vercel/next.js`) + + + + The question or task you need help with, scoped to a single concept. Be specific and include relevant details, but keep each query to one topic — if the user's question spans multiple distinct concepts, make a separate call per concept instead of combining them, unless the question is about how the concepts interact. Good: "How to set up authentication with JWT in Express.js" or "React useEffect cleanup function examples". Bad (too vague): "auth" or "hooks". Bad (too broad): "routing and auth and caching in Next.js". + + +### Output Format + +On success, the tool returns the documentation as plain text, formatted for easy consumption by the AI model: + +``` +# Server Components + +Server Components let you write UI that can be rendered and optionally cached on the server. + +## Example + +\`\`\`tsx +async function ServerComponent() { + const data = await fetchData(); + return
{data}
; +} +\`\`\` + +--- + +# Using Server Components with Client Components + +You can import Server Components into Client Components... +``` + +#### On Failure + +``` +No documentation found for library "/invalid/library". This might have happened because you used an invalid Context7-compatible library ID. Use 'resolveLibraryId' to get a valid ID. +``` + +## Examples + +### Basic Usage with Both Tools + +```typescript +import { resolveLibraryId, queryDocs } from "@upstash/context7-tools-ai-sdk"; +import { generateText, stepCountIs } from "ai"; +import { openai } from "@ai-sdk/openai"; + +const { text } = await generateText({ + model: openai("gpt-5.2"), + prompt: "Show me how to set up routing in Next.js App Router", + tools: { + resolveLibraryId: resolveLibraryId(), + queryDocs: queryDocs(), + }, + stopWhen: stepCountIs(5), +}); + +// The model will: +// 1. Call resolveLibraryId to get the library ID +// 2. Call queryDocs({ libraryId: "/vercel/next.js", query: "routing in App Router" }) +// 3. Generate a response using the fetched documentation +``` + +### With Custom Configuration + +```typescript +import { queryDocs } from "@upstash/context7-tools-ai-sdk"; + +const tool = queryDocs({ + apiKey: process.env.CONTEXT7_API_KEY, +}); +``` + +### Direct Library ID (Skip resolveLibraryId) + +If the user provides a library ID directly, the model can skip the resolution step: + +```typescript +import { queryDocs } from "@upstash/context7-tools-ai-sdk"; +import { generateText, stepCountIs } from "ai"; +import { openai } from "@ai-sdk/openai"; + +const { text } = await generateText({ + model: openai("gpt-5.2"), + prompt: "Using /vercel/next.js, explain middleware", + tools: { + queryDocs: queryDocs(), + }, + stopWhen: stepCountIs(3), +}); + +// The model recognizes the /org/project format and calls queryDocs directly +``` + +### Multi-Step Documentation Lookup + +For comprehensive documentation, the model can make multiple queries: + +```typescript +import { resolveLibraryId, queryDocs } from "@upstash/context7-tools-ai-sdk"; +import { generateText, stepCountIs } from "ai"; +import { anthropic } from "@ai-sdk/anthropic"; + +const { text } = await generateText({ + model: anthropic("claude-sonnet-4-20250514"), + prompt: "Give me a comprehensive guide to Supabase authentication", + tools: { + resolveLibraryId: resolveLibraryId(), + queryDocs: queryDocs(), + }, + stopWhen: stepCountIs(8), // Allow more steps for multiple queries +}); + +// The model may call queryDocs multiple times with different queries +// to gather comprehensive documentation +``` + +## Version-Specific Documentation + +Library IDs can include version specifiers: + +```typescript +// Latest version +"/vercel/next.js"; + +// Specific version +"/vercel/next.js/v14.3.0-canary.87"; +``` + +The model can request documentation for specific versions when the user asks about a particular version. + +## Related + +- [resolveLibraryId](/agentic-tools/ai-sdk/tools/resolve-library-id) - Search for libraries and get their IDs +- [Context7Agent](/agentic-tools/ai-sdk/agents/context7-agent) - Pre-built agent that handles the full workflow diff --git a/docs/agentic-tools/ai-sdk/tools/resolve-library-id.mdx b/docs/agentic-tools/ai-sdk/tools/resolve-library-id.mdx new file mode 100644 index 0000000..6f3492f --- /dev/null +++ b/docs/agentic-tools/ai-sdk/tools/resolve-library-id.mdx @@ -0,0 +1,174 @@ +--- +title: "resolveLibraryId" +sidebarTitle: "resolveLibraryId" +description: "Search for libraries and resolve them to Context7-compatible IDs" +--- + +The `resolveLibraryId` tool searches Context7's library database and returns matching results with their Context7-compatible library IDs. This is typically the first step in a documentation lookup workflow. + +## Usage + +```typescript +import { resolveLibraryId } from "@upstash/context7-tools-ai-sdk"; +import { generateText, stepCountIs } from "ai"; +import { openai } from "@ai-sdk/openai"; + +const { text } = await generateText({ + model: openai("gpt-5.2"), + prompt: "Find documentation for React hooks", + tools: { + resolveLibraryId: resolveLibraryId(), + }, + stopWhen: stepCountIs(3), +}); +``` + +## Configuration + +```typescript +resolveLibraryId(config?: Context7ToolsConfig) +``` + +### Parameters + + + Configuration options for the tool. + + + + Context7 API key. If not provided, uses the `CONTEXT7_API_KEY` environment variable. + + + + +### Returns + +Returns an AI SDK `tool` that can be used with `generateText`, `streamText`, or agents. + +## Tool Behavior + +When the AI model calls this tool, it: + +1. Takes a `query` and `libraryName` parameter from the model +2. Searches Context7's database for matching libraries +3. Returns formatted results including: + - Library ID (e.g., `/reactjs/react.dev`) + - Title and description + - Number of code snippets available + - Source reputation score + - Available versions + +### Input Schema + +The tool accepts the following input from the AI model: + + + The user's original question or task. This is used to rank library results by relevance to what the user is trying to accomplish. + + + + Library name to search for (e.g., "react", "next.js", "vue") + + +### Output Format + +On success, the tool returns the search results as plain text, formatted for easy consumption by the AI model: + +``` +- Title: React Documentation +- Context7-compatible library ID: /reactjs/react.dev +- Description: The library for web and native user interfaces +- Code Snippets: 1250 +- Source Reputation: High +- Benchmark Score: 98 +- Versions: 19.0.0, 18.3.1, 18.2.0 +---------- +- Title: React Native +- Context7-compatible library ID: /facebook/react-native +- Description: A framework for building native applications using React +- Code Snippets: 890 +- Source Reputation: High +- Benchmark Score: 95 +- Versions: 0.76.0, 0.75.4 +``` + +On failure: + +``` +No libraries found matching "unknown-lib". Try a different search term or check the library name. +``` + +## Examples + +### Basic Usage + +```typescript +import { resolveLibraryId, queryDocs } from "@upstash/context7-tools-ai-sdk"; +import { generateText, stepCountIs } from "ai"; +import { openai } from "@ai-sdk/openai"; + +const { text, toolCalls } = await generateText({ + model: openai("gpt-5.2"), + prompt: "What libraries are available for React?", + tools: { + resolveLibraryId: resolveLibraryId(), + queryDocs: queryDocs(), + }, + stopWhen: stepCountIs(5), +}); + +// The model will call resolveLibraryId and receive a list of matching libraries +console.log(text); +``` + +### With Custom API Key + +```typescript +import { resolveLibraryId } from "@upstash/context7-tools-ai-sdk"; + +const tool = resolveLibraryId({ + apiKey: process.env.CONTEXT7_API_KEY, +}); +``` + +### Inspecting Tool Calls + +```typescript +import { resolveLibraryId } from "@upstash/context7-tools-ai-sdk"; +import { generateText, stepCountIs } from "ai"; +import { openai } from "@ai-sdk/openai"; + +const { toolCalls, toolResults } = await generateText({ + model: openai("gpt-5.2"), + prompt: "Find the official Next.js documentation", + tools: { + resolveLibraryId: resolveLibraryId(), + }, + stopWhen: stepCountIs(3), +}); + +// See what the model searched for +for (const call of toolCalls) { + console.log("Searched for:", call.input.libraryName); +} + +// See the results +for (const result of toolResults) { + console.log("Found:", result.output); +} +``` + +## Selection Guidance + +The tool's description instructs the AI model to select libraries based on: + +1. **Name similarity** - Exact matches are prioritized +2. **Description relevance** - How well the description matches the query intent +3. **Documentation coverage** - Libraries with more code snippets are preferred +4. **Source reputation** - High/Medium reputation sources are more authoritative +5. **Benchmark score** - Quality indicator (100 is the highest) + +## Related + +- [queryDocs](/agentic-tools/ai-sdk/tools/query-docs) - Fetch documentation using the resolved library ID +- [Context7Agent](/agentic-tools/ai-sdk/agents/context7-agent) - Pre-built agent that handles the full workflow diff --git a/docs/agentic-tools/overview.mdx b/docs/agentic-tools/overview.mdx new file mode 100644 index 0000000..3c8c662 --- /dev/null +++ b/docs/agentic-tools/overview.mdx @@ -0,0 +1,139 @@ +--- +title: "Overview" +sidebarTitle: "Overview" +description: "Build AI agents with up-to-date library documentation" +--- + +# Agentic Tools + +Context7 provides tools and integrations that give your AI agents access to accurate, up-to-date library documentation. Instead of relying on potentially outdated training data, your agents can fetch real-time documentation to answer questions and generate code. + +## Why Agentic Tools? + +AI agents often struggle with: + +- **Outdated knowledge** - Training data becomes stale, leading to deprecated API usage +- **Hallucinated APIs** - Models confidently suggest methods that don't exist +- **Version mismatches** - Code examples from old versions that no longer work + +Context7's agentic tools solve these problems by giving your agents direct access to current documentation during inference. + +## Available Integrations + + + + Add Context7 tools to your AI SDK workflows with `generateText`, `streamText`, or use the + pre-built `Context7Agent` for automatic documentation lookup. + + + Call Context7 directly from any TypeScript or Node.js app. + + + Connect Context7's MCP server to any agent or editor. + + + +## How It Works + +```mermaid +sequenceDiagram + participant User + participant Agent + participant Context7 + participant Docs + + User->>Agent: "How do I use React Server Components?" + Agent->>Context7: resolveLibraryId(query: "React Server Components", libraryName: "react") + Context7-->>Agent: Library ID: /reactjs/react.dev + Agent->>Context7: queryDocs(libraryId: "/reactjs/react.dev", query: "server components") + Context7->>Docs: Fetch latest documentation + Docs-->>Context7: Current docs with examples + Context7-->>Agent: Documentation content + Agent->>User: Answer with accurate, up-to-date code examples +``` + +## Use Cases + + + + Build chatbots that answer framework questions with accurate, version-specific information: + + ```typescript + import { generateText, stepCountIs } from "ai"; + import { openai } from "@ai-sdk/openai"; + import { resolveLibraryId, queryDocs } from "@upstash/context7-tools-ai-sdk"; + + const { text } = await generateText({ + model: openai("gpt-5.2"), + prompt: "How do I set up authentication in Next.js 15?", + tools: { + resolveLibraryId: resolveLibraryId(), + queryDocs: queryDocs(), + }, + stopWhen: stepCountIs(5), + }); + ``` + + + + + Ensure generated code uses current APIs and best practices: + + ```typescript + import { Context7Agent } from "@upstash/context7-tools-ai-sdk"; + import { anthropic } from "@ai-sdk/anthropic"; + + const agent = new Context7Agent({ + model: anthropic("claude-sonnet-4-20250514"), + }); + + const { text } = await agent.generate({ + prompt: "Generate a Supabase Edge Function that handles webhooks", + }); + ``` + + + + + Build code review agents that verify implementations against current API documentation: + + ```typescript + import { generateText, stepCountIs } from "ai"; + import { anthropic } from "@ai-sdk/anthropic"; + import { resolveLibraryId, queryDocs } from "@upstash/context7-tools-ai-sdk"; + + const codeToReview = ` + const { data } = await supabase + .from('users') + .select('*') + .eq('id', userId) + .single(); + `; + + const { text } = await generateText({ + model: anthropic("claude-sonnet-4-20250514"), + prompt: `Review this Supabase code for correctness and best practices: + + ${codeToReview} + + Check against the latest Supabase documentation.`, + tools: { + resolveLibraryId: resolveLibraryId(), + queryDocs: queryDocs(), + }, + stopWhen: stepCountIs(5), + }); + + // Agent fetches current Supabase docs to verify: + // - Correct method signatures + // - Deprecated patterns + // - Security best practices + // - Error handling recommendations + ``` + + + diff --git a/docs/api-guide.mdx b/docs/api-guide.mdx new file mode 100644 index 0000000..1be3de0 --- /dev/null +++ b/docs/api-guide.mdx @@ -0,0 +1,204 @@ +--- +title: API Guide +description: Authentication, rate limits, best practices, and integration guides for the Context7 API +--- + +## Authentication + +All API requests require authentication using an API key. Include your API key in the `Authorization` header: + +```bash +Authorization: Bearer CONTEXT7_API_KEY +``` + +Get your API key at [context7.com/dashboard](https://context7.com/dashboard). Learn more about [creating and managing API keys](/howto/api-keys). + + +## API Methods + +| Method | Endpoint | Description | +|--------|----------|-------------| +| [Search Library](/api-reference/search/search-for-libraries) | `GET /api/v2/libs/search` | Find libraries by name | +| [Get Context](/api-reference/context/get-documentation-context) | `GET /api/v2/context` | Retrieve documentation snippets for a library | +| [Refresh Library](/api-reference/refresh/refresh-a-library) | `POST /api/v1/refresh` | Refresh a library's documentation | +| [Get Policies](/api-reference/policies/get-teamspace-policies) | `GET /api/v2/policies` | Retrieve teamspace policy configuration | +| [Update Policies](/api-reference/policies/update-teamspace-policies) | `PATCH /api/v2/policies` | Update teamspace policies | +| [Add Library](/api-reference/add-library/add-a-github-repository) | `POST /api/v2/add/repo/{provider}` | Submit a repository for processing | +| [Add OpenAPI](/api-reference/add-library/add-an-openapi-specification-by-url) | `POST /api/v2/add/openapi` | Submit an OpenAPI spec | +| [Upload OpenAPI](/api-reference/add-library/upload-an-openapi-specification-file) | `POST /api/v2/add/openapi-upload` | Upload an OpenAPI spec file | +| [Add LLMs.txt](/api-reference/add-library/add-an-llmstxt-file) | `POST /api/v2/add/llmstxt` | Submit an llms.txt file | +| [Add Website](/api-reference/add-library/add-a-website) | `POST /api/v2/add/website` | Submit a website for crawling | +| [Add Confluence](/api-reference/add-library/add-a-confluence-space) | `POST /api/v2/add/confluence` | Submit a Confluence space | + +## Library ID format + +A **library ID** is the URL path of the library on context7.com. If the library page is at `https://context7.com/websites/uploadcare_com`, its ID is `/websites/uploadcare_com`. The same ID works for every endpoint that accepts a `libraryId` or `libraryName` — including [Get Context](/api-reference/context/get-documentation-context) and [Refresh Library](/api-reference/refresh/refresh-a-library). + +Use `/owner/repo` for GitHub repositories, or `//` for other sources: + +| Source | Example library ID | +|--------|--------------------| +| GitHub repository | `/vercel/next.js` | +| GitLab / Bitbucket / generic Git repo | `//` (same shape as GitHub) | +| Website | `/websites/uploadcare_com` | +| llms.txt source | `/llmstxt/` | +| npm / package source | `/packages/` or `/npm/` | +| Uploaded docs | `/docs/` | + +You can pin a specific version with either `/owner/repo/` or `/owner/repo@`: + +``` +/vercel/next.js/v15.1.8 +/vercel/next.js@v15.1.8 +``` + + + Don't know the ID for a library? Find it on [context7.com](https://context7.com) — the URL path of the library page **is** the ID. Or call [Search Library](/api-reference/search/search-for-libraries) and use the `id` from the response. + + +### Complete Workflow Example + +```python +import os +import requests + +headers = {"Authorization": f"Bearer {os.environ['CONTEXT7_API_KEY']}"} + +# Step 1: Search for the library +search_response = requests.get( + "https://context7.com/api/v2/libs/search", + headers=headers, + params={"libraryName": "react", "query": "I need to manage state"} +) +data = search_response.json() +best_match = data["results"][0] +print(f"Found: {best_match['title']} ({best_match['id']})") + +# Step 2: Get documentation context +context_response = requests.get( + "https://context7.com/api/v2/context", + headers=headers, + params={"libraryId": best_match["id"], "query": "How do I use useState?", "type": "json"} +) +docs = context_response.json() + +for snippet in docs["codeSnippets"]: + print(f"Title: {snippet['codeTitle']}") + for code in snippet["codeList"]: + print(f"Code: {code['code'][:200]}...") + +for info in docs["infoSnippets"]: + print(f"Content: {info['content'][:200]}...") +``` + + + For TypeScript SDK usage, see [Search Library](/sdks/ts/commands/search-library) and [Get Context](/sdks/ts/commands/get-context). + + +## Rate Limits + +- **Without API key**: Low rate limits and no custom configuration +- **With API key**: Higher limits based on your plan +- View current usage and reset windows in the [dashboard](https://context7.com/dashboard). + +When you exceed rate limits, the API returns a `429` status code with these headers: + +| Header | Description | +|--------|-------------| +| `Retry-After` | Seconds until rate limit resets | +| `RateLimit-Limit` | Total request limit | +| `RateLimit-Remaining` | Remaining requests in window | +| `RateLimit-Reset` | Unix timestamp when limit resets | + +## Best Practices + +### Be Specific with Queries + +Use detailed, natural language queries for better results: + +```bash +# Good - specific question +curl "https://context7.com/api/v2/context?libraryId=/vercel/next.js&query=How%20to%20implement%20authentication%20with%20middleware" \ + -H "Authorization: Bearer CONTEXT7_API_KEY" + +# Less optimal - vague query +curl "https://context7.com/api/v2/context?libraryId=/vercel/next.js&query=auth" \ + -H "Authorization: Bearer CONTEXT7_API_KEY" + +# Non-GitHub source (website) - same endpoint, same shape +curl "https://context7.com/api/v2/context?libraryId=/websites/uploadcare_com&query=image%20transformations" \ + -H "Authorization: Bearer CONTEXT7_API_KEY" +``` + +### Cache Responses + +Documentation updates are relatively infrequent, so caching responses for several hours or days reduces API calls and improves performance. + +### Handle Rate Limits + +Implement exponential backoff for rate limit errors: + +```python +import time +import requests + +def fetch_with_retry(url, headers, max_retries=3): + for attempt in range(max_retries): + response = requests.get(url, headers=headers) + + if response.status_code == 429: + retry_after = int(response.headers.get("Retry-After", 2 ** attempt)) + time.sleep(retry_after) + continue + + return response + + raise Exception("Max retries exceeded") +``` + +### Use Specific Versions + +Pin to a specific version for consistent results. Both `/` and `@` syntax are supported: + +```bash +curl "https://context7.com/api/v2/context?libraryId=/vercel/next.js/v15.1.8&query=app%20router" \ + -H "Authorization: Bearer CONTEXT7_API_KEY" + +curl "https://context7.com/api/v2/context?libraryId=/vercel/next.js@v15.1.8&query=app%20router" \ + -H "Authorization: Bearer CONTEXT7_API_KEY" +``` + +## Error Handling + +The Context7 API uses standard HTTP status codes: + +| Code | Description | Action | +| ---- | ----------------------------------------- | -------------------------------------------- | +| 200 | Success | Process the response normally | +| 202 | Accepted - Library not finalized | Wait and retry later | +| 301 | Moved - Library redirected | Use the new library ID from `redirectUrl` | +| 400 | Bad Request - Invalid parameters | Check query parameters | +| 401 | Unauthorized - Invalid API key | Check your API key format (starts with `ctx7sk`) | +| 403 | Forbidden - Access denied | Check library access permissions or plan | +| 404 | Not Found - Library doesn't exist | Verify the library ID | +| 409 | Conflict - Resource already exists | The library has already been added | +| 422 | Unprocessable - Library too large/no code | Try a different library | +| 429 | Too Many Requests - Rate limit exceeded | Wait for `Retry-After` header, then retry | +| 500 | Internal Server Error | Retry with backoff | +| 503 | Service Unavailable - Search failed | Retry later | +| 504 | Gateway Timeout - Processing timed out | Retry later | + +All errors return a JSON object with `error` and `message` fields: + +```json +{ + "error": "library_not_found", + "message": "Library \"/owner/repo\" not found. Please check the library ID or your access permissions." +} +``` + +For `301` redirects, the response also includes a `redirectUrl` field pointing to the new library ID. + +## SDK and Libraries + +For TypeScript SDK installation and usage, see the [Getting Started guide](/sdks/ts/getting-started). diff --git a/docs/clients/claude-code.mdx b/docs/clients/claude-code.mdx new file mode 100644 index 0000000..277b998 --- /dev/null +++ b/docs/clients/claude-code.mdx @@ -0,0 +1,178 @@ +--- +title: Claude Code +description: Using Context7 with Claude Code +--- + +Context7 integrates with Claude Code to provide current library documentation instead of relying on training data. Claude Code supports skills, agents, and commands that make documentation lookups more powerful. + +## Installation + +Run the setup command to configure Context7 for Claude Code: + +```bash +npx ctx7 setup --claude +``` + +This flow authenticates via OAuth, generates an API key, and installs the appropriate skill. You can choose between CLI or MCP mode. Login uses the OAuth device flow — it shows a verification link and short code you open on any device, so it works the same locally or on a remote, headless, or SSH host. + +Create or manage API keys in the [Context7 dashboard](https://context7.com/dashboard). For manual MCP installation or other configuration options, see [All MCP Clients](/resources/all-clients). + +--- + +## Using Context7 + +With `ctx7 setup`, a skill is installed that triggers automatically when you ask about libraries — no need to say "use context7". You can also invoke it explicitly: + +``` +use context7 to show me how to set up middleware in Next.js 15 +use context7 for Prisma query examples with relations +use context7 for the Supabase syntax for row-level security +``` + +If you know the library ID, use it directly to skip resolution: + +``` +use context7 with /supabase/supabase for authentication docs +use context7 with /vercel/next.js for app router setup +``` + + +With the [Context7 plugin](#the-context7-plugin) installed, you get additional agents and commands on top of the skill. + + +--- + +## The Context7 Plugin + +The full Context7 plugin for Claude Code includes more than just the MCP server: + + + +The tools for fetching documentation (`resolve-library-id`, `query-docs`) + + +Auto-triggers documentation lookups when you ask about libraries + + +A `docs-researcher` agent for focused lookups that keep context lean + + +`/context7:docs` for manual documentation queries + + + +### Installing the Plugin + +The plugin is available from the Context7 marketplace. Run these commands in Claude Code: + +``` +/plugin marketplace add upstash/context7 +/plugin install context7@context7-marketplace +``` + +This adds the Context7 marketplace and installs the plugin with skills, agents, and commands. + +### Using Your API Key with the Plugin + +Without an API key, the plugin connects anonymously and shares the anonymous rate limits. To use your own plan, create an API key in the [Context7 dashboard](https://context7.com/dashboard) and export it as an environment variable before launching Claude Code: + +```bash +# e.g. in ~/.zshrc or ~/.bashrc +export CONTEXT7_API_KEY="your-api-key" +``` + +The plugin reads `CONTEXT7_API_KEY` from your environment automatically. Restart Claude Code after setting it, then confirm requests are counted against your plan in the [dashboard](https://context7.com/dashboard). + + +If the variable is not set, the plugin still works — requests just go through the anonymous tier, which has lower rate limits. + + +### Skills + +#### Documentation Lookup Skill + +This skill triggers automatically when you ask about libraries, frameworks, or need code examples. You don't need to type "use context7" — the skill recognizes when documentation would help. + + + +- Setup questions: "How do I configure Next.js middleware?" +- Code generation: "Write a Prisma query for user relations" +- API references: "What are the Supabase auth methods?" +- Framework mentions: React, Vue, Svelte, Express, Tailwind, etc. + + +1. **Resolve**: Finds the library ID using `resolve-library-id` with your question as context +2. **Select**: Picks the best match based on name accuracy and quality scores +3. **Fetch**: Calls `query-docs` with the library ID and your specific question +4. **Return**: Provides code examples and explanations from current documentation + + + +### Agents + +#### docs-researcher Agent + +When you're in the middle of a long task and don't want documentation tool calls cluttering your context, spawn the `docs-researcher` agent. It runs in a separate context and returns just the answer. + + + +- You need docs but want to keep your main context clean +- You're working on something complex and context is getting long +- You want a focused answer without side effects + + +``` +spawn docs-researcher to look up React hooks documentation +spawn docs-researcher: how do I set up Prisma with PostgreSQL? +spawn docs-researcher to find Tailwind CSS grid utilities +``` + + + +The agent uses the same tools (`resolve-library-id` and `query-docs`) but runs on a lighter model (Sonnet) to keep things fast. + +#### When to Use Agents vs Inline Tools + +| Scenario | Use | +|----------|-----| +| Deep into a task with long context | Agent | +| Want to avoid context bloat | Agent | +| Context is short | Inline tools | +| Want docs visible in conversation | Inline tools | + +### Commands + +#### /context7:docs + +Manual command for documentation lookups. + +**Format:** +``` +/context7:docs [query] +``` + +**Examples:** + + + +``` +/context7:docs react hooks +/context7:docs next.js authentication +/context7:docs prisma relations +``` + + +``` +/context7:docs /vercel/next.js app router +/context7:docs /supabase/supabase row level security +``` + +Using a library ID directly skips the resolution step. + + + +**When to use:** +- You know exactly which library and topic you need +- You want a quick lookup without explaining your full context +- You're testing what documentation is available + diff --git a/docs/clients/cli.mdx b/docs/clients/cli.mdx new file mode 100644 index 0000000..6124f65 --- /dev/null +++ b/docs/clients/cli.mdx @@ -0,0 +1,251 @@ +--- +title: CLI +description: The ctx7 CLI — fetch library documentation and configure Context7 MCP from your terminal +--- + +The `ctx7` CLI is the command-line interface for Context7. It does two things: + +- **Fetch library documentation** — resolve any library by name and query its up-to-date docs directly in your terminal, without opening a browser +- **Configure your AI coding agent** — set up the Context7 MCP server (or a CLI-based `docs` skill) for Claude Code, Cursor, OpenCode, and more with a single command + +The CLI is useful both as a standalone tool (fetching docs while you code) and as a setup utility (wiring up Context7 for your AI coding agent). + +## Installation + +Requires Node.js 18 or later. + + + + Run ctx7 directly without installing anything. Useful for one-off commands or trying it out. + + ```bash + npx ctx7 --help + npx ctx7 library react + ``` + + + + Install globally for faster access — no `npx` prefix needed on every command. + + ```bash + npm install -g ctx7 + + # Verify installation + ctx7 --version + ``` + + + + +--- + +## Query Library Documentation + +Fetching docs is a two-step process: first resolve the library name to get its Context7 ID, then use that ID to query documentation. + +### Step 1 — ctx7 library + +Searches the Context7 index by name and returns matching libraries. Pass a `query` describing what you're trying to do — this ranks results by relevance and helps when a library name is ambiguous or shared across multiple packages. + +```bash +ctx7 library react "How to clean up useEffect with async operations" +ctx7 library nextjs "How to set up app router with middleware" +ctx7 library prisma "How to define one-to-many relations with cascade delete" +``` + +Each result includes: + +| Field | Description | +| --------------------- | -------------------------------------------------------------------------- | +| **Library ID** | The identifier to pass to `ctx7 docs` (format: `/org/project`) | +| **Code Snippets** | Number of indexed code examples — higher means more documentation coverage | +| **Source Reputation** | Authority indicator: High, Medium, Low, or Unknown | +| **Benchmark Score** | Quality score from 0 to 100 | +| **Versions** | Version-specific IDs when available (format: `/org/project/version`) | + +When multiple results come back, the best match is usually the one with the closest name, highest snippet count, and strongest reputation. If you need docs for a specific version, pick the matching version ID from the list. + +```bash +# Fetch docs for a specific version +ctx7 docs /vercel/next.js/v14.3.0-canary.87 "How to set up app router" + +# Output as JSON for scripting +ctx7 library react "How to use hooks for state management" --json | jq '.[0].id' +``` + +### Step 2 — ctx7 docs + +Takes a library ID and a natural-language question, and returns relevant code snippets and explanations from the indexed documentation. + +```bash +ctx7 docs /facebook/react "How to clean up useEffect with async operations" +ctx7 docs /vercel/next.js "How to add middleware that redirects unauthenticated users" +ctx7 docs /prisma/prisma "How to define one-to-many relations with cascade delete" +``` + + + Library IDs always start with `/`. Running `ctx7 docs react "hooks"` will fail — always use the + full ID returned by `ctx7 library` in Step 1. + + +Queries work best when they're specific. Describe what you're trying to accomplish rather than using single keywords — `"How to set up authentication with JWT in Express.js"` returns much better results than `"auth"`. + +The output contains two types of content: **code snippets** (titled, with language-tagged blocks) and **info snippets** (prose explanations with breadcrumb context). Both are formatted for readability in the terminal. + +```bash +# Output as structured JSON +ctx7 docs /facebook/react "How to use hooks for state management" --json + +# Pipe to other tools — output is clean when not in a TTY (no spinners or colors) +ctx7 docs /facebook/react "How to use hooks for state management" | head -50 +ctx7 docs /vercel/next.js "How to add middleware for route protection" | grep -A 10 "middleware" +``` + +--- + +## Setup + +Configure Context7 for your AI coding agent. On first run, prompts you to choose between two modes: + +- **MCP server** — registers the Context7 MCP server in your agent's config so it can call `resolve-library-id` and `query-docs` tools natively +- **CLI + Skills** — installs a `docs` skill that guides your agent to fetch up-to-date library docs using `ctx7` CLI commands (no MCP required) + +### ctx7 setup + +```bash +# Interactive — prompts for mode, then agent/install target +ctx7 setup + +# Skip the mode prompt +ctx7 setup --mcp # MCP server mode +ctx7 setup --cli # CLI + Skills mode + +# Target a specific agent (MCP mode) +ctx7 setup --claude +ctx7 setup --cursor +ctx7 setup --opencode + +# Target a specific install location (CLI + Skills mode) +ctx7 setup --cli --claude # Claude Code (~/.claude/skills) +ctx7 setup --cli --cursor # Cursor (~/.cursor/skills) +ctx7 setup --cli --universal # Universal (~/.agents/skills) +ctx7 setup --cli --antigravity # Antigravity (~/.agent/skills) + +# Configure for current project only (default is global) +ctx7 setup --project + +# Skip confirmation prompts +ctx7 setup --yes +``` + +**Authentication options:** + +```bash +# Use an existing API key (works for both MCP and CLI + Skills mode) +ctx7 setup --api-key YOUR_API_KEY + +# Use OAuth endpoint — MCP mode only (IDE handles the auth flow) +ctx7 setup --oauth +``` + +Without `--api-key` or `--oauth`, setup runs the OAuth device flow: it shows a verification link and short code that you open on any device to sign in, so it works the same locally or on a remote, headless, or SSH host. MCP mode additionally generates a new API key after login. `--oauth` is MCP-only — use it when an IDE handles the auth flow on your behalf. + +**What gets written — MCP mode:** + +| File | Purpose | +| --------------------------------------------------- | ---------------------------------------------------------------- | +| `.mcp.json` / `.cursor/mcp.json` / `.opencode.json` | MCP server entry | +| Agent rules directory | Rule file — instructs the agent to use Context7 for library docs | +| Agent skills directory | `context7-mcp` skill | + +**What gets written — CLI + Skills mode:** + +| File | Purpose | +| ---------------------- | ------------------------------------------------------------------------------ | +| Agent skills directory | `docs` skill — guides the agent to use `ctx7 library` and `ctx7 docs` commands | + +### ctx7 remove + +Remove the setup written by `ctx7 setup`. By default this removes both MCP setup and CLI setup for the selected agent. + +```bash +# Interactive +ctx7 remove + +# Target specific agents +ctx7 remove --cursor +ctx7 remove --claude --project + +# Remove both setup modes explicitly +ctx7 remove --cursor --all + +# Remove only one setup mode +ctx7 remove --cursor --cli +ctx7 remove --claude --mcp +``` + +If you installed the CLI itself with `npm install -g ctx7`, remove that separately with `npm uninstall -g ctx7`. If you run Context7 with `npx ctx7`, there is no permanent CLI install to remove. + +--- + +## Authentication + +Most commands work without authentication. Log in to unlock higher rate limits on documentation commands. + +### Commands + +```bash +# Log in (opens browser for OAuth) +ctx7 login + +# Log in without opening the browser (prints URL instead) +ctx7 login --no-browser + +# Check current login status +ctx7 whoami + +# Log out +ctx7 logout +``` + +### API Key + +Set an API key via environment variable to skip interactive login entirely — useful for CI or scripting: + +```bash +export CONTEXT7_API_KEY=your_key +``` + +### When is authentication required? + +| Feature | Required | +| -------------------------------------------------------- | ---------------------------------------------------------------------------- | +| `ctx7 library` / `ctx7 docs` | No — login gives higher rate limits | +| `ctx7 setup` | Yes — unless `--api-key` is passed (`--oauth` also skips login for MCP mode) | + +--- + +## Telemetry + +The CLI collects anonymous usage data to help improve the product. To disable: + +```bash +# For a single command +CTX7_TELEMETRY_DISABLED=1 ctx7 docs /facebook/react "useEffect examples" + +# Permanently — add to ~/.bashrc or ~/.zshrc +export CTX7_TELEMETRY_DISABLED=1 +``` + +--- + +## Next Steps + + + + Set up Context7 in Claude Code + + + Installation for every supported editor + + diff --git a/docs/clients/codex.mdx b/docs/clients/codex.mdx new file mode 100644 index 0000000..58383db --- /dev/null +++ b/docs/clients/codex.mdx @@ -0,0 +1,129 @@ +--- +title: Codex +description: Using Context7 with OpenAI Codex +--- + +Context7 integrates with [OpenAI Codex](https://developers.openai.com/codex/) to provide current library documentation instead of relying on training data. Codex comes in three surfaces — the Codex CLI, Codex Desktop, and Codex Cloud — and Context7 works across all of them. + + +MCP servers in Codex are configured once and shared everywhere. The Codex CLI, Codex Desktop, and the IDE extension all read the same `~/.codex/config.toml`, so adding Context7 in one place enables it in the others. See the [Codex MCP documentation](https://developers.openai.com/codex/mcp) for more details. + + +## Installation + +Run the setup command to configure Context7 for Codex: + +```bash +npx ctx7 setup --codex +``` + +This authenticates via OAuth, generates an API key, and writes the Context7 configuration to your `~/.codex/config.toml` and `AGENTS.md`. You can choose between CLI or MCP mode. Login uses the OAuth device flow, which shows a verification link and short code you open on any device, so it works locally, on SSH hosts, and in headless environments. + +You can also install Context7 as a Codex plugin. It connects to the hosted MCP server and includes a skill that looks up documentation when you ask about libraries: + +```bash +codex plugin marketplace add upstash/context7 +codex plugin add context7@context7-marketplace +``` + +After adding the plugin, a browser window opens so you can log in to Context7 via OAuth — plugin installs use your account's authenticated rate limits too. Start a new Codex thread after installation so Codex can load the plugin's skill and MCP tools. + +Create or manage API keys in the [Context7 dashboard](https://context7.com/dashboard). For manual configuration or other clients, see [All MCP Clients](/resources/all-clients). + +--- + +## Codex surfaces + + + +The local coding agent that runs in your terminal. Add Context7 with `codex mcp add` or by editing `config.toml`. + + +The Codex app for macOS and Windows. Enable Context7 from the app's MCP settings, or rely on the shared `config.toml`. + + +The web-based agent that runs tasks in cloud environments. Add Context7 to the tools for an environment from the Codex web app. + + + +### Codex CLI + +If you only want the MCP server, add Context7 from the terminal with the `codex mcp add` command: + +```bash +codex mcp add context7 -- npx -y @upstash/context7-mcp --api-key YOUR_API_KEY +``` + +Or add it directly to `~/.codex/config.toml` (use a project-scoped `.codex/config.toml` for trusted projects): + +```toml +[mcp_servers.context7] +command = "npx" +args = ["-y", "@upstash/context7-mcp", "--api-key", "YOUR_API_KEY"] +startup_timeout_ms = 20_000 +``` + +Prefer the hosted server? Use the remote connection instead: + +```toml +[mcp_servers.context7] +url = "https://mcp.context7.com/mcp" +http_headers = { "CONTEXT7_API_KEY" = "YOUR_API_KEY" } +``` + +### Codex Desktop + +The Codex app (macOS and Windows) shares the same MCP configuration as the CLI and IDE extension. Enable Context7 from the app's MCP settings, or add it to `~/.codex/config.toml` using the snippets above — it's picked up automatically. + +### Codex Cloud + +Codex Cloud delegates tasks to OpenAI's agent in managed cloud environments, so they can run in the background without your local machine. Each environment defines the repo, setup steps, and tools Codex uses — configure Context7 as part of an [environment](https://developers.openai.com/codex/cloud/environments) from the Codex web app. Cloud environments also have [configurable internet access](https://developers.openai.com/codex/cloud/internet-access), which Context7 needs to reach the documentation API. + +--- + +## Using Context7 + +With `ctx7 setup` or the plugin, a skill triggers automatically when you ask about libraries. You can also invoke it explicitly: + +``` +use context7 to show me how to set up middleware in Next.js 15 +use context7 for Prisma query examples with relations +use context7 for the Supabase syntax for row-level security +``` + +If you know the library ID, use it directly to skip resolution: + +``` +use context7 with /supabase/supabase for authentication docs +use context7 with /vercel/next.js for app router setup +``` + +You can also add instructions to your `AGENTS.md` file: + +```markdown AGENTS.md +When you need to search docs, use Context7. +``` + +--- + +## Tips + + + +- Be specific about what you're trying to do, not just which library +- Mention versions when they matter +- If the first result isn't right, ask for a different part of the docs + +``` +# Good +How do I handle file uploads with the Supabase Storage API? + +# Less specific +How does Supabase storage work? +``` + + + +If you see a startup "request timed out" or "not found program" error, increase `startup_timeout_ms` to `40_000` and retry. On Windows, point `command` at the absolute `npx.cmd` path and set `SystemRoot` and `APPDATA` explicitly — `npx` requires them, but some Codex MCP clients don't set them by default. + + diff --git a/docs/clients/copilot-cli.mdx b/docs/clients/copilot-cli.mdx new file mode 100644 index 0000000..e58c5bc --- /dev/null +++ b/docs/clients/copilot-cli.mdx @@ -0,0 +1,125 @@ +--- +title: GitHub Copilot CLI +description: Using Context7 with GitHub Copilot CLI +--- + +Context7 integrates with [GitHub Copilot CLI](https://docs.github.com/en/copilot/concepts/agents/about-copilot-cli) to provide current library documentation instead of relying on training data. The Context7 plugin ships the MCP server together with a skill, an agent, and a command, so documentation lookups work out of the box. + +## Installation + +Add the Context7 marketplace and install the plugin: + +```bash +copilot plugin marketplace add upstash/context7 +copilot plugin install context7@context7-marketplace +``` + +You can also run the same steps from an interactive session with `/plugin marketplace add upstash/context7` and `/plugin install context7@context7-marketplace`. + +For manual MCP configuration (for example, to add an API key for higher rate limits), see [All MCP Clients](/resources/all-clients). Create or manage API keys in the [Context7 dashboard](https://context7.com/dashboard). + +--- + +## What's Included + + + +The tools for fetching documentation (`resolve-library-id`, `query-docs`) + + +Auto-triggers documentation lookups when you ask about libraries + + +A `docs-researcher` agent for focused lookups that keep context lean + + +`/context7:docs` for manual documentation queries + + + +--- + +## Using Context7 + +The bundled skill triggers automatically when you ask about libraries — no need to say "use context7". You can also invoke it explicitly: + +``` +use context7 to show me how to set up middleware in Next.js 15 +use context7 for Prisma query examples with relations +use context7 for the Supabase syntax for row-level security +``` + +If you know the library ID, use it directly to skip resolution: + +``` +use context7 with /supabase/supabase for authentication docs +use context7 with /vercel/next.js for app router setup +``` + +### Skills + +The documentation lookup skill recognizes when documentation would help and fetches it automatically. + + + +- Setup questions: "How do I configure Next.js middleware?" +- Code generation: "Write a Prisma query for user relations" +- API references: "What are the Supabase auth methods?" +- Framework mentions: React, Vue, Svelte, Express, Tailwind, etc. + + +1. **Resolve**: Finds the library ID using `resolve-library-id` with your question as context +2. **Select**: Picks the best match based on name accuracy and quality scores +3. **Fetch**: Calls `query-docs` with the library ID and your specific question +4. **Return**: Provides code examples and explanations from current documentation + + + +### Agents + +When you're in the middle of a long task and don't want documentation tool calls cluttering your context, use the `docs-researcher` agent. It runs in a separate context and returns just the answer: + +```bash +copilot --agent docs-researcher -p "how do I set up Prisma with PostgreSQL?" +``` + +| Scenario | Use | +|----------|-----| +| Deep into a task with long context | Agent | +| Want to avoid context bloat | Agent | +| Context is short | Inline tools | +| Want docs visible in conversation | Inline tools | + +### Commands + +`/context7:docs` is a manual command for documentation lookups. + +**Format:** +``` +/context7:docs [query] +``` + +**Examples:** + + + +``` +/context7:docs react hooks +/context7:docs next.js authentication +/context7:docs prisma relations +``` + + +``` +/context7:docs /vercel/next.js app router +/context7:docs /supabase/supabase row level security +``` + +Using a library ID directly skips the resolution step. + + + +**When to use:** +- You know exactly which library and topic you need +- You want a quick lookup without explaining your full context +- You're testing what documentation is available diff --git a/docs/clients/cursor.mdx b/docs/clients/cursor.mdx new file mode 100644 index 0000000..e855fa4 --- /dev/null +++ b/docs/clients/cursor.mdx @@ -0,0 +1,125 @@ +--- +title: Cursor +description: Using Context7 with Cursor +--- + +Context7 brings up-to-date library documentation directly into Cursor. Instead of getting outdated code examples from training data, you get current documentation from source repositories. + +## Installation + +Run the setup command to configure Context7 for Cursor: + +```bash +npx ctx7 setup --cursor +``` + +Authenticates via OAuth, generates an API key, and installs the appropriate skill. You can choose between CLI or MCP mode. + +For manual MCP installation or other configuration options, see [All MCP Clients](/resources/all-clients). + +--- + +## Setting Up Rules + +With `ctx7 setup`, a skill is installed that triggers Context7 automatically. If you prefer to use a rule instead, add one in Cursor. + + + + + +Go to `Cursor` → `Settings...` → `Cursor Settings` → `Rules and Commands`. You can also press `Cmd+Shift+P` (or `Ctrl+Shift+P` on Windows/Linux) and type "Cursor Settings". + + + Cursor Rules and Commands + + + +``` +Always use Context7 MCP when I ask about library documentation, +API references, or need code examples from external packages. +``` + + + + +Create a `.cursorrules` file in your project root: + +``` +# Context7 Integration + +When the user asks about: +- Library APIs or documentation +- Framework setup or configuration +- Code examples for external packages +- How to use a specific library feature + +Automatically use Context7 MCP to fetch current documentation. Don't rely on training data for library-specific code. +``` + +This makes Context7 part of your project's standard workflow and can be version-controlled. + + + + +--- + +## Using Context7 + +Add "use context7" to your prompts to fetch current documentation: + +``` +use context7 to show me how to set up middleware in Next.js 15 +use context7 for Prisma query examples with relations +use context7 for the Supabase syntax for row-level security +``` + +If you know the library ID, use it directly to skip resolution: + +``` +use context7 with /supabase/supabase for authentication docs +use context7 with /vercel/next.js for app router setup +``` + +--- + +## Tips + + + +Use **global config** (`~/.cursor/mcp.json`) when: +- You want Context7 available in all projects +- You're using a personal API key + +Use **project config** (`.cursor/mcp.json`) when: + +- The project has specific Context7 requirements +- You want to share the setup with teammates +- Different projects need different API keys + + + +Context7 works well with Cursor's Composer feature. When you're building something that involves external libraries: + +1. Start with a prompt that mentions the libraries you need +2. Context7 fetches the relevant docs +3. Composer uses those docs to generate accurate code + +This is especially useful for newer library versions that might not be in Cursor's training data. + + + + +- Be specific about what you're trying to do, not just which library +- Mention versions when they matter +- If the first result isn't right, ask for a different part of the docs + +``` +# Good +How do I handle file uploads with the Supabase Storage API? + +# Less specific +How does Supabase storage work? +``` + + + diff --git a/docs/clients/opencode.mdx b/docs/clients/opencode.mdx new file mode 100644 index 0000000..d990776 --- /dev/null +++ b/docs/clients/opencode.mdx @@ -0,0 +1,76 @@ +--- +title: OpenCode +description: Using Context7 with OpenCode +--- + +Context7 integrates with [OpenCode](https://opencode.ai/) to provide current library documentation instead of relying on training data. Get accurate, up-to-date code examples directly in your coding sessions. + + +For more details on MCP server configuration in OpenCode, see the [OpenCode MCP documentation](https://opencode.ai/docs/mcp-servers/). + + +## Installation + +Run the setup command to configure Context7 for OpenCode: + +```bash +npx ctx7 setup --opencode +``` + +Authenticates via OAuth, generates an API key, and installs the appropriate skill. You can choose between CLI or MCP mode. + +For manual MCP installation or other configuration options, see [All MCP Clients](/resources/all-clients). + +--- + +## Using Context7 + +With `ctx7 setup`, a skill is installed that triggers automatically when you ask about libraries. You can also invoke it explicitly: + +``` +use context7 to show me how to set up middleware in Next.js 15 +use context7 for Prisma query examples with relations +use context7 for the Supabase syntax for row-level security +``` + +If you know the library ID, use it directly to skip resolution: + +``` +use context7 with /supabase/supabase for authentication docs +use context7 with /vercel/next.js for app router setup +``` + +You can also add instructions to your `AGENTS.md` file: + +```markdown AGENTS.md +When you need to search docs, use Context7. +``` + +--- + +## Tips + + + +- Be specific about what you're trying to do, not just which library +- Mention versions when they matter +- If the first result isn't right, ask for a different part of the docs + +``` +# Good +How do I handle file uploads with the Supabase Storage API? + +# Less specific +How does Supabase storage work? +``` + + + +You can place your `opencode.json` in your project directory to have project-specific configurations. This is useful when: + +- Different projects need different API keys +- You want to share the config with your team via version control +- A project requires specific Context7 settings + + + diff --git a/docs/clients/pi.mdx b/docs/clients/pi.mdx new file mode 100644 index 0000000..29198cd --- /dev/null +++ b/docs/clients/pi.mdx @@ -0,0 +1,90 @@ +--- +title: Pi +description: Using Context7 with the Pi coding agent +--- + +Context7 integrates with the [Pi coding agent](https://pi.dev) through the official [`@upstash/context7-pi`](https://github.com/upstash/context7/tree/master/packages/pi) extension. Instead of relying on training data, Pi gets current library documentation directly in your coding sessions. + +The extension is self-contained — it registers Context7's tools natively in Pi, so there's no separate MCP server to run. + +## Installation + +Install the extension with Pi's package command: + +```bash +pi install npm:@upstash/context7-pi +``` + +## Authentication + +The extension works out of the box at IP-based rate limits — useful for trying it out. For higher quotas and access to private repositories, generate a free key at the [Context7 dashboard](https://context7.com/dashboard) and export it: + +```bash +export CONTEXT7_API_KEY=ctx7sk_... +``` + +Set it in your shell profile so Pi picks it up on launch. + +--- + +## What it adds + + + +Converts a package or product name to a Context7 library ID (e.g. `Next.js` → `/vercel/next.js`). The agent calls this first. + + +Fetches documentation and code examples for a resolved library ID. + + +Teaches the agent to reach for these tools whenever you ask about a library, framework, SDK, API, CLI tool, or cloud service. + + +Runs the resolve + query flow in one shot for manual lookups. + + + +--- + +## Using Context7 + +Once installed, the skill triggers automatically when you ask about libraries — just ask a docs question and the tools are invoked for you: + +``` +how do I configure caching in Next.js 16? +use the Prisma syntax for relations +what are the Supabase auth methods? +``` + +For a manual lookup, use the slash command: + +``` +/c7-docs +``` + +For example: + +``` +/c7-docs next.js Cache Components +/c7-docs supabase row level security +``` + +--- + +## Tips + + + +- Be specific about what you're trying to do, not just which library +- Mention versions when they matter +- If the first result isn't right, ask for a different part of the docs + +``` +# Good +How do I handle file uploads with the Supabase Storage API? + +# Less specific +How does Supabase storage work? +``` + + diff --git a/docs/clients/vscode.mdx b/docs/clients/vscode.mdx new file mode 100644 index 0000000..387e7d6 --- /dev/null +++ b/docs/clients/vscode.mdx @@ -0,0 +1,76 @@ +--- +title: VS Code +description: Using Context7 with VS Code +--- + +The [Context7 VS Code extension](https://marketplace.visualstudio.com/items?itemName=Upstash.context7-mcp) registers the Context7 MCP server with VS Code's built-in MCP support, so AI features like Copilot Chat in agent mode get current library documentation instead of relying on training data. + +The extension connects to the hosted server at `https://mcp.context7.com/mcp`. There is no local server process to manage and nothing to update manually. The source is available at [upstash/context7-vscode-extension](https://github.com/upstash/context7-vscode-extension). + +## Installation + +Install **Context7 MCP Server** from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=Upstash.context7-mcp), or search for `Upstash.context7-mcp` in the Extensions view. + +Requires VS Code 1.101 or later. + +The server registers automatically when the extension activates. To confirm, run the **MCP: List Servers** command and check that "Context7" is listed. + +If you prefer to configure the MCP server yourself instead of using the extension, see [All MCP Clients](/resources/all-clients). + +--- + +## Adding an API Key + +An API key gives you higher rate limits and access to private repositories. Create one in the [Context7 dashboard](https://context7.com/dashboard). + + + +Press `Cmd+,` (or `Ctrl+,` on Windows/Linux) and search for "context7". + + +Paste your key into the **Context7: Api Key** field, or add it to `settings.json` directly: + +```json +{ + "context7.apiKey": "YOUR_API_KEY" +} +``` + + +Changing the key stops the running server so the new key can be picked up. Restart it via **MCP: List Servers** → **Context7** → **Start Server**, or just send a new chat request, which prompts to start it. No window reload required. + + + + +Keep the API key in your user settings rather than workspace settings if you commit `.vscode/settings.json` to version control. + + +--- + +## Using Context7 + +Add "use context7" to your prompts in Copilot Chat: + +``` +use context7 to show me how to set up middleware in Next.js 15 +use context7 for Prisma query examples with relations +use context7 for the Supabase syntax for row-level security +``` + +If you know the library ID, use it directly to skip resolution: + +``` +use context7 with /supabase/supabase for authentication docs +use context7 with /vercel/next.js for app router setup +``` + + +Add a rule to your AI assistant's instructions (e.g. `.github/copilot-instructions.md`) telling it to use Context7 for code generation and library questions, so you don't have to type "use context7" every time. + + +### Available Tools + +The extension exposes the two Context7 tools to VS Code: + +1. **`resolve-library-id`**: Resolves a package or product name to a Context7-compatible library ID +2. **`query-docs`**: Fetches up-to-date documentation for a library diff --git a/docs/contact.mdx b/docs/contact.mdx new file mode 100644 index 0000000..e9588ff --- /dev/null +++ b/docs/contact.mdx @@ -0,0 +1,4 @@ +--- +title: Contact +url: https://context7.com/contact +--- diff --git a/docs/docs.json b/docs/docs.json new file mode 100644 index 0000000..4656619 --- /dev/null +++ b/docs/docs.json @@ -0,0 +1,297 @@ +{ + "$schema": "https://mintlify.com/docs.json", + "theme": "mint", + "name": "Context7 MCP", + "description": "Up-to-date code docs for any prompt.", + "redirects": [ + { + "source": "/enterprise/azure-apim", + "destination": "/enterprise/enterprise-managed-auth/entra" + } + ], + "colors": { + "primary": "#10B981", + "light": "#ECFDF5", + "dark": "#064E3B" + }, + "contextual": { + "options": [ + "copy", + "view", + "chatgpt", + "claude" + ] + }, + "navigation": { + "groups": [ + { + "group": "Overview", + "pages": [ + "overview", + "installation", + "plans-pricing", + "clients/cli", + "adding-libraries", + "library-owners", + "library-updates", + "api-guide", + "tips" + ] + }, + { + "group": "How To", + "pages": [ + { + "group": "Authentication", + "pages": [ + "howto/api-keys", + "howto/oauth" + ] + }, + "howto/claiming-libraries", + "howto/chat-widget", + "howto/verification", + "howto/private-sources", + "howto/policies", + "howto/rules", + "howto/usage", + "howto/teamspace" + ] + }, + { + "group": "Enterprise", + "pages": [ + "enterprise", + { + "group": "Enterprise-Managed Auth", + "pages": [ + "enterprise/enterprise-managed-auth/entra", + "enterprise/enterprise-managed-auth/okta" + ] + }, + { + "group": "On-Premise", + "pages": [ + "enterprise/on-premise", + { + "group": "Integrations", + "pages": [ + "enterprise/integrations/github", + "enterprise/integrations/confluence" + ] + }, + { + "group": "Security", + "pages": [ + "enterprise/security/entra-sso", + "enterprise/security/oidc-sso" + ] + }, + { + "group": "Deployment", + "pages": [ + "enterprise/deployment/docker", + "enterprise/deployment/kubernetes" + ] + }, + { + "group": "Features", + "pages": [ + "enterprise/library-import", + "enterprise/gitops", + "enterprise/backup-restore" + ] + }, + { + "group": "API Reference", + "pages": [ + "enterprise/api/authentication", + { + "group": "Search", + "pages": ["enterprise/api/search/search-for-libraries"] + }, + { + "group": "Context", + "pages": ["enterprise/api/context/get-documentation-context"] + }, + { + "group": "Parse", + "pages": [ + "enterprise/api/parse/parse-a-git-repository", + "enterprise/api/parse/parse-an-openapi-spec-by-url", + "enterprise/api/parse/upload-an-openapi-spec-file", + "enterprise/api/parse/import-libraries", + "enterprise/api/parse/parse-a-website", + "enterprise/api/parse/refresh-a-library", + "enterprise/api/parse/get-parse-status" + ] + } + ] + } + ] + } + ] + }, + { + "group": "Security", + "pages": [ + "security/overview", + "security/data-privacy", + "security/infrastructure", + "security/auth-and-access-control", + "security/compliance-and-reporting", + "security/data-safety", + "security/best-practices" + ] + }, + { + "group": "Clients", + "pages": [ + "clients/claude-code", + "clients/codex", + "clients/copilot-cli", + "clients/cursor", + "clients/opencode", + "clients/pi", + "clients/vscode", + "resources/all-clients" + ] + }, + { + "group": "SDKs", + "pages": [ + { + "group": "TypeScript", + "pages": [ + "sdks/ts/getting-started", + { + "group": "Commands", + "pages": [ + "sdks/ts/commands/search-library", + "sdks/ts/commands/get-context" + ] + } + ] + } + ] + }, + { + "group": "Agentic Tools", + "pages": [ + "agentic-tools/overview", + { + "group": "Vercel AI SDK", + "pages": [ + "agentic-tools/ai-sdk/getting-started", + { + "group": "Tools", + "pages": [ + "agentic-tools/ai-sdk/tools/resolve-library-id", + "agentic-tools/ai-sdk/tools/query-docs" + ] + }, + { + "group": "Agents", + "pages": [ + "agentic-tools/ai-sdk/agents/context7-agent" + ] + } + ] + } + ] + }, + { + "group": "API Reference", + "openapi": "openapi.json" + }, + { + "group": "Integrations", + "pages": [ + "integrations/github-actions", + "integrations/code-rabbit", + "integrations/factory-ai", + "integrations/tembo", + "integrations/mastra" + ] + }, + { + "group": "Resources", + "pages": [ + "resources/developer", + "resources/troubleshooting" + ] + } + ] + }, + "api": { + "playground": { + "display": "simple" + } + }, + "logo": { + "light": "/public/logo/logo.svg", + "dark": "/public/logo/logo-dark.svg", + "href": "https://context7.com" + }, + "favicon": "/public/favicon.ico", + "navbar": { + "links": [ + { + "label": "Contact", + "href": "https://context7.com/contact" + }, + { + "label": "GitHub", + "href": "https://github.com/upstash/context7" + } + ], + "primary": { + "type": "button", + "label": "Dashboard", + "href": "https://context7.com" + } + }, + "footer": { + "socials": { + "x": "https://x.com/context7ai", + "github": "https://github.com/upstash/context7", + "discord": "https://upstash.com/discord" + }, + "links": [ + { + "header": "Resources", + "items": [ + { + "label": "Website", + "href": "https://context7.com" + }, + { + "label": "Submit a Library", + "href": "https://context7.com/add-library" + }, + { + "label": "Dashboard", + "href": "https://context7.com/dashboard" + } + ] + }, + { + "header": "Community", + "items": [ + { + "label": "GitHub", + "href": "https://github.com/upstash/context7" + }, + { + "label": "Discord", + "href": "https://upstash.com/discord" + }, + { + "label": "Twitter", + "href": "https://x.com/context7ai" + } + ] + } + ] + } +} diff --git a/docs/enterprise.mdx b/docs/enterprise.mdx new file mode 100644 index 0000000..5ebde6f --- /dev/null +++ b/docs/enterprise.mdx @@ -0,0 +1,96 @@ +--- +title: Enterprise +sidebarTitle: Overview +description: Turn your internal documentation into LLM-ready context for developers, coding agents, and engineering leaders +--- + +Context7 Enterprise converts your internal documentation into structured, high-quality context optimized for LLMs — enabling human developers, coding agents, and engineering leaders to build faster and operate with clarity. + +## Core Use Cases + +### Assist Human Developers + +Cut onboarding time and reduce internal support load. + +- Faster onboarding and fewer interruptions +- Immediate API/service reference inside IDEs +- Always-up-to-date documentation context +- Reduced Slack/Teams dependency + +### Power Coding Agents With Correct Documentation + +Let your agents write correct code on the first try. + +- Supply agents with accurate repo + docs context +- Reduce hallucinations and incorrect API calls +- Enable autonomous generation, refactoring, and analysis +- Feed structured context into LangGraph/agent frameworks + +### Engineering Management & Knowledge Governance + +One source of truth. Zero stale docs. + +- Enforce documentation and context rules across projects +- Automatically parse APIs, RST/Sphinx, MDX, OpenAPI +- Detect outdated or inconsistent sections +- Maintain a single source of truth across engineering + +## Enterprise Features + +- **SOC 2 certified** cloud infrastructure +- **SSO** (SAML, OAuth, OIDC) +- Unlimited seats and teamspaces +- Custom volume expansions and high-usage plans +- Private GitHub / GitLab / Bitbucket repository ingestion +- Professional support with response time SLA +- On-premise deployment options available + +## Security & Compliance + +Context7 runs on **SOC 2 Type II** compliant infrastructure provided by [Upstash](https://upstash.com). Key security highlights include: + +- **Privacy-first architecture** — your original prompts and code never leave your AI assistant. Only MCP-formulated search queries reach the Context7 API, and sensitive data is stripped before transmission. +- **Encryption** at rest and in transit (TLS 1.2+) +- **VPC isolation**, RBAC, DDoS protection, and 24/7 monitoring +- **API key security** — cryptographically generated, hashed, encrypted, and rate-limited +- **Enterprise SSO** — supports SAML 2.0, OAuth 2.0, and OpenID Connect (OIDC) +- **GDPR compliant** with data access, deletion, and portability rights +- Data stored in the US and EU with cross-border transfers following GDPR and EU-U.S. Data Privacy Framework +- **ISO 27001** certification in progress +- Open-source MCP server — publicly auditable at [github.com/upstash/context7](https://github.com/upstash/context7) + +Enterprise customers can also disable query storage, use their own LLM provider for code extraction and private library ranking, and limit context retrieval to privately indexed documentation only. + +For full details, see the [Security](/security/overview) page and the [Upstash Trust Center](https://trust.upstash.com/). + +## Quality & Safety + +Context7 is built with retrieval quality and trust at its core: + +- **Benchmark-driven retrieval** — a library benchmark system generates developer-style questions and measures how effectively each library answers them. Scores are publicly visible and help prioritize better-performing libraries during retrieval. +- **Trust scores** — every library receives a trust score based on repository signals (stars, activity, account age) and website signals (TLS, domain authority, backlinks). This ensures reliable, well-established libraries are surfaced first. +- **Deduplication** — exact match checking and cosine similarity filtering remove redundant code snippets and overlapping documentation content. +- **Version-aware parsing** — a version analyzer detects multi-version documentation structures, ensuring only current docs are stored by default while older versions remain accessible. +- **Prompt injection protection** — a two-pass detection pipeline combining complementary stages blocks malicious documentation content while minimizing false positives. Pipelines are regularly updated to address evolving attack methods. +- **Minimal data ingestion** — Context7 does not ingest user code, conversation history, or other sensitive data. + +For more details, see the [Quality and Safety in Context7](https://upstash.com/blog/context7-quality-and-safety) blog post. + +## Pricing + +For pricing details and custom plans, [contact us](mailto:context7@upstash.com). + +## About Upstash + +Context7 is built by [Upstash](https://upstash.com), a serverless data platform powering 80,000+ active databases worldwide. Upstash delivers managed Redis, Vector, Queue, and Search services — processing 850+ billion requests per month with 99.99%+ uptime. Backed by Andreessen Horowitz (a16z) and headquartered in California, Upstash brings deep distributed systems expertise. Context7 follows the same engineering, reliability, and security standards. + +## Contact + + + + context7@upstash.com + + + context7.com + + diff --git a/docs/enterprise/api/authentication.mdx b/docs/enterprise/api/authentication.mdx new file mode 100644 index 0000000..4a5c873 --- /dev/null +++ b/docs/enterprise/api/authentication.mdx @@ -0,0 +1,64 @@ +--- +title: "Authentication" +description: "How to authenticate requests to your on-premise Context7 instance" +--- + +The on-premise API supports API keys for server-to-server and MCP access. Pass the key in the `Authorization` header: + +```bash +Authorization: Bearer ctx7op-xxxxxxxx_xxxxxxxxxxxxxxxx +``` + +Keys are scoped to the user account that created them and inherit that user's role (`admin` or `member`). There are no per-key scopes or expiry - revoke a key to invalidate it. + +## Creating an API Key + + + + Go to **Personal Settings > API Keys** in the admin dashboard and click **Create API Key**. + + + ![API Keys settings page](/images/enterprise/api-keys/api-keys-empty.png) + + + + Give the key a descriptive name so you know which client or service is using it (e.g. `CI pipeline`, `Cursor`). + + + ![Create API Key dialog](/images/enterprise/api-keys/api-keys-create-dialog.png) + + + + Copy the full key value before closing the dialog. It is only shown once. + + + ![API Key Created dialog showing the key value](/images/enterprise/api-keys/api-keys-created.png) + + + + +API keys are shown only once at creation. Store yours securely before closing the dialog. + +## Revoking a Key + +Go to **Settings > API Keys** and click the delete icon next to the key. Revocation is immediate and cannot be undone. Update any integrations using the key before revoking. + +## Roles + +| Role | Access | +|---|---| +| `admin` | Full access to all endpoints including settings, user management, and delete operations | +| `member` | Can trigger parsing and search. Cannot access admin endpoints | + +Default credentials on a fresh install are `admin` / `admin`. Change them immediately from **Settings > Change Credentials**. + +## Anonymous Access + +Certain operations can be allowed without authentication. Configure them from **Settings > Permissions**: + +| Permission | Default | +|---|---| +| Anonymous parse / refresh | Off | +| Anonymous delete | Off | + +The search (`GET /v2/libs/search`) and context (`GET /v2/context`) endpoints are always publicly accessible unless a global `API_KEY` environment variable is set, in which case every endpoint requires a bearer token. diff --git a/docs/enterprise/api/context/get-documentation-context.mdx b/docs/enterprise/api/context/get-documentation-context.mdx new file mode 100644 index 0000000..dd5c56a --- /dev/null +++ b/docs/enterprise/api/context/get-documentation-context.mdx @@ -0,0 +1,5 @@ +--- +title: "Get documentation context" +description: "Retrieve documentation snippets for a library ranked by relevance to your query" +openapi: "openapi-enterprise.json GET /v2/context" +--- diff --git a/docs/enterprise/api/parse/get-parse-status.mdx b/docs/enterprise/api/parse/get-parse-status.mdx new file mode 100644 index 0000000..f77affd --- /dev/null +++ b/docs/enterprise/api/parse/get-parse-status.mdx @@ -0,0 +1,5 @@ +--- +title: "Get parse status" +description: "Returns the status of all active and queued parse jobs" +openapi: "openapi-enterprise.json GET /parse-status" +--- diff --git a/docs/enterprise/api/parse/import-libraries.mdx b/docs/enterprise/api/parse/import-libraries.mdx new file mode 100644 index 0000000..c51bbe9 --- /dev/null +++ b/docs/enterprise/api/parse/import-libraries.mdx @@ -0,0 +1,5 @@ +--- +title: "Import a library bundle" +description: "Import pre-parsed libraries into an airgapped on-premise install, as a JSON body or a Context7 Cloud export file" +openapi: "openapi-enterprise.json POST /import-libraries" +--- diff --git a/docs/enterprise/api/parse/parse-a-git-repository.mdx b/docs/enterprise/api/parse/parse-a-git-repository.mdx new file mode 100644 index 0000000..962258f --- /dev/null +++ b/docs/enterprise/api/parse/parse-a-git-repository.mdx @@ -0,0 +1,5 @@ +--- +title: "Parse a Git repository" +description: "Queue a GitHub or GitLab repository for parsing and indexing" +openapi: "openapi-enterprise.json POST /parse" +--- diff --git a/docs/enterprise/api/parse/parse-a-website.mdx b/docs/enterprise/api/parse/parse-a-website.mdx new file mode 100644 index 0000000..200f9f3 --- /dev/null +++ b/docs/enterprise/api/parse/parse-a-website.mdx @@ -0,0 +1,5 @@ +--- +title: "Parse a website" +description: "Crawl and index a public website starting from the given URL" +openapi: "openapi-enterprise.json POST /parse-website" +--- diff --git a/docs/enterprise/api/parse/parse-an-openapi-spec-by-url.mdx b/docs/enterprise/api/parse/parse-an-openapi-spec-by-url.mdx new file mode 100644 index 0000000..1eb0a3f --- /dev/null +++ b/docs/enterprise/api/parse/parse-an-openapi-spec-by-url.mdx @@ -0,0 +1,5 @@ +--- +title: "Parse an OpenAPI spec by URL" +description: "Queue a remote OpenAPI specification (JSON or YAML) for parsing and indexing" +openapi: "openapi-enterprise.json POST /parse-openapi" +--- diff --git a/docs/enterprise/api/parse/refresh-a-library.mdx b/docs/enterprise/api/parse/refresh-a-library.mdx new file mode 100644 index 0000000..ac79d2f --- /dev/null +++ b/docs/enterprise/api/parse/refresh-a-library.mdx @@ -0,0 +1,5 @@ +--- +title: "Refresh a library" +description: "Re-parse an existing library using its stored settings" +openapi: "openapi-enterprise.json POST /projects/{projectId}/refresh" +--- diff --git a/docs/enterprise/api/parse/upload-an-openapi-spec-file.mdx b/docs/enterprise/api/parse/upload-an-openapi-spec-file.mdx new file mode 100644 index 0000000..a4c7efe --- /dev/null +++ b/docs/enterprise/api/parse/upload-an-openapi-spec-file.mdx @@ -0,0 +1,5 @@ +--- +title: "Upload an OpenAPI spec file" +description: "Upload an OpenAPI specification file directly for parsing and indexing" +openapi: "openapi-enterprise.json POST /parse-openapi-upload" +--- diff --git a/docs/enterprise/api/search/search-for-libraries.mdx b/docs/enterprise/api/search/search-for-libraries.mdx new file mode 100644 index 0000000..daffa00 --- /dev/null +++ b/docs/enterprise/api/search/search-for-libraries.mdx @@ -0,0 +1,5 @@ +--- +title: "Search for libraries" +description: "Search locally indexed libraries by name" +openapi: "openapi-enterprise.json GET /v2/libs/search" +--- diff --git a/docs/enterprise/backup-restore.mdx b/docs/enterprise/backup-restore.mdx new file mode 100644 index 0000000..883fbd9 --- /dev/null +++ b/docs/enterprise/backup-restore.mdx @@ -0,0 +1,151 @@ +--- +title: "Backup and Restore" +sidebarTitle: "Backup & Restore" +--- + +Context7 On-Premise can back up all of its data into a single archive, on a schedule or on demand. A backup contains everything needed to rebuild your deployment on a fresh machine: the SQLite database (configuration, credentials, indexed libraries), the vector index, and the encryption key that protects stored secrets. + +Backups run safely while the server is serving traffic. The database snapshot uses SQLite's online backup API, so you don't need a maintenance window. + + +Backup archives include the database and the encryption key, which means anyone holding an archive can read your stored credentials (LLM API keys, Git tokens). Store backups with the same care as the data volume itself. For S3, use a private bucket with server-side encryption. + + +## Configuring Backups + +Open **Settings → Backup** in the dashboard. Choose a destination, set a schedule, and save. + +### Local or Network Path + +Writes archives to a directory on the server's filesystem. Use this for air-gapped deployments or when you back up to an NFS mount. + +When running in Docker, mount a dedicated volume for backups so they survive independently of the data volume: + +```yaml +services: + context7: + # ... + volumes: + - context7-data:/data + - context7-backups:/backups + +volumes: + context7-data: + context7-backups: +``` + +Then set the backup directory to `/backups` in the dashboard. + +### S3 + +Works with AWS S3 and any S3-compatible store such as MinIO or Ceph. + +| Field | Description | +| ----- | ----------- | +| Bucket | Bucket name (required) | +| Region | Bucket region, defaults to `us-east-1` | +| Access Key ID / Secret | Static credentials. Leave blank to use the AWS default credential chain (IAM role, environment variables) | +| Endpoint | Custom endpoint for S3-compatible storage. Leave blank for AWS | +| Path-style addressing | Enable for most MinIO setups | +| Key prefix | Optional prefix inside the bucket, e.g. `context7/` | + +The secret key is stored encrypted in the local database. + +### Schedule and Retention + +Pick a preset (daily, every 6 hours, weekly) or enter a custom cron expression. Retention keeps the newest N archives and prunes older ones automatically; choose **Keep all** to retain everything. + +If an indexing job is running when a scheduled backup fires, the backup still completes, but that one library may be only partially indexed. Schedule backups for quiet hours, or simply re-index that library after a restore. + +## Running a Backup Manually + +Click **Back up now** in the dashboard, or call the API: + +```bash +curl -X POST http://localhost:3000/api/backup \ + -H "Cookie: " +``` + +All backup endpoints require an admin session and keep working even if your license has expired, so you can always get your data out. + +| Endpoint | Description | +| -------- | ----------- | +| `POST /api/backup` | Start a backup in the background | +| `GET /api/backup/status` | Whether a backup is running, plus the last result | +| `GET /api/backups` | List available archives | +| `GET /api/backups//download` | Download an archive (local destination only) | +| `GET /api/backup/config` / `PUT` | Read or update the backup configuration | + +## Restoring + +Restore a backup from the dashboard (for local backups) or with the offline CLI (for S3 backups, scripted recovery, or a fresh machine). + +In every case the restore never deletes your current data. It moves the existing database, vector index, and encryption key into a `pre-restore-` directory inside the data volume, so you can roll back. Delete that directory once you've verified the restore. + + +A backup created by a newer Context7 version cannot be restored into an older installation; the restore tool will refuse and tell you to upgrade first. Backups from older versions restore fine, and the database is migrated automatically the next time the server starts. + + +### From the dashboard + +Open **Settings → Backup**, find the backup in the list, and click the restore icon. Context7 validates the archive, shows what it contains (created date, libraries, schema version), and asks you to confirm. It then stages the restore and restarts to apply it, because the live database and vector index cannot be swapped while the server is running. Under Docker or Kubernetes the server comes back automatically; otherwise start it again after it stops. + +### Offline with the CLI + +Run the CLI with the server stopped. For S3 backups, download the archive to the machine first. + +#### Docker + +```bash +# 1. Stop the server +docker compose stop context7 + +# 2. Run the restore against the same volumes +docker compose run --rm --no-deps context7 \ + node dist/enterprise/restore.mjs /backups/context7-backup-2026-06-12T02-00-00.tar.gz --yes + +# 3. Start the server again +docker compose start context7 +``` + +If the archive is not already inside a mounted volume (for example, you downloaded it from S3), copy it in first: + +```bash +docker compose cp ./context7-backup-2026-06-12T02-00-00.tar.gz context7:/data/ +``` + +#### Kubernetes + +Scale the StatefulSet down, run the restore in a one-off pod that mounts the same PVC, then scale back up: + +```bash +kubectl -n context7 scale statefulset context7 --replicas=0 + +kubectl -n context7 run context7-restore --rm -it --restart=Never \ + --image=ghcr.io/context7/enterprise:latest \ + --overrides='{"spec":{"imagePullSecrets":[{"name":"context7-registry"}],"containers":[{"name":"context7-restore","image":"ghcr.io/context7/enterprise:latest","command":["node","dist/enterprise/restore.mjs","/data/context7-backup-2026-06-12T02-00-00.tar.gz","--yes"],"volumeMounts":[{"name":"data","mountPath":"/data"}]}],"volumes":[{"name":"data","persistentVolumeClaim":{"claimName":"data-context7-0"}}]}}' + +kubectl -n context7 scale statefulset context7 --replicas=1 +``` + +Use `kubectl cp` to place the archive on the volume first if it isn't there already. + +#### Running locally + +If you run Context7 without Docker: + +```bash +npm run ctx7:restore -- /path/to/context7-backup-2026-06-12T02-00-00.tar.gz +``` + +The command prompts for confirmation before replacing anything. Pass `--yes` to skip the prompt in scripts. + +## Disaster Recovery Checklist + +1. Deploy a fresh Context7 instance on the new machine (same or newer version). +2. Don't run the setup wizard. Stop the server instead. +3. Copy your latest backup archive onto the machine. +4. Run the restore as shown above. +5. Start the server. Your configuration, credentials, users, indexed libraries, and search index are all back. + +Because the encryption key travels inside the archive, restored credentials work immediately on the new machine. Nothing needs to be re-entered. diff --git a/docs/enterprise/deployment/docker.mdx b/docs/enterprise/deployment/docker.mdx new file mode 100644 index 0000000..376dcc5 --- /dev/null +++ b/docs/enterprise/deployment/docker.mdx @@ -0,0 +1,131 @@ +--- +title: "Docker Deployment" +sidebarTitle: "Docker" +description: "Deploy Context7 On-Premise with Docker Compose" +--- + +Deploy Context7 On-Premise with Docker Compose. This guide assumes you have completed the [On-Premise setup](/enterprise/on-premise) and have a valid license key. + +## Prerequisites + +- Docker and Docker Compose installed +- Context7 license key + +## Registry Authentication + +Context7 Enterprise images are hosted on `ghcr.io` and require authentication. Log in using your license key: + +```bash +LICENSE_KEY="" + +TOKEN=$(curl -s -H "Authorization: Bearer $LICENSE_KEY" \ + https://context7.com/api/v1/license/registry-token | jq -r '.token') + +docker login ghcr.io -u x-access-token -p $TOKEN +``` + +Docker stores these credentials locally. `docker compose` will use them automatically when pulling the image. You can also pull manually: + +```bash +docker pull ghcr.io/context7/enterprise:latest +``` + +## Docker Compose + +Create a `docker-compose.yml`: + +```yaml +services: + context7: + image: ghcr.io/context7/enterprise:latest + container_name: context7 + restart: unless-stopped + ports: + - "3000:3000" + volumes: + - context7-data:/data + environment: + - LICENSE_KEY=${LICENSE_KEY} + +volumes: + context7-data: + driver: local +``` + + +The `context7-data` volume is critical. It stores your SQLite database (configuration, credentials, indexed libraries) and all vector embeddings. Without a persistent volume, all data is lost when the container restarts or is recreated. Never run without a volume mount in production. + + +Create a `.env` file in the same directory: + +```bash +LICENSE_KEY=ctx7sk-... +``` + +Start the service: + +```bash +docker compose up -d +``` + +Once the container is running, open `http://localhost:3000` in your browser to complete the setup wizard. + +## Operations + +### Updating + +If your registry login has expired, re-authenticate first: + +```bash +LICENSE_KEY="" + +TOKEN=$(curl -s -H "Authorization: Bearer $LICENSE_KEY" \ + https://context7.com/api/v1/license/registry-token | jq -r '.token') + +docker login ghcr.io -u x-access-token -p $TOKEN +``` + +Then pull the latest image and restart the container: + +```bash +docker compose pull +docker compose up -d +``` + +Data persists in the named Docker volume across updates. + +### Health Check + +```bash +curl http://localhost:3000/api/health +``` + +Example response: + +```json +{ + "status": "healthy", + "version": "1.0.0", + "setup": "complete", + "license": "configured", + "licenseInfo": { + "valid": true, + "teamSize": 10, + "expiresAt": "2026-06-01T00:00:00.000Z" + }, + "repos_parsed": 5, + "uptime": 3600, + "connectivity": { + "llm": "configured", + "llm_provider": "openai", + "embedding": "configured", + "embedding_provider": "openai", + "github": "configured", + "gitlab": "not configured" + } +} +``` + +## Connecting AI Clients + +Once deployed, point your MCP clients to your deployment URL. See [Connecting Your AI Client](/enterprise/on-premise#connecting-your-ai-client) for client-specific instructions. diff --git a/docs/enterprise/deployment/kubernetes.mdx b/docs/enterprise/deployment/kubernetes.mdx new file mode 100644 index 0000000..4643dc7 --- /dev/null +++ b/docs/enterprise/deployment/kubernetes.mdx @@ -0,0 +1,341 @@ +--- +title: "Kubernetes Deployment" +sidebarTitle: "Kubernetes" +description: "Deploy Context7 On-Premise on Kubernetes using raw manifests" +--- + +Deploy Context7 On-Premise on Kubernetes using raw manifests. This guide assumes you have completed the [On-Premise setup](/enterprise/on-premise) and have a valid license key. + +## Prerequisites + +- Kubernetes cluster (v1.24+) +- `kubectl` configured for your cluster +- A StorageClass that supports `ReadWriteOnce` volumes +- Context7 license key + +## Registry Authentication + +Context7 Enterprise images are hosted on `ghcr.io` and require authentication. Create an image pull secret using your license key: + +```bash +LICENSE_KEY="" + +# Get a registry token from Context7 +TOKEN=$(curl -s -H "Authorization: Bearer $LICENSE_KEY" \ + https://context7.com/api/v1/license/registry-token | jq -r '.token') + +# Create the namespace and secrets +kubectl create namespace context7 + +kubectl create secret docker-registry context7-registry \ + --namespace context7 \ + --docker-server=ghcr.io \ + --docker-username=x-access-token \ + --docker-password="$TOKEN" \ + --dry-run=client -o yaml | kubectl apply -f - + +kubectl create secret generic context7-config \ + --namespace context7 \ + --from-literal=LICENSE_KEY="$LICENSE_KEY" \ + --dry-run=client -o yaml | kubectl apply -f - +``` + +## Manifests + +Context7 Enterprise runs as a single-replica StatefulSet with persistent storage. The manifests below define the core resources: a StatefulSet for the application, a Service for internal routing, and an Ingress for external access. + +### StatefulSet + +Context7 uses SQLite and LanceDB for local storage, which require a persistent volume. This means it must run as a **StatefulSet with a single replica** since SQLite does not support concurrent writers. + +```yaml statefulset.yaml +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: context7 + namespace: context7 +spec: + serviceName: context7 + replicas: 1 + selector: + matchLabels: + app: context7 + template: + metadata: + labels: + app: context7 + spec: + imagePullSecrets: + - name: context7-registry + terminationGracePeriodSeconds: 60 + containers: + - name: context7 + image: ghcr.io/context7/enterprise:latest + imagePullPolicy: Always + ports: + - containerPort: 3000 + name: http + env: + - name: LICENSE_KEY + valueFrom: + secretKeyRef: + name: context7-config + key: LICENSE_KEY + volumeMounts: + - name: data + mountPath: /data + resources: + requests: + cpu: "1" + memory: "2Gi" + limits: + cpu: "4" + memory: "8Gi" + startupProbe: + httpGet: + path: /api/health + port: http + initialDelaySeconds: 5 + periodSeconds: 5 + failureThreshold: 12 + livenessProbe: + httpGet: + path: /api/health + port: http + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /api/health + port: http + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + volumeClaimTemplates: + - metadata: + name: data + spec: + # storageClassName: gp3 # Set this if your cluster has no default StorageClass + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 10Gi +``` + + + **Storage class:** If your cluster does not have a default StorageClass, the PVC will stay in `Pending` and the pod won't start. Uncomment `storageClassName` and set it to a StorageClass available in your cluster (e.g. `gp3` on AWS EKS, `standard` on GKE, `default` on AKS). Run `kubectl get sc` to see available options. + + + + **Resource sizing:** The defaults above (1 CPU / 2 GiB request) work for light usage. If you are parsing many large repositories concurrently, increase the limits. Parsing is CPU and memory intensive due to LLM calls and vector indexing. + + + + Do not set `replicas` higher than 1. Context7 uses SQLite which only supports a single writer. Running multiple replicas will cause database lock errors. + + +### Service + +```yaml service.yaml +apiVersion: v1 +kind: Service +metadata: + name: context7 + namespace: context7 +spec: + selector: + app: context7 + ports: + - port: 3000 + targetPort: http + protocol: TCP + name: http + type: ClusterIP +``` + +### Ingress + +```yaml ingress.yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: context7 + namespace: context7 + annotations: + nginx.ingress.kubernetes.io/proxy-body-size: "50m" +spec: + ingressClassName: nginx + tls: + - hosts: + - context7.internal.yourcompany.com + secretName: context7-tls + rules: + - host: context7.internal.yourcompany.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: context7 + port: + number: 3000 +``` + +Replace `context7.internal.yourcompany.com` with your actual hostname and `context7-tls` with your TLS secret. + +## Apply Everything + +After creating the namespace and secrets in the [Registry Authentication](#registry-authentication) step, apply the manifests: + +```bash +kubectl apply -f statefulset.yaml +kubectl apply -f service.yaml +kubectl apply -f ingress.yaml +``` + +Verify the pod is running: + +```bash +kubectl get pods -n context7 +kubectl logs -n context7 context7-0 +``` + +Once the pod is ready, open your Ingress hostname in a browser to complete the setup wizard. + +## Networking Requirements + +Context7 requires outbound connectivity to the following: + +| Destination | Purpose | +|---|---| +| `ghcr.io` | Container image pulls (`imagePullPolicy: Always`) | +| `context7.com` | License validation | +| Your LLM provider (e.g. `api.openai.com`) | AI inference and embeddings | +| `github.com` / `gitlab.com` | Repository cloning | + +If you use NetworkPolicies, ensure egress to these endpoints is allowed: + +```yaml networkpolicy.yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: context7-egress + namespace: context7 +spec: + podSelector: + matchLabels: + app: context7 + policyTypes: + - Egress + egress: + - {} # Allow all egress (simplest) +``` + +For stricter policies, allow egress on port 443 to the specific domains listed above, and ensure egress to `kube-dns` on port 53 (UDP/TCP) is permitted for DNS resolution. + +## Operations + +### Updating + +Pull the latest image and restart: + +```bash +kubectl rollout restart statefulset/context7 -n context7 +``` + +To pin a specific version: + +```bash +kubectl set image statefulset/context7 \ + context7=ghcr.io/context7/enterprise:1.2.0 \ + -n context7 +``` + +If your registry token has expired, refresh it before restarting: + +```bash +LICENSE_KEY="" + +TOKEN=$(curl -s -H "Authorization: Bearer $LICENSE_KEY" \ + https://context7.com/api/v1/license/registry-token | jq -r '.token') + +kubectl create secret docker-registry context7-registry \ + --namespace context7 \ + --docker-server=ghcr.io \ + --docker-username=x-access-token \ + --docker-password="$TOKEN" \ + --dry-run=client -o yaml | kubectl apply -f - +``` + +### Health Monitoring + +The `/api/health` endpoint returns structured JSON with license status, connectivity, and parsed repo count. Point your monitoring stack at it: + +```bash +kubectl exec -n context7 context7-0 -- \ + wget -qO- http://localhost:3000/api/health +``` + +Example response: + +```json +{ + "status": "healthy", + "version": "1.0.0", + "setup": "complete", + "license": "configured", + "licenseInfo": { + "valid": true, + "teamSize": 10, + "expiresAt": "2026-06-01T00:00:00.000Z" + }, + "repos_parsed": 5, + "uptime": 3600, + "connectivity": { + "llm": "configured", + "llm_provider": "openai", + "embedding": "configured", + "embedding_provider": "openai", + "github": "configured", + "gitlab": "not configured" + } +} +``` + +### Logs + +```bash +# Follow logs +kubectl logs -f -n context7 context7-0 + +# Check license and startup status +kubectl logs -n context7 context7-0 | head -20 +``` + +## Troubleshooting + +### Pod is in CrashLoopBackOff + +Context7 validates your license key on startup. If the key is missing, invalid, or expired, the server exits immediately before the health endpoint is available. This means Kubernetes will report `CrashLoopBackOff` rather than a failed probe. + +Check the logs first: + +```bash +kubectl logs -n context7 context7-0 +``` + +Look for `[license]` messages in the first few lines. Common causes: + +- **Missing or incorrect `LICENSE_KEY`** in the `context7-config` secret +- **No outbound connectivity** to `context7.com` for license validation +- **Expired license**: contact [context7@upstash.com](mailto:context7@upstash.com) to renew + + + The startup probe only comes into play after the license is validated. If the pod is crash-looping, the issue is always upstream of the probe. Check logs, not probe events. + + +## Connecting AI Clients + +Once deployed, point your MCP clients to your Ingress URL. See [Connecting Your AI Client](/enterprise/on-premise#connecting-your-ai-client) for client-specific instructions. Replace `localhost:3000` with your Kubernetes Ingress hostname. diff --git a/docs/enterprise/enterprise-managed-auth/entra.mdx b/docs/enterprise/enterprise-managed-auth/entra.mdx new file mode 100644 index 0000000..3680ac4 --- /dev/null +++ b/docs/enterprise/enterprise-managed-auth/entra.mdx @@ -0,0 +1,751 @@ +--- +title: "Azure API Management as MCP gateway" +sidebarTitle: "Microsoft Entra ID" +description: "Route Context7 MCP traffic through Azure API Management with per-user Microsoft Entra ID authentication." +--- + +This guide walks through deploying Azure API Management (APIM) as a gateway in front of `mcp.context7.com`, with per-user authentication backed by your Microsoft Entra tenant. Developers sign in once with their corporate Entra account in their MCP client (for example VS Code with GitHub Copilot), and every request to Context7 is attributed to that individual through the `oid` claim on their Entra access token. + +The gateway uses an On-Behalf-Of (OBO) flow: clients acquire a token for the APIM gateway, APIM exchanges it via Entra for a token targeting your MCP API, and the resulting token is forwarded to `mcp.context7.com`. Context7 validates the token against your tenant configuration and resolves the user. APIM remains the network and audit boundary; MFA and Conditional Access continue to be enforced by Entra at sign-in. + +## Architecture + +```mermaid +sequenceDiagram + participant Client as MCP Client + participant APIM as Azure APIM + participant Entra as Microsoft Entra + participant Context7 as mcp.context7.com + + Client->>Entra: Acquire token for APIM Gateway app + Entra-->>Client: JWT (aud = Gateway, scp = Mcp.Gateway.Access) + + Client->>APIM: Request + Bearer token + APIM->>APIM: validate-azure-ad-token
(aud = Gateway) + APIM->>Entra: OBO exchange
(scope = MCP API) + Entra-->>APIM: JWT (aud = MCP API, scp = mcp.access) + APIM->>APIM: Cache OBO token per user oid + + APIM->>Context7: Forward request + new Bearer token + Context7->>Context7: Validate against tenant config
Resolve oid to user + Context7-->>APIM: Response + APIM-->>Client: Response +``` + +## Before you start + +You will need: + +- An **Azure subscription** in the same tenant as your Entra users. +- A **Microsoft Entra admin** who can register applications and grant tenant-wide consent. +- A **Context7 enterprise teamspace**. The dashboard surfaces the Entra ID configuration card only for enterprise and enterprise-trial teamspaces. +- The **Azure CLI** installed locally (`brew install azure-cli` on macOS) and authenticated with `az login`. + +Plan for about 45 to 60 minutes end-to-end on a clean Azure subscription. + +## Part 1: Provision API Management + +APIM Basic v2 provisions in about 5 minutes and supports MCP routing. Consumption tier does **not** support MCP backends. + +Create a Bicep file: + +```bicep apim.bicep +param name string +param location string +param publisherEmail string +param publisherName string + +resource apim 'Microsoft.ApiManagement/service@2024-05-01' = { + name: name + location: location + sku: { + name: 'BasicV2' + capacity: 1 + } + properties: { + publisherEmail: publisherEmail + publisherName: publisherName + } +} + +output gatewayUrl string = apim.properties.gatewayUrl +``` + +Deploy it: + +```bash +RG=rg-context7-mcp +LOC=westeurope +APIM=apim-context7-$(openssl rand -hex 3) + +az group create -n $RG -l $LOC +az deployment group create -g $RG --template-file apim.bicep \ + --parameters name=$APIM location=$LOC \ + publisherEmail=you@example.com publisherName="Your Org" +``` + +Capture the gateway URL: + +```bash +APIM_HOST=$(az apim show -g $RG -n $APIM --query gatewayUrl -o tsv) +echo $APIM_HOST # https://.azure-api.net +``` + +## Part 2: Register Entra applications + +Two Entra app registrations are required: one representing the MCP API (the protected resource), and one representing the APIM gateway (the OBO intermediary). + +### Step 1: Register the MCP API app + +This app represents Context7's MCP server in your tenant. Issued tokens will carry its Application (client) ID as the `aud` claim. + +1. **Microsoft Entra admin center** → **App registrations** → **+ New registration**. + - **Name:** `Context7 MCP API` + - **Supported account types:** Single tenant only (formerly labelled "Accounts in this organizational directory only") + - **Redirect URI:** leave blank + - **Register** + +2. Copy the **Application (client) ID** from the Overview page. You will provide it to Context7 in Part 4. + +3. **Expose an API** → **Add** next to "Application ID URI" → accept the default `api://` → **Save**. + +4. **+ Add a scope**: + - **Scope name:** `mcp.access` + - **Who can consent:** Admins and users + - **Admin consent display name:** `Access Context7 MCP server` + - **State:** Enabled + - **Add scope** + +5. **Manifest** → set `requestedAccessTokenVersion: 2` under the `api` object. Save. + + + This forces v2 tokens with `iss: https://login.microsoftonline.com//v2.0`. v1 tokens use a different issuer and fail validation at the Context7 backend. + + +### Step 2: Register the APIM Gateway app + +This app represents the gateway as an Entra resource. Clients request tokens for it; APIM exchanges them for MCP API tokens. + +1. **App registrations** → **+ New registration**. + - **Name:** `Context7 APIM Gateway` + - **Supported account types:** Single tenant only (formerly labelled "Accounts in this organizational directory only") + - **Register** + +2. Copy the **Application (client) ID** and **Directory (tenant) ID** from the Overview page. + +3. **Certificates & secrets** → **+ New client secret** → set an expiry → **Add**. Copy the **Value** column immediately; it is only shown once. + +4. **Expose an API** → **Add** next to "Application ID URI" → accept the default → **Save**. + +5. **+ Add a scope**: + - **Scope name:** `Mcp.Gateway.Access` + - **Who can consent:** Admins and users + - **State:** Enabled + - **Add scope** + +6. **Manifest** → set `requestedAccessTokenVersion: 2`. Save. + + + The Manifest UI sometimes silently fails to persist this value. If you see v1 tokens (`iss: https://sts.windows.net/...` or `ver: 1.0`) after setting it, apply it via CLI instead: + + ```bash + az ad app update --id --set api.requestedAccessTokenVersion=2 + az ad app show --id --query api.requestedAccessTokenVersion -o tsv # should print 2 + ``` + + Do the same for the MCP API app from Step 1 if its tokens come back as v1. + + +7. **Authentication** → **+ Add a platform** → **Web** → enter `https://vscode.dev/redirect` as the redirect URI → **Configure**. + + + VS Code with GitHub Copilot uses Microsoft's hosted OAuth broker at `vscode.dev/redirect` rather than a local loopback URI. The redirect URI must be registered on the Gateway app or the sign-in flow fails with `AADSTS500113` or `AADSTS50011`. Add additional redirect URIs (or platforms) here for other MCP clients as you adopt them. Each client tool's documentation lists its expected URI. + + +### Step 3: Wire the permission chain + +The APIM Gateway app must be allowed to call the MCP API on a user's behalf, and the MCP client tools must be allowed to call the Gateway. + +In the **Context7 APIM Gateway** app: + +1. **API permissions** → **+ Add a permission** → **My APIs** → `Context7 MCP API` → **Delegated permissions** → check `mcp.access` → **Add permissions**. +2. Click **Grant admin consent for ``** at the top of the permissions table. +3. **Expose an API** → **Authorized client applications** → **+ Add a client application**. For each MCP client tool you want to allow, add its client ID and tick the `Mcp.Gateway.Access` scope: + - **VS Code with GitHub Copilot:** `aebc6443-996d-45c2-90f0-388ff96faa56` (Microsoft's well-known VS Code client ID). + - **Other tools:** check the tool's documentation for its published OAuth client ID. + +In the **Context7 MCP API** app: + +1. **Expose an API** → **Authorized client applications** → **+ Add a client application**. Add the **Context7 APIM Gateway** app's client ID and tick the `mcp.access` scope. This skips the end-user consent prompt during the OBO exchange. + +## Part 3: Configure API Management + +### Step 1: Store credentials as named values + +```bash +az apim nv create -g $RG --service-name $APIM \ + --named-value-id entra-tenant-id \ + --display-name entra-tenant-id \ + --value "" + +az apim nv create -g $RG --service-name $APIM \ + --named-value-id apim-gateway-app-id \ + --display-name apim-gateway-app-id \ + --value "" + +az apim nv create -g $RG --service-name $APIM \ + --named-value-id apim-gateway-client-secret \ + --display-name apim-gateway-client-secret \ + --value "" \ + --secret true + +az apim nv create -g $RG --service-name $APIM \ + --named-value-id mcp-api-app-id \ + --display-name mcp-api-app-id \ + --value "" +``` + + +For production, back the client secret with Azure Key Vault rather than storing the value inline. Update the named value to reference a Key Vault secret and grant APIM's managed identity `get` access to the vault. + + +### Step 2: Create the API and the MCP operation + +```bash +az apim api create -g $RG --service-name $APIM \ + --api-id context7-mcp \ + --display-name "Context7 MCP" \ + --path context7 \ + --service-url https://mcp.context7.com \ + --protocols https \ + --subscription-required false + +az apim api operation create -g $RG --service-name $APIM \ + --api-id context7-mcp \ + --operation-id post-mcp \ + --display-name "MCP" \ + --method POST \ + --url-template "/mcp" +``` + +### Step 3: Attach the OBO policy + +Save the following as `policy.xml`: + +```xml policy.xml + + + + + + + {{apim-gateway-app-id}} + + + + Mcp.Gateway.Access + + + + + + + + + + + + + + + + + @("https://login.microsoftonline.com/" + (string)context.Variables["entraTenantId"] + "/oauth2/v2.0/token") + POST + + application/x-www-form-urlencoded + + @{ + var auth = context.Request.Headers.GetValueOrDefault("Authorization", ""); + var inbound = auth.StartsWith("Bearer ") ? auth.Substring(7) : auth; + var pairs = new System.Collections.Generic.Dictionary<string, string> { + { "grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer" }, + { "client_id", (string)context.Variables["gatewayAppId"] }, + { "client_secret", (string)context.Variables["gatewaySecret"] }, + { "assertion", inbound }, + { "scope", "api://" + (string)context.Variables["mcpApiAppId"] + "/.default" }, + { "requested_token_use", "on_behalf_of" } + }; + var parts = new System.Collections.Generic.List<string>(); + foreach (var kv in pairs) { + parts.Add(System.Net.WebUtility.UrlEncode(kv.Key) + "=" + System.Net.WebUtility.UrlEncode(kv.Value)); + } + return string.Join("&", parts); + } + + + + + + + + + + @("Bearer " + (string)context.Variables["oboToken"]) + + + + + + + + + + + + + +``` + + +Two XML quirks the policy works around: + +1. **Named values do not substitute inside policy expressions.** `{{...}}` is substituted by APIM only in plain element/attribute text. References inside a `@{...}` or `@(...)` expression are treated as literal C# strings. Pull each named value into a `context.Variables` slot with an attribute-form `` block, then reference the variable inside the expression. +2. **Attribute values cannot contain raw `"`, `<`, `>`, or `&`.** Use `"`, `<`, `>`, `&` in attribute-form expressions. Element content (like ``) only needs to escape `<`, `>`, and `&`; double quotes are fine. CDATA sections also avoid escaping but disable named-value substitution, so prefer plain element content with escapes. + + +Apply it via the management REST API. `jq` wraps the policy XML in the JSON envelope the management API expects, written to `policy-body.json`: + +```bash +SUB=$(az account show --query id -o tsv) + +jq -Rs '{properties: {value: ., format: "xml"}}' policy.xml > policy-body.json + +az rest --method put \ + --uri "https://management.azure.com/subscriptions/$SUB/resourceGroups/$RG/providers/Microsoft.ApiManagement/service/$APIM/apis/context7-mcp/policies/policy?api-version=2024-05-01" \ + --body @policy-body.json +``` + + +The cache duration (`3000` seconds) is slightly below Entra's default access token lifetime of one hour. Adjust if your Conditional Access policies issue shorter-lived tokens. The cache key includes the `oid` claim so each user's OBO token is isolated. + + +## Part 4: Onboard your tenant in Context7 + +Context7 validates inbound tokens in two stages: first the token's signature, audience, issuer, and scope are checked against your teamspace's tenant configuration; then the token's `oid` claim is resolved against a list of pre-provisioned users for the teamspace. **Both checks are mandatory.** Any developer who has not been added to the teamspace's user list will be rejected with `401` even when their token is otherwise valid. + +An owner or admin of the teamspace configures both from the dashboard. Users can be added one at a time (Step 2) or synced automatically from an Entra security group (Step 3). + +### Step 1: Configure the tenant + +1. Sign in to [context7.com/dashboard](https://context7.com/dashboard) and select the teamspace that will own the integration. +2. **Settings** tab → **Microsoft Entra ID** card → **Configure**. + + + The Settings tab itself is visible only for enterprise teamspaces and active enterprise trials. If you don't see it, confirm the selected teamspace is on an enterprise plan. + + +3. Fill in: + - **Tenant ID:** your Entra directory ID + - **Audience:** the **MCP API app** Application (client) ID (the second token's audience, not the gateway app) + - **Required scope:** `mcp.access` + +4. Click **Test connection**. Context7 fetches your tenant's OpenID Connect discovery document from Microsoft and confirms the issuer matches. + +5. **Save**. + +### Step 2: Pre-provision your developers + +After saving the tenant configuration, scroll down to the **Microsoft Entra ID users** card on the same Settings tab. This is where you list every Entra user who should be able to authenticate to the teamspace through APIM. + +1. Click **Add user**. +2. Enter the user's: + - **Email:** the address they sign in to Entra with. + - **Object ID (oid):** their Entra object ID. Find it in the Entra admin center under **Users → `` → Overview → Object ID**, or have the user run `az ad signed-in-user show --query id -o tsv` after `az login`. +3. Click **Add user** to save. + +Context7 creates a Clerk user record for the developer, adds them as a `developer` member of the teamspace, and inserts a `(tenant, oid, teamspace)` mapping. The same email can be added to multiple teamspaces; the Clerk user is reused and a separate mapping row is created per teamspace. + + +Clicking **Remove** on the Microsoft Entra ID card removes both the tenant configuration **and** all provisioned users for the teamspace in a single step. If you only need to revoke a single user, remove them from the Microsoft Entra ID users card instead. + + + +Each MCP API app (audience) can be configured for **one** teamspace at a time. If you reuse an audience already claimed by a different teamspace you will see "This audience is already configured for another teamspace". Open the other teamspace's Settings tab and remove the Entra configuration there first, or register a new MCP API app for this teamspace. + + + +For more than a handful of developers, prefer **Step 3: Auto-provision from an Entra security group** below. Adds and revokes track group membership automatically. CSV bulk-import and SCIM provisioning remain on the roadmap; reach out to [context7@upstash.com](mailto:context7@upstash.com) if your scale needs either ahead of general availability. + + +### Step 3: Auto-provision from an Entra security group (optional) + +For teams of more than a handful of developers, Context7 can sync the teamspace's user list directly from a Microsoft Entra security group. Members added to the group are added to the teamspace automatically; members removed from the group have their access revoked. The sync runs every 30 minutes; an admin can also trigger an immediate sync from the dashboard. + +The integration uses Microsoft Graph with **Workload Identity Federation** (WIF). Context7 acts as an OIDC issuer and signs short-lived JWT assertions that your sync app trusts via a federated credential. No shared secret is stored, rotated, or exchanged on either side. + +1. **Add Microsoft Graph permissions** to an Entra app registration. + + The simplest path is to reuse the **Context7 MCP API** app from [Part 2 Step 1](#step-1-register-the-mcp-api-app): federated identity holds no secret, so reusing it adds no risk. Open that app and add: + + - **API permissions** → **+ Add a permission** → **Microsoft Graph** → **Application permissions**. + - Search and tick `GroupMember.Read.All` and `User.ReadBasic.All`. + - **Add permissions**, then click **Grant admin consent for ``** at the top of the list. + + + Both permissions are required. `GroupMember.Read.All` alone returns each user's `oid` with all profile fields nulled out, so the sync can't resolve them to emails and drops them, surfacing as `0 members` synced. `User.ReadBasic.All` populates `mail`, `userPrincipalName`, and `displayName`. + + +2. **Add a federated credential.** + + On the same app: **Certificates & secrets** → **Federated credentials** tab → **+ Add credential** → **Federated credential scenario: Other issuer**. Open the Context7 dashboard alongside the Entra portal. The **Auto-provisioning from Entra group** card surfaces three values with copy buttons. Paste them as: + + - **Issuer**: `https://context7.com` + - **Type**: Explicit subject identifier + - **Value**: `teamspace:` (copy verbatim from the dashboard) + - **Audience**: `api://AzureADTokenExchange` + - **Name**: any label (e.g. `Context7-sync`). + + **Add**. No client secret is generated. + +3. **Create or pick an Entra security group** containing the developers who should have access. + + Entra admin center → **Groups** → **+ New group** (type *Security*, membership type *Assigned*). Add developers as **Members**, not Owners. Graph's `/members` endpoint doesn't include group owners by default. + + Open the group → **Overview** → copy the **Object ID**. + +4. **Configure in the Context7 dashboard.** + + Settings tab → **Microsoft Entra ID users** card → **Auto-sync from Entra group** panel → **Configure**. + + - **Sync app client ID**: the app you set up in step 1 (the MCP API app's client ID if you reused it). + - **Group object ID**: from step 3. + - Leave **Revoke access when a user is removed from the group** and **Run sync on schedule** ticked. + - Click **Test connection**. Expected response: *"Connected. Group has N members."* + - **Save**. + +5. **Click "Sync now"** to provision the current group members immediately. Each appears in the **Microsoft Entra ID users** list with a **Synced** badge. Subsequent syncs run every 30 minutes. + + +Manually-added users (Step 2) and synced users (Step 3) coexist on the same teamspace. The sync reconciler only touches rows whose provisioning source is `graph_group_sync`, so removing someone from the Entra group never revokes a manually-added user. + + + +If you want strict separation of concerns, register a dedicated **Context7 Sync** app instead of reusing the MCP API app. Add the same two Graph permissions and the same federated credential to it, and use its client ID in step 4. The choice is purely organizational; both produce identical sync behavior. + + + +Nested groups are not expanded. If `Context7 MCP Users` contains a subgroup `Engineering`, only direct members of `Context7 MCP Users` are synced. Flatten by adding individual members or use a single dynamic membership group. + + +The Context7 MCP server now accepts tokens whose `aud` matches the audience you provided, signed by your tenant's Entra issuer, with the required scope present, and whose `oid` matches one of the users on the teamspace's user list (manual or synced). + +## Part 5: Expose OAuth discovery for MCP clients + +For MCP clients (VS Code with GitHub Copilot, Claude Code, Cursor) to authenticate themselves without a manually-pasted Bearer token, APIM needs to advertise an OAuth 2.1 discovery surface and bridge `/authorize` and `/token` to Entra. The MCP server returns `401` with a `WWW-Authenticate` header pointing at a PRM document; clients follow the chain to obtain a token. + +### Step 1: Create the OAuth proxy API at the host root + +A second API in APIM at the root path hosts the well-known endpoints and the OAuth bridge: + +```bash +az apim api create -g $RG --service-name $APIM \ + --api-id oauth-proxy \ + --display-name "OAuth Proxy" \ + --path "" \ + --service-url "https://login.microsoftonline.com//oauth2/v2.0" \ + --protocols https \ + --subscription-required false + +for op in prm-metadata as-metadata authorize token; do + case $op in + prm-metadata) path="/.well-known/oauth-protected-resource"; method=GET ;; + as-metadata) path="/.well-known/oauth-authorization-server"; method=GET ;; + authorize) path="/authorize"; method=GET ;; + token) path="/token"; method=POST ;; + esac + az apim api operation create -g $RG --service-name $APIM \ + --api-id oauth-proxy --operation-id $op \ + --display-name "$op" --method $method --url-template "$path" +done +``` + +### Step 2: Attach the discovery + redirect policies + +Save the three policy files: + +```xml prm-policy.xml + + + + + + application/json + + { + "resource": "https:///context7", + "authorization_servers": ["https://"], + "scopes_supported": ["api:///Mcp.Gateway.Access"], + "bearer_methods_supported": ["header"] +} + + + +``` + +```xml as-metadata-policy.xml + + + + + + application/json + + { + "issuer": "https://", + "authorization_endpoint": "https:///authorize", + "token_endpoint": "https:///token", + "jwks_uri": "https://login.microsoftonline.com//discovery/v2.0/keys", + "response_types_supported": ["code"], + "grant_types_supported": ["authorization_code", "refresh_token"], + "code_challenge_methods_supported": ["S256"], + "token_endpoint_auth_methods_supported": ["none", "client_secret_post"], + "scopes_supported": ["openid", "profile", "email", "offline_access", "api:///Mcp.Gateway.Access"] +} + + + +``` + +```xml authorize-policy.xml + + + + + + @($"https://login.microsoftonline.com//oauth2/v2.0/authorize{context.Request.OriginalUrl.QueryString}") + + + + +``` + +Apply all three: + +```bash +for op in prm-metadata as-metadata authorize; do + case $op in + prm-metadata) file=prm-policy.xml ;; + as-metadata) file=as-metadata-policy.xml ;; + authorize) file=authorize-policy.xml ;; + esac + jq -Rs '{properties: {value: ., format: "xml"}}' $file > /tmp/body.json + az rest --method put \ + --uri "https://management.azure.com/subscriptions/$SUB/resourceGroups/$RG/providers/Microsoft.ApiManagement/service/$APIM/apis/oauth-proxy/operations/$op/policies/policy?api-version=2024-05-01" \ + --body @/tmp/body.json +done +``` + +The `/token` operation needs no custom policy. APIM forwards POST `/token` to the service URL (`.../oauth2/v2.0/token`) with the form-encoded body and JSON response intact. + + +We use a 302 redirect on `/authorize` rather than a transparent proxy. Microsoft's sign-in page contains relative URLs and cookies tied to `login.microsoftonline.com`; proxying the HTML breaks form submissions. The redirect lands the user's browser on Microsoft's domain directly, where the sign-in flow works normally. + + +### Step 3: Add WWW-Authenticate to the MCP API on 401 + +Update the `` block in the context7-mcp policy from Part 3 so unauthorised requests carry the discovery hint: + +```xml + + + + + + Bearer resource_metadata="https:///.well-known/oauth-protected-resource" + + + + +``` + +Re-apply the policy with the same `az rest` command from Part 3. + +### Step 4: Verify the discovery surface + +```bash +curl -s "https:///.well-known/oauth-protected-resource" +curl -s "https:///.well-known/oauth-authorization-server" + +curl -i -o /dev/null -w "%{http_code} -> %{redirect_url}\n" \ + "https:///authorize?client_id=&response_type=code&redirect_uri=http%3A%2F%2F127.0.0.1%2F&code_challenge=abc&code_challenge_method=S256&scope=api%3A%2F%2F%2FMcp.Gateway.Access&state=x" + +curl -i -X POST "https:///context7/mcp" -d '{}' -H "Content-Type: application/json" 2>&1 | head -10 +``` + +Expected: +- PRM and AS metadata return the JSON documents you just defined. +- `/authorize` returns `302 Found` with a `Location` header pointing at Entra's authorize endpoint. +- An unauthorised POST to `/context7/mcp` returns `401` with `WWW-Authenticate: Bearer resource_metadata="https:///.well-known/oauth-protected-resource"`. + +## Part 6: Smoke test the gateway from CLI + +Before pointing real MCP clients at the gateway, validate the full OBO flow from your terminal. This catches misconfigurations (wrong audience, missing scope, unmapped user) without involving an MCP client. + +### Step 1: Authorize the Azure CLI on the Gateway app + +Azure CLI's well-known client ID is `04b07795-8ddb-461a-bbee-02f9e1bf7b46`. Pre-authorize it on the Gateway app's scope so `az account get-access-token` can mint tokens: + +1. Entra admin center → **App registrations** → **Context7 APIM Gateway** → **Expose an API**. +2. Under **Authorized client applications**, click **+ Add a client application**. +3. **Client ID:** `04b07795-8ddb-461a-bbee-02f9e1bf7b46`. +4. Tick the `api:///Mcp.Gateway.Access` scope. **Add**. + + +This pre-authorization is only required for the CLI smoke test described here. End users connecting via VS Code with GitHub Copilot use Microsoft's first-party VS Code client ID, which you already pre-authorized in [Part 2 Step 3](#step-3-wire-the-permission-chain). + + +### Step 2: Acquire a token and call the gateway + +```bash +GATEWAY_APP_ID= +APIM_HOST= + +az login --tenant --scope api://$GATEWAY_APP_ID/.default + +TOKEN=$(az account get-access-token --resource api://$GATEWAY_APP_ID --query accessToken -o tsv) + +curl -i -X POST "https://$APIM_HOST/context7/mcp" \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json, text/event-stream" \ + -d '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"smoke","version":"0.0.1"}}}' +``` + +Expected: `200 OK`, an `mcp-session-id` response header, and a Server-Sent Events body with the Context7 server info. That confirms APIM validated your inbound token, performed the OBO exchange, forwarded the new token to `mcp.context7.com`, the MCP server validated it against your tenant configuration, and the request was attributed to your provisioned user. + +If you get a non-200 status, decode `$TOKEN` at [jwt.io](https://jwt.io) and confirm `aud` is the Gateway app's client ID, `scp` is `Mcp.Gateway.Access`, and `oid` matches the value you added under **Microsoft Entra ID users**. See [Troubleshooting](#troubleshooting) for specific error codes. + +## Part 7: Connect an MCP client + +Configure your MCP client to talk to the APIM endpoint. Example for VS Code with GitHub Copilot: + +`~/Library/Application Support/Code/User/mcp.json` on macOS (similar paths on Windows/Linux, or `.vscode/mcp.json` per workspace): + +```json +{ + "servers": { + "context7": { + "type": "http", + "url": "https:///context7/mcp" + } + } +} +``` + +Reload VS Code. The first time GitHub Copilot uses the server, the OAuth flow runs: + +1. VS Code calls `/context7/mcp` with no token. APIM returns `401` with the `WWW-Authenticate` header. +2. VS Code follows the PRM, then the AS metadata. +3. VS Code attempts Dynamic Client Registration. Because Entra ID does not implement RFC 7591, the request fails and VS Code shows a dialog: **"Dynamic Client Registration not supported. Do you want to proceed by manually providing a client registration?"** +4. Click **Copy URIs & Proceed**, then paste the **APIM Gateway app's Application (client) ID** when prompted. (This is the same app whose client secret APIM uses for the OBO call.) +5. A browser window opens. The URL bar should switch to `login.microsoftonline.com/...` after APIM's 302 redirect. Sign in with your Entra account and accept the `Mcp.Gateway.Access` consent. +6. The browser redirects to `https://vscode.dev/redirect` (VS Code's hosted OAuth broker), which hands the auth code back to your local VS Code instance. +7. VS Code exchanges the code at APIM's `/token` endpoint, which forwards the request to Entra. Entra returns an access token whose audience is the Gateway app. +8. VS Code calls `/context7/mcp` with the new token. APIM validates it, performs the OBO exchange to mint an MCP-API-audience token, and forwards to Context7. +9. The MCP server validates the OBO token against your tenant configuration and serves the request as the signed-in user. + +Trigger a Copilot Chat tool call ("use context7 to resolve the library ID for Next.js") to verify the integration. + + +The manual client ID step is required because Entra ID doesn't implement RFC 7591 Dynamic Client Registration. You can document the Gateway app's client ID in your internal onboarding guide and rotate it on the normal app-registration lifecycle. Microsoft's first-party VS Code client ID (`aebc6443-996d-45c2-90f0-388ff96faa56`) can also be used by pre-authorising it on the Gateway scope, but the Gateway app's own client ID is the most consistent path because PKCE removes the need for a client secret on the user-facing side. + + +## End-to-end token claims + +The flow produces two distinct tokens, both issued by your Entra tenant for the same user: + +| Hop | `iss` | `aud` | `oid` | `scp` | +|---|---|---|---|---| +| Client → APIM | `https://login.microsoftonline.com//v2.0` | `` | user's Entra object ID | `Mcp.Gateway.Access` | +| APIM → Context7 (after OBO) | `https://login.microsoftonline.com//v2.0` | `` | user's Entra object ID | `mcp.access` | + +Context7 validates the second token against your dashboard configuration and resolves `oid` to a user in your teamspace. + +## Troubleshooting + +### `401 Unauthorized` at APIM + +The inbound token failed `validate-azure-ad-token`. Decode it at [jwt.io](https://jwt.io) and check: + +- `iss` is `https://login.microsoftonline.com//v2.0`. If it is `https://sts.windows.net//`, the APIM Gateway app's manifest needs `requestedAccessTokenVersion: 2`. +- `aud` equals the **APIM Gateway** app's client ID, not the MCP API app's. +- `scp` contains `Mcp.Gateway.Access`. +- `exp` is in the future. + +### OBO exchange returns `AADSTS50013` or `AADSTS65001` + +The APIM Gateway app is not authorised to call the MCP API on a user's behalf. In the APIM Gateway app, verify the **API permissions** tab lists `Context7 MCP API → mcp.access (Delegated)` with **Granted for ``**. If admin consent has not been granted, run **Grant admin consent**. + +### OBO exchange returns `AADSTS70011: Invalid scope` + +The `scope` parameter in the OBO request is malformed. Verify that the `mcp-api-app-id` named value contains the **MCP API** app's client ID (a GUID) and that the policy expression renders `api:///.default`. + +### `401 Unauthorized` from Context7 with a valid OBO token + +Either the token does not match the teamspace's tenant configuration, or the user is not on the teamspace's pre-provisioned list. + +First open **Settings → Microsoft Entra ID** in the dashboard and verify: + +- **Tenant ID** matches the OBO token's `tid` claim. +- **Audience** matches the OBO token's `aud` claim exactly (case-sensitive, GUID form for v2 tokens). +- **Required scope** matches a value in the token's `scp` claim. + +Use **Test connection** to confirm the tenant is reachable. + +If the tenant config is correct, the user's `oid` is probably not in the teamspace's provisioned users list. Decode the OBO token at [jwt.io](https://jwt.io) and copy the `oid` claim, then check that exact value appears in **Settings → Microsoft Entra ID users**. If it's missing, add the user (see Part 4 Step 2). + +### Streaming responses get cut off + +APIM diagnostics with "Number of payload bytes to log" set above zero truncate MCP's Server-Sent Events stream. Set Frontend Response payload logging to `0` at the service level. + +### Wrong client ID returned to MCP clients + +If a client signs in but receives `AADSTS65005: The resource is disabled` or similar, the client's app ID is not in the APIM Gateway app's **Authorized client applications** list for the `Mcp.Gateway.Access` scope. Add it explicitly. + +### Auto-sync reports "0 members" but the group has members + +Two common causes, in order of likelihood: + +1. **The sync app is missing `User.ReadBasic.All`.** With only `GroupMember.Read.All`, Microsoft Graph returns each user's `oid` but with `mail`, `userPrincipalName`, and `displayName` set to `null`. Context7 drops users without a resolvable email. The dashboard surfaces this as the error message: *"Graph returned N user members but their profile fields are null. Sync app needs User.ReadBasic.All in addition to GroupMember.Read.All."* Add `User.ReadBasic.All` to the sync app's API permissions and grant admin consent. + +2. **The users are group Owners, not Members.** Open the group in Entra → **Members** tab (not Owners) → verify the people you expect to sync are listed there. Add them as Members if they're only Owners. + +### `AADSTS500113: No reply address is registered for the application` + +The Gateway app has no redirect URIs registered. VS Code's OAuth flow sends `https://vscode.dev/redirect` as the redirect URI, and Entra rejects the request when that URI isn't on the app. Open the Gateway app in Entra → **Authentication** → **+ Add a platform** → **Web** → add `https://vscode.dev/redirect` → **Configure**. See [Part 2 Step 2](#step-2-register-the-apim-gateway-app). + +### `AADSTS50011: The redirect URI ... does not match` + +A specific redirect URI was sent that the Gateway app doesn't have on its list. Read the error message to see exactly which URI Entra received (most commonly `https://vscode.dev/redirect`), then add it under the Gateway app's **Authentication** → **+ Add a platform** → **Web**. + +## What this does not cover + +- **On-premise MCP server.** This guide proxies the hosted `mcp.context7.com`. For air-gapped or compliance scenarios where MCP traffic cannot leave your network, contact [context7@upstash.com](mailto:context7@upstash.com). +- **Dynamic Client Registration.** Entra does not implement RFC 7591. Each approved MCP client must be pre-registered (or use a Microsoft first-party client ID) and pre-authorized on the APIM Gateway app's scope. +- **Group-based authorization at Context7.** Context7 resolves the `oid` claim to a user record and authorises against teamspace membership. Group-based policies inside Context7 (for example, restricting which Entra group can use which libraries) are not configured by this guide; reach out if your team needs that level of control. diff --git a/docs/enterprise/enterprise-managed-auth/okta.mdx b/docs/enterprise/enterprise-managed-auth/okta.mdx new file mode 100644 index 0000000..83c7c5d --- /dev/null +++ b/docs/enterprise/enterprise-managed-auth/okta.mdx @@ -0,0 +1,129 @@ +--- +title: "Enterprise-Managed Auth with Okta" +sidebarTitle: "Okta" +description: "Centrally authorize the Context7 MCP server for your organization through Okta Cross-App Access, so developers connect on first login with no per-user OAuth." +--- + +Enterprise-Managed Auth (EMA) lets your Okta administrators decide who can use the Context7 MCP server, in the same console where you manage every other app. Developers sign in once with their corporate Okta account and their MCP client is connected automatically. There is no per-user OAuth consent and no API keys to distribute. + +It implements the MCP [Enterprise-Managed Authorization](https://modelcontextprotocol.io/extensions/auth/enterprise-managed-authorization) extension: Okta issues a short-lived Identity Assertion (ID-JAG) for the user, Context7 validates it against your Okta tenant, and resolves the user to your teamspace by email. + + +Enterprise-Managed Auth currently works with **Claude Code** as the MCP client. + + + +Okta Cross-App Access (the productized ID-JAG flow) is an Early Access feature. Enable it from **Admin Console → Settings → Features** before you start. EMA also requires a Context7 enterprise teamspace. + + +## How it works + +- A developer signs in to their MCP client with your Okta org. +- The client asks Okta for an ID-JAG scoped to Context7. Okta applies your access policy (group, role, conditional access) and issues it only if the user is allowed. +- The client exchanges the ID-JAG with Context7 for an access token, then calls `mcp.context7.com`. +- Context7 validates the ID-JAG against your tenant and, on first sign-in, provisions the user as a teamspace member automatically (matched by email). + +Access is governed entirely in Okta. There is no user list to maintain in Context7: anyone your admin assigns to the connected app is provisioned on first sign-in. Removing them from the app blocks new sign-ins immediately, and any active session ends when its short-lived access token expires (within an hour). + +## Before you start + +- An **Okta org** with **Cross App Access** enabled. +- A **Context7 enterprise teamspace**. The Enterprise-Managed Auth settings appear only for enterprise plans. +- Developers assigned to the connected Okta app. They are provisioned into the teamspace automatically on first sign-in, so there is no manual user list to maintain. + +## Part 1: Configure Okta + +### Step 1: Enable Cross App Access + +In the **Admin Console**, go to **Settings → Features**, find **Cross App Access** under Early Access, and turn it on. + + + ![Cross App Access toggle in Okta Admin Console Settings → Features](/images/enterprise/enterprise-managed-auth/okta-enable-feature.png) + + +### Step 2: Add Context7 as a resource app + +Go to **Applications → Applications → Browse App Catalog**, search for **XAA Resource App**, and click **Add Integration**. + +- **Application label:** `Context7` +- **Issuer URL:** `https://context7.com` + +Click **Done**. + + + ![Add XAA Resource App general settings with Context7 label and issuer URL](/images/enterprise/enterprise-managed-auth/okta-resource-app.png) + + +### Step 3: Add your MCP client as a requesting app + +Browse the catalog again, search for **XAA Requesting App**, and click **Add Integration**. + +- **Application label:** a name for the MCP client (for example `MCP Client`) +- **Issuer URL:** `https://context7.com` +- **Client ID:** the client identifier the MCP client uses (for example `mcpclient-at-context7`) + +Click **Done**, then open the **Sign On** tab and note the Client ID and secret if your client needs them. + + + ![Add XAA Requesting App general settings with label, issuer URL, and client ID](/images/enterprise/enterprise-managed-auth/okta-requesting-app.png) + + +### Step 4: Connect the two apps + +Open the requesting app → **Manage Connections** tab. Under **Apps providing consent**, choose **Add resource apps**, select **Context7**, and **Save**. + + + ![Manage Connections tab linking the MCP Client to the Context7 resource app](/images/enterprise/enterprise-managed-auth/okta-manage-connections.png) + + +### Step 5: Assign your users + +On both apps, open the **Assignments** tab and assign the people (or groups) who should have access. Only assigned users can obtain an ID-JAG. + + + ![Assignments tab assigning a user to the app](/images/enterprise/enterprise-managed-auth/okta-assignments.png) + + +## Part 2: Configure Context7 + +Sign in to [context7.com/dashboard](https://context7.com/dashboard), select your enterprise teamspace, open the **Enterprise** tab, and select **Okta**. + +- **Identity provider issuer:** your Okta org issuer, for example `https://.okta.com`. +- **Scope** (optional): scopes to grant on the issued access token. Leave blank to pass through whatever Okta authorizes. + +Click **Configure**, enter the issuer, and **Save**. Context7 validates the issuer against your tenant's OpenID Connect metadata on save. + + + ![Context7 dashboard Enterprise-Managed Auth settings card with the Okta issuer field](/images/enterprise/enterprise-managed-auth/context7-ema-config.png) + + + +Use your **org** authorization server issuer (`https://.okta.com`), not a custom authorization server. Cross-App Access apps cannot use custom authorization servers. + + +## Part 3: How developers connect + +Enterprise-Managed Auth is wired on the **client** side by your organization, not per developer. The Okta sign-in isn't triggered by a server URL someone pastes. It happens because Claude Code is configured to use your enterprise IdP for managed connectors. + +Your admin connects the Okta org to Claude and enables the Context7 MCP server (`https://mcp.context7.com/mcp`) as a managed connector. After that, anyone using Claude Code with their corporate Okta identity gets Context7 automatically: Claude Code obtains an ID-JAG from Okta and exchanges it with Context7 for an access token. There is no token to paste and no per-user OAuth. + +See Claude's [Enterprise-Managed Auth](https://claude.com/blog/enterprise-managed-auth) documentation for the client-side admin setup. + +## Troubleshooting + +### `unauthorized_client` / "client cannot use a custom authorization server" + +The sign-in or token-exchange used a custom authorization server. Use the org authorization server endpoints (`https://.okta.com/oauth2/v1/...`). + +### A valid Okta user can't be provisioned + +Context7 provisions members from the `email` claim on the ID-JAG, so the connected app must request the `email` scope at sign-in (it's included in the setup above). If provisioning still fails, the teamspace may be at its member limit. + +### The user receives no token at all + +The user is not assigned to the connected apps in Okta, or the connection between the requesting and resource apps was not saved. Re-check Steps 4 and 5. + +## What this does not cover + +- **Identity providers other than Okta.** EMA currently supports Okta as the IdP. For Microsoft Entra, see [Microsoft Entra ID](/enterprise/enterprise-managed-auth/entra). +- **Group-based authorization inside Context7.** Okta decides who can obtain a token; Context7 authorizes against teamspace membership. Restricting which libraries a group can access is not configured here. diff --git a/docs/enterprise/gitops.mdx b/docs/enterprise/gitops.mdx new file mode 100644 index 0000000..64d147f --- /dev/null +++ b/docs/enterprise/gitops.mdx @@ -0,0 +1,148 @@ +--- +title: "GitOps" +sidebarTitle: "GitOps" +description: "Manage the list of indexed repositories declaratively from a Git repo and reconcile your on-premise instance to match it" +--- + +GitOps lets you keep the list of sources Context7 indexes in a Git repository, instead of adding them one by one in the dashboard. Alongside Git repositories, a source can be a Confluence space, a website, an llms.txt index, or an OpenAPI specification. Context7 reads a manifest file from that repo and reconciles its own state to match: it indexes anything new, re-indexes anything whose settings changed, and (optionally) removes anything you have deleted from the manifest. + +The point is to keep your configuration in code. After a disaster, or when standing up a second environment, you point a fresh instance at the manifest repository and the entire index rebuilds itself with no manual clicks. + + + ![The GitOps settings card under Settings, Indexing](/images/enterprise/gitops/gitops-settings.png) + + +## Before you start + +GitOps clones your manifest repository and the repositories it indexes using the Git credentials you configure under **Settings → Integrations**. Connect a GitHub App or a personal access token first; see [GitHub Integration](/enterprise/integrations/github). Automatic syncs on every push require the **GitHub App** (a personal access token cannot receive webhooks). + + +If you set up the GitHub App **before** GitOps was available, it is not subscribed to push events and will not trigger syncs. Add the **push** event to the App on GitHub, or recreate it from **Settings → Integrations**. See [GitHub Integration](/enterprise/integrations/github#webhooks). + + +## How it works + +You commit a manifest file (by default `repos.yaml`) to a Git repository. Context7 clones that repository using the same Git credentials you already configured under **Settings → Integrations** (a GitHub App or a personal access token), reads the manifest, and compares it against the repositories it currently has indexed. + +For each source in the manifest, Context7 decides what to do: + +- **Add** it if it is in the manifest but not yet indexed. +- **Re-index** it if its manifest entry changed, for example a different branch, new folder filters, or a changed page limit, or if its last indexing run did not finish. +- **Leave it untouched** if it already matches. Running a sync with no changes is a safe no-op. + +When pruning is enabled, repositories that you remove from the manifest are also deleted from the instance. Pruning only ever removes repositories that GitOps itself added; repositories you add by hand in the dashboard are never touched. + + +GitOps is the source of truth only for the repositories listed in the manifest. You can still add other repositories manually in the dashboard, and they will be left alone during a sync. + + +## The manifest file + +The manifest is a YAML file with a list of sources under `repos`. An optional `defaults` block applies to every entry unless an entry overrides it. + +An entry's `type` selects which parser handles it. Omit `type` and the entry is treated as a Git repository, so manifests written before multi-source support keep working unchanged. + +```yaml repos.yaml +defaults: + indexSourceCode: false + branch: "" # empty means the repository's default branch +repos: + # Git repository (the default when type is omitted) + - url: https://github.com/acme/payments + branch: main + folders: [docs] + excludeFolders: [node_modules] + + # Confluence space (uses the connection from Settings → Integrations) + - url: https://acme.atlassian.net/wiki + type: confluence + spaceKey: TEAM + + # llms.txt index + - url: https://docs.acme.com/llms.txt + type: llmstxt + + # Website crawl + - url: https://docs.acme.com/ + type: website + maxPages: 200 + + # OpenAPI specification + - url: https://petstore.swagger.io/v3/openapi.json + type: openapi +``` + +Every entry needs a `url` (or `repoUrl`). The remaining fields depend on `type`: + +| `type` | Fields | +| ------ | ------ | +| `git` (default) | `branch`, `folders`, `excludeFolders`, `excludeFiles`, `indexSourceCode` — the same options as the **Add Repository** form. | +| `confluence` | `spaceKey` (required), `spaceId` (Cloud only, resolved automatically from the key when omitted), `spaceName`, `title`, `description`. The whole space is indexed. | +| `website` | `maxPages`, `maxDepth`, `excludePatterns`, `title`, `description`. | +| `llmstxt` | `maxPages`, `title`, `description`. The URL must point to an `llms.txt`, `llms-full.txt`, or `llms-small.txt` file. | +| `openapi` | `title`, `description`. | + + +Confluence entries reuse the site URL and API token you set under **Settings → Integrations → Confluence**, so no credentials go in the manifest. Website, llms.txt, and OpenAPI sources are fetched over public HTTP and need no credentials. Configure Confluence before adding Confluence entries, or the sync reports those entries as failed. + + +The manifest is validated strictly: an unknown `type`, a field that does not belong to the entry's type (a common source of silent mistakes), or a missing required field rejects the **whole** sync. Nothing changes until the file parses cleanly, so a malformed manifest can never partially apply or wipe your index. + +## Configuring in the dashboard + +Open **Settings → Indexing → GitOps**, fill in the manifest repository, and save. + +| Setting | Description | +| ------- | ----------- | +| Enable GitOps sync | Turns on automatic reconciliation (on startup, on the schedule, and on push). When off, nothing syncs automatically, but you can still run a sync by hand. | +| Manifest repository URL | The Git repository that holds the manifest. | +| Manifest path | Path to the manifest within that repository. Defaults to `repos.yaml`. | +| Branch | Branch to read the manifest from. Leave blank for the default branch. | +| Sync schedule | How often to reconcile automatically. Choose a preset or enter a custom cron expression. Set to **Manual only** to disable scheduled syncs. | +| Prune removed repositories | Delete GitOps-managed repositories that are no longer in the manifest. Off by default. | + +The manifest repository is cloned with the Git token from **Settings → Integrations**, so private repositories work without any extra credentials. If you have not configured a GitHub App or personal access token for the host, the sync reports a clear error. + + +Pruning permanently deletes a repository's indexed data (snippets and embeddings). It only affects repositories GitOps added, never ones you created in the dashboard, but treat the manifest as authoritative once pruning is on. Removing an entry and syncing will delete that library. + + +## When syncs happen + +A reconcile runs in four situations: + +- **On startup.** When the instance boots with GitOps enabled, it reconciles immediately. This is what makes disaster recovery a single step: bring up a fresh instance pointed at the manifest repo and the index rebuilds itself. +- **On a schedule.** The cron schedule you set acts as a steady fallback that keeps the instance in line with the manifest. +- **On push (webhook).** If the manifest repository is on a connected GitHub App, every push triggers an immediate sync. See [Webhooks](#webhooks) below. +- **On demand.** Click **Sync now** in the dashboard, or call the API, to reconcile right away. + +Repeated syncs are cheap. Context7 remembers the last commit it processed and skips the work entirely when nothing has changed, and it only re-indexes a repository when its manifest entry actually differs. + +## Webhooks + +When the manifest repository is served by the [GitHub App](/enterprise/integrations/github), every push to its configured branch triggers an immediate sync, with no CI step required. Pushes to other repositories or other branches are ignored. + +Webhook delivery requires the GitHub App, an instance reachable from GitHub, and the App subscribed to push events. See [GitHub Integration](/enterprise/integrations/github#webhooks) for setup, including what to do if you connected the App before push support existed. With a personal access token instead of the App, webhooks are unavailable; use the sync schedule or have CI call the reconcile endpoint. + +## Disaster recovery + +Because the repository list lives in Git, rebuilding an instance does not require restoring it from a backup. Stand up a fresh Context7 instance, configure your LLM and Git credentials, enable GitOps with the manifest repository URL, and start it. On boot it reads the manifest and re-indexes every listed repository. Your configuration is reproducible from code. + +## API + +The same operations are available over the REST API and require an admin [API key](/enterprise/api/authentication). + +``` +GET /api/gitops/status # current configuration and the last sync result +PUT /api/gitops/config # update the configuration +POST /api/gitops/reconcile # run a sync now +``` + +To propagate a manifest change from CI immediately (for example when you are not using a GitHub App), call the reconcile endpoint after merging: + +```bash +curl -X POST http://localhost:3000/api/gitops/reconcile \ + -H "Authorization: Bearer " +``` + +The response reports what the sync did, including how many repositories were created, updated, left unchanged, pruned, and skipped. diff --git a/docs/enterprise/integrations/confluence.mdx b/docs/enterprise/integrations/confluence.mdx new file mode 100644 index 0000000..f8edeb9 --- /dev/null +++ b/docs/enterprise/integrations/confluence.mdx @@ -0,0 +1,84 @@ +--- +title: "Confluence Integration" +sidebarTitle: "Confluence" +description: "Index Confluence spaces from Atlassian Cloud or a self-hosted Data Center instance" +--- + +Context7 can index the pages of a Confluence space and serve them like any other library. It works with **Atlassian Cloud** and with self-hosted **Data Center / Server**. + +An admin connects Confluence once under **Settings → Integrations** using an API token. After that, anyone who can add libraries picks a space and pages from **Add → Confluence**. There is no OAuth app to register, which keeps the setup self-contained on your own infrastructure. + + +Confluence pages are behind authentication, so Context7 reaches them with the token you configure. The token needs read access to the spaces you want to index. + + +## Connect Confluence + +Open **Settings → Integrations → Confluence**, choose your deployment, fill in the fields, and use **Test connection** to confirm before saving. + + + ![Confluence integration settings with the Data Center deployment selected](/images/enterprise/integrations/confluence-settings.png) + + + + + | Field | Value | + | ----- | ----- | + | Deployment | Cloud | + | Site URL | `https://your-company.atlassian.net` | + | Email | The account email that owns the token | + | API Token | Create one at [id.atlassian.com](https://id.atlassian.com/manage-profile/security/api-tokens) | + + Cloud uses the Confluence v2 REST API and authenticates with the email and API token together. + + + | Field | Value | + | ----- | ----- | + | Deployment | Data Center | + | Site URL | `https://confluence.your-company.com` (include the context path if your install uses one, for example `/confluence`) | + | Email | Leave blank | + | Personal Access Token | Create one in Confluence under your profile, **Personal Access Tokens** | + + Data Center uses the v1 REST API and authenticates with a Personal Access Token. Personal Access Tokens require Confluence 7.9 or later. If your instance uses basic auth instead, put the username in the Email field and the password in the token field. + + + + +Point Context7 at a service account rather than a personal login, so indexing does not depend on one person's access. + + +## Index a space + +Go to **Add** and choose **Confluence**. + + + ![The Add Libraries source picker with a Confluence tile](/images/enterprise/integrations/confluence-source.png) + + +Pick a space, then index the whole space or choose specific pages. Give the project a title and description if you want to override the auto-detected ones, then choose **Start Parsing**. + + + ![Selecting a Confluence space and pages, with the page tree and Start Parsing button](/images/enterprise/integrations/confluence-add.png) + + + + + Choose the space from the dropdown, or paste a space URL (for example `https://your-site.atlassian.net/wiki/spaces/TEAM`) into **Space URL** to select it directly — handy when the account can read many spaces. + + + Leave **Index the entire space** on to index everything, which is the fastest path and the right choice for large spaces. Turn it off to pick individual pages: the page tree mirrors the space hierarchy, so selecting a parent selects its children. Very large spaces load their pages in batches — use **Load more pages** to fetch the rest, and the search box to filter. + + + Context7 fetches the pages, converts them to Markdown (code blocks, tables, and callouts are preserved), and indexes them. The project appears under your libraries when it finishes. + + + + +Indexing the entire space means a later refresh also picks up pages added since. Selecting a specific subset pins the project to exactly those pages. + + +You can also index Confluence spaces declaratively with [GitOps](/enterprise/gitops) — add a `type: confluence` entry with a `spaceKey` to your manifest, and it reuses this same connection. + +## Refresh and delete + +A Confluence project behaves like any other library. **Refresh** re-indexes the space using the stored selection and the current admin token, so rotating the token in Settings updates future refreshes without editing the project. **Delete** removes the project and its indexed content. diff --git a/docs/enterprise/integrations/github.mdx b/docs/enterprise/integrations/github.mdx new file mode 100644 index 0000000..7be108b --- /dev/null +++ b/docs/enterprise/integrations/github.mdx @@ -0,0 +1,107 @@ +--- +title: "GitHub Integration" +sidebarTitle: "GitHub" +description: "Connect Context7 to GitHub with a GitHub App or a personal access token for private repository access and push webhooks" +--- + +Context7 needs access to your GitHub repositories to clone and index them. You can connect GitHub in two ways: a **GitHub App** (recommended) or a **personal access token**. The GitHub App additionally delivers push webhooks, which power push-triggered [GitOps](/enterprise/gitops) syncs. + +Both are configured under **Settings → Integrations**. + + +Running GitHub Enterprise Server instead of github.com? Point Context7 at your server first. See [GitHub Enterprise Server](#github-enterprise-server). + + +## GitHub App + +The GitHub App is the recommended option. It gives Context7 fine-grained access to only the repositories you select, rotates short-lived access tokens automatically, and delivers webhooks for push-triggered GitOps syncs. + +Connecting the App is two steps: first create the App, then install it on your repositories. + + + + Go to **Settings → Integrations** and choose **Set up GitHub App**. Context7 generates a pre-filled App manifest and sends you to GitHub to create the App in one click. You are redirected back and Context7 stores everything it needs automatically: the App ID, private key, client ID and secret, and the webhook secret. + + + After it is created, install the App on the account or organization that owns your repositories, and grant it access to the repositories you want to index (including your GitOps manifest repository, if you use GitOps). + + + +Once both steps are done, the GitHub App card shows the connected App and its installation: + + + ![Connected GitHub App with one installation under Settings, Integrations](/images/enterprise/integrations/github-app.png) + + +### Verify the App configuration + +The setup flow configures everything below automatically, so a newly created App is ready to use. Use this section to confirm the App, or to fix an App you connected before GitOps existed (it will be missing the push event; see [Webhooks](#webhooks)). Open the App at `github.com/settings/apps`. + +| Setting | Required value | +| ------- | -------------- | +| Repository permission: Contents | Read-only | +| Repository permission: Metadata | Read-only (mandatory) | +| Subscribed events | Push | +| Webhook | Active | +| Webhook URL | `https:///api/github/webhook` | +| Webhook secret | Set | +| Callback URL | `https:///api/github/callback` | +| Setup URL | `https:///api/github/setup` | + +Under **Permissions & events**, the repository permissions are granted and the **Push** event is subscribed: + + + ![GitHub App repository permissions and the subscribed Push event](/images/enterprise/integrations/github-permissions.png) + + +Under **Webhook**, it is active and points at your instance with a secret configured: + + + ![GitHub App webhook settings: active, webhook URL, and a configured secret](/images/enterprise/integrations/github-webhook.png) + + +## Personal access token + +As a simpler alternative, add a GitHub personal access token under **Settings → Integrations**. Use a token with the `repo` scope for private repository access. + + + ![Git token fields under Settings, Integrations](/images/enterprise/integrations/git-tokens.png) + + +A personal access token can clone and index repositories, but it **cannot receive webhooks**. With a token only, push-triggered GitOps syncs are unavailable; use the GitOps sync schedule or trigger syncs from CI instead. + +## GitHub Enterprise Server + +Context7 works with GitHub Enterprise Server, not only github.com. Set your server host **before** you create the GitHub App or add a token, so the App is created on your own server instead of github.com. + + + + Open **Settings → Integrations → Git Tokens** and select **Using GitHub Enterprise?**. Enter your server host, for example `github.your-company.com` (no `https://`), then choose **Save & Apply**. + + + ![Git Tokens section with the Using GitHub Enterprise option under Settings, Integrations](/images/enterprise/integrations/git-tokens.png) + + + + Now follow [GitHub App](#github-app) or [Personal access token](#personal-access-token) above. The App manifest, installation, sign-in, and all API calls target your server. Before you create the App, the GitHub App card shows the server it will use, so you can confirm it is not github.com. + + + +For this to work, Context7 must reach your server's API at `https:///api/v3`, and your server must reach Context7 at its webhook URL for push delivery. + + +Prefer to set this at deploy time, for example as part of a disaster recovery rebuild? Set the `GITHUB_URL` environment variable to your server URL, such as `https://github.your-company.com`. A host saved in the UI takes precedence over the environment variable when both are set. + + +## Webhooks + +When the GitHub App is connected, GitHub delivers `push` events to `https:///api/github/webhook`. Context7 verifies each delivery's signature against the App's webhook secret and uses pushes to drive [GitOps](/enterprise/gitops) reconciliation: a push to a GitOps manifest repository triggers an immediate sync. + +For delivery to work: + +- Your instance must be **reachable from GitHub** at the webhook URL. An instance behind a firewall that GitHub cannot reach will not receive webhooks. +- The App must be **subscribed to push events** (new App setups are configured this way automatically). + + +GitHub Apps created before push support was added are not subscribed to any events, so they do not deliver webhooks. If you set up the App earlier, open it on GitHub and add the **push** event under its event subscriptions, confirm its webhook URL is `https:///api/github/webhook`, or recreate the App from **Settings → Integrations**. + diff --git a/docs/enterprise/library-import.mdx b/docs/enterprise/library-import.mdx new file mode 100644 index 0000000..0c4169f --- /dev/null +++ b/docs/enterprise/library-import.mdx @@ -0,0 +1,183 @@ +--- +title: "Library Import" +sidebarTitle: "Library Import" +description: "Move library content from Context7 Cloud into an airgapped on-premise install" +--- + +Airgapped on-premise installs can't reach Context7 Cloud, but you may still want the content of public libraries that the cloud already indexes. Library Import lets you select those libraries in the cloud dashboard, download them as a single file, and import that file into your on-premise install. + +This feature is available only to customers with an **offline (airgapped) license**. Installs running an online license fetch public library content from the cloud directly and don't need it. + +## How It Works + +The export bundle carries only snippet content, not embeddings. Embeddings are tied to a specific embedding model, so they aren't portable between deployments. When you import, your on-premise install re-embeds the snippets with its own configured embedding provider. This means imported libraries match the rest of your index and stay fully searchable, with nothing but text crossing the airgap. + +```mermaid +flowchart LR + subgraph cloud["Context7 Cloud"] + direction TB + A["Select
libraries"] --> B["Download
.zip bundle"] + end + + subgraph onprem["On-Premise install"] + direction TB + C["Upload
and import"] --> D["Re-embed
locally"] --> E["Searchable
library"] + end + + B -. "transfer
across airgap" .-> C + + classDef cloud fill:#dbeafe,stroke:#3b82f6,color:#1e3a8a; + classDef step fill:#ede9fe,stroke:#8b5cf6,color:#5b21b6; + classDef done fill:#dcfce7,stroke:#16a34a,color:#166534; + class A,B cloud; + class C,D step; + class E done; +``` + +## Before You Start + +- An **offline on-premise license**. The export page is only visible to accounts that hold one. +- Your on-premise **AI provider is configured** (Settings → completed setup wizard). Import re-embeds snippets, so it needs a working embedding provider. + +## Exporting from Context7 Cloud + + + + + +In the [Context7 Cloud dashboard](https://context7.com), open **More → Export Libraries**. The link only appears for accounts with an offline license. + + + ![Export Libraries link in the dashboard menu](/images/enterprise/library-import/export-menu.png) + + + + + + +Search for libraries by name and click **Add** to put them in your selection. The selection persists while you keep searching, so you can collect libraries from several searches before downloading. Remove a library from the selection with the **x** on its chip. + +You can export up to 50 libraries at once. + + + ![Searching and selecting libraries to export](/images/enterprise/library-import/export-select.png) + + + + + + +Click **Download selected**. Context7 gathers every code and info snippet for the chosen libraries and produces a single `context7-libraries.zip` file. + + + + + +## Importing on Your On-Premise Install + + + + + +Move `context7-libraries.zip` into your airgapped environment using whatever method your security policy allows. + + + + + +In your on-premise dashboard, click **Add Repo**, then choose the **Context7 Export** source. This source only appears on offline-license installs. + + + ![Context7 Export source on the Add page](/images/enterprise/library-import/import-source.png) + + + + + + +Select your `.zip` export (up to 100 MB). To replace libraries that already exist on this install, enable **Overwrite existing libraries**. Click **Import**. + + + ![Uploading a Context7 export to import](/images/enterprise/library-import/import-upload.png) + + +Each library is queued as its own job. Follow progress under the **Parse Queue** tab while snippets are re-embedded locally. + + + + + +## After Import + +Imported libraries appear in your Repositories list with an **Imported** badge and are queryable like any other library. + + + ![Imported badge on a library in the Repositories list](/images/enterprise/library-import/imported-badge.png) + + +Because your install didn't parse these libraries from source, it can't refresh them. The Refresh action is disabled for imported libraries. To update one, export a fresh bundle from Context7 Cloud and import it again with **Overwrite existing libraries** enabled. + + +Re-importing a library you already have does nothing unless **Overwrite existing libraries** is checked. The import skips libraries that already exist and tells you which ones it skipped. + + +## Automating with the API + +Besides the dashboard flow, both sides expose an API so you can script imports. For example, you can sync a fixed set of libraries into on-premise on a schedule from a bridge host that can reach both networks. + + + + + +Call the cloud export endpoint with your **enterprise license key** in the `Authorization` header. It returns one library's full content (every code and info snippet, without embeddings), already shaped for the import endpoint. + +```bash +curl -X POST https://context7.com/api/v1/enterprise/export \ + -H "Authorization: Bearer YOUR_LICENSE_KEY" \ + -H "Content-Type: application/json" \ + -d '{"library":"vercel/next.js"}' +``` + +Only public libraries can be exported this way. + + + + + +Post that JSON to your install's [import endpoint](/enterprise/api/parse/import-libraries), authenticated with a [personal API key](/enterprise/api/authentication#creating-an-api-key). The body is `{ "libraries": [...], "force": false }`, which is exactly the export response shape. + +```bash +curl -X POST https://your-instance.example.com/api/import-libraries \ + -H "Authorization: Bearer YOUR_API_KEY" \ + -H "Content-Type: application/json" \ + --data @library.json +``` + + + + + +From a host that can reach both networks, such as a bridge or import gateway, the two calls chain directly: + +```bash +curl -sf -X POST https://context7.com/api/v1/enterprise/export \ + -H "Authorization: Bearer YOUR_LICENSE_KEY" \ + -H "Content-Type: application/json" \ + -d '{"library":"vercel/next.js"}' \ +| curl -X POST https://your-instance.example.com/api/import-libraries \ + -H "Authorization: Bearer YOUR_API_KEY" \ + -H "Content-Type: application/json" \ + --data-binary @- +``` + +For a strictly airgapped install, save the export response to a file, transfer it the same way you would the `.zip`, then import it. The import endpoint also accepts the dashboard `.zip` bundle as a `multipart/form-data` upload (field `bundleFile`). See the [endpoint reference](/enterprise/api/parse/import-libraries) for details. + + +The import endpoint is available only on offline-license installs, the same gate as the dashboard flow. A library that already exists is skipped unless you overwrite it with `force`, either as a `?force=true` query param (handy when piping the export straight through) or a `"force": true` field in a JSON body. The response lists what it queued and skipped. + + +## Limits + +- Up to 50 libraries per export. +- Export files up to 100 MB per import. +- Only public libraries indexed by Context7 Cloud can be exported. diff --git a/docs/enterprise/on-premise.mdx b/docs/enterprise/on-premise.mdx new file mode 100644 index 0000000..6ce04cd --- /dev/null +++ b/docs/enterprise/on-premise.mdx @@ -0,0 +1,229 @@ +--- +title: "On-Premise Deployment" +sidebarTitle: "Getting Started" +description: "Run the full Context7 stack inside your own infrastructure, so code and documentation never leave your environment" +--- + +Context7 On-Premise lets you run the full Context7 stack inside your own infrastructure. Your code, documentation, and embeddings never leave your environment. + +## What's Included + +- Full Context7 parsing and indexing pipeline +- Local vector storage (no external vector DB required) +- Built-in MCP server. Works with any MCP-compatible AI client +- Web UI for managing indexed libraries and configuration +- REST API compatible with the public Context7 API +- Private GitHub and GitLab repository ingestion + + + ![On-Premise Architecture](/images/on-premise-architecture.png) + + +## Setup + + + + + +Go to [context7.com/plans](https://context7.com/plans) and click **On-Premise Trial**. Fill out the request form. No credit card required. You'll receive a 30-day full-featured license key via email once approved. + + + + + +Follow the deployment guide for your platform: + + + + Deploy with Docker Compose + + + Deploy on Kubernetes with raw manifests + + + + + + + +Open `http://localhost:3000` in your browser. On first launch, the setup wizard guides you through configuring: + +1. **AI Provider** - Choose OpenAI, Anthropic, Gemini, or a custom OpenAI-compatible endpoint. Enter your API key and model name. +2. **Embedding Provider** - Use the same provider as your LLM, or configure a separate one for embeddings. +3. **Git Tokens** - Add a GitHub and/or GitLab token for the platforms you use. + +All configuration is stored locally in the embedded database and can be updated later from the Settings page. + + + + + +From the dashboard, click **Add Repository** and enter a GitHub or GitLab URL. Once ingestion completes, your private docs are ready to query. + +You can also add libraries via the REST API: + +```bash +curl -X POST http://localhost:3000/api/parse \ + -H "Content-Type: application/json" \ + -d '{"url": "https://github.com/your-org/your-repo"}' +``` + + + + + +## Connecting Your AI Client + +Point your MCP client at your deployment URL. Replace `https://context7.internal.yourcompany.com` with your actual host. + +### Claude Code + +```bash +claude mcp add --scope user --transport http context7 https://context7.internal.yourcompany.com/mcp +``` + +### Cursor + +Add to `~/.cursor/mcp.json`: + +```json +{ + "mcpServers": { + "context7": { + "url": "https://context7.internal.yourcompany.com/mcp" + } + } +} +``` + +### Opencode + +```json +{ + "mcp": { + "context7": { + "type": "remote", + "url": "https://context7.internal.yourcompany.com/mcp", + "enabled": true + } + } +} +``` + +For other clients, see [All Clients](/resources/all-clients). + +## Configuration + +### Environment Variables + +These are set in your `docker-compose.yml` or `.env` file before starting the container. + +| Variable | Required | Description | +|---|---|---| +| `LICENSE_KEY` | Yes | License key issued by Upstash | +| `PORT` | No | HTTP port (default: `3000`) | +| `DATA_DIR` | No | Data directory inside the container (default: `/data`) | + + +AI provider keys, model settings, and git tokens are **not** set via environment variables. They are configured through the setup wizard and can be updated anytime from the Settings page in the web UI. + + +### AI Provider Settings + +Configured via the **Settings** page in the web UI. + +| Setting | Description | +|---|---| +| LLM Provider | `openai`, `anthropic`, `gemini`, or custom | +| LLM API Key | API key for your chosen provider | +| LLM Model | Model name (e.g. `gpt-4o`, `claude-sonnet-4-5`, `gemini-2.5-flash`) | +| LLM Base URL | Custom OpenAI-compatible endpoint (for local models or proxies) | + +#### Examples + + + + ``` + Provider: custom + Base URL: https://openrouter.ai/api/v1 + Model: openai/gpt-4o + API Key: sk-or-v1-... + ``` + + + ``` + Provider: custom + Base URL: http://host.docker.internal:11434/v1 + Model: llama3.2 + API Key: ollama + ``` + + + +### Embedding Settings + +By default, Context7 uses the same provider as your LLM for generating embeddings. You can configure a separate embedding provider if needed. + +| Setting | Description | +|---|---| +| Embedding Provider | `openai` or `gemini` | +| Embedding API Key | Separate API key for embeddings (falls back to LLM API key) | +| Embedding Model | Embedding model name (e.g. `text-embedding-3-small`) | +| Embedding Base URL | Custom embedding endpoint | + +### Git Access Tokens + +Configured via the **Settings** page in the web UI. + +| Setting | Description | +|---|---| +| GitHub Token | GitHub Personal Access Token. Required for GitHub repositories | +| GitLab Token | GitLab token. Required for GitLab repositories | + +You only need tokens for the platforms you use. If you only parse GitLab repos, you don't need a GitHub token, and vice versa. Create tokens with `repo` scope (GitHub) or `read_repository` scope (GitLab) for private repository access. + +## Access Control + +Admin credentials are set during first login (default: `admin` / `admin`). Change these immediately after setup via **Settings > Change Credentials**. + +The Settings page lets you control which operations are available without authentication. + +| Permission | Default | Description | +|---|---|---| +| Allow anonymous parse | Off | Allow unauthenticated users to trigger parsing | +| Allow anonymous refresh | Off | Allow unauthenticated users to refresh libraries | +| Allow anonymous delete | Off | Allow unauthenticated users to delete libraries | +| Allow anonymous support bundle | Off | Allow unauthenticated support bundle downloads | + +When a permission is off, the operation requires admin login. The MCP endpoint and search API are always publicly accessible. + +## Policies + +Policies let you control which public documentation from the Context7 cloud is accessible to your on-premise instance. They do not affect locally parsed on-premise content. + +Access Policies from **Settings > Policies** tab. Requires admin login and a valid `LICENSE_KEY`. + +For details on source type toggles and library filters, see [Customizing What Is Retrieved](/security/data-privacy#customizing-what-is-retrieved). + +## Web UI + +Open your deployment URL in a browser to access the dashboard. From here you can: + +- Add and remove libraries +- Trigger re-indexing +- Monitor parsing status and logs +- Update AI provider settings, git tokens, and permissions +- Configure policies for public cloud documentation access +- Test MCP connectivity +- Change admin credentials + +## Operations + +For updating, health checks, and other operational tasks, see the deployment guide for your platform: + +- [Docker Operations](/enterprise/deployment/docker#operations) +- [Kubernetes Operations](/enterprise/deployment/kubernetes#operations) + +## Support + +For license issues, upgrade requests, or deployment questions, contact [context7@upstash.com](mailto:context7@upstash.com). diff --git a/docs/enterprise/security/entra-sso.mdx b/docs/enterprise/security/entra-sso.mdx new file mode 100644 index 0000000..51eb704 --- /dev/null +++ b/docs/enterprise/security/entra-sso.mdx @@ -0,0 +1,239 @@ +--- +title: "Microsoft Entra ID (SSO)" +sidebarTitle: "Entra SSO" +description: "Let your teamspace sign in with Microsoft Entra ID instead of shared passwords." +--- + +Context7 On-Premise supports single sign-on with Microsoft Entra ID (formerly Azure AD). Once configured, anyone in your Entra tenant who is assigned one of the Context7 app roles can sign in to the dashboard with their work account, and Context7 creates a matching user record automatically on their first login. + +This guide walks through the full setup end-to-end: registering an application in Microsoft Entra, wiring it into Context7, and verifying a user can sign in. Plan for about 10 to 15 minutes for the Entra side and a minute or two on the Context7 side. + +## Before you start + +You'll need: + +- An **Entra admin** (or someone who can register applications in your tenant). +- A running Context7 On-Premise instance that you can reach in your browser. +- The Context7 admin password. This is the same account you use to open **Teamspace Settings** today. On a fresh install it is `admin` / `admin` until you change it. + + +Entra SSO is an **addition** to password login, not a replacement. The seeded admin account keeps working even after you turn on SSO, so you never get locked out if the Entra app goes sideways. + + +## Part 1: Register the application in Microsoft Entra + +### Step 1: Create a new app registration + +In the [Azure portal](https://portal.azure.com), open **Microsoft Entra ID** from the left sidebar. Expand **Manage** and click **App registrations**, then **+ New registration**. + +Fill in the form: + +- **Name**: `Context7` (anything memorable, your users won't see it) +- **Supported account types**: *Accounts in this organizational directory only* +- **Redirect URI**: pick **Web** from the dropdown and enter `https:///api/auth/entra/callback`. For a local test deployment that's usually `http://localhost:3000/api/auth/entra/callback`. + +Click **Register**. + + + ![Azure App registrations: New registration form](/images/enterprise/entra-sso/01-register-app.png) + + + +The redirect URI has to match *exactly* what Context7 sends later: same scheme (`http` vs `https`), same host, same port, same path. Microsoft compares byte-for-byte. + + +### Step 2: Copy the Application (client) ID and Directory (tenant) ID + +After registering, you land on the app's Overview page. Two values matter here: + +- **Application (client) ID** +- **Directory (tenant) ID** + +Copy both somewhere temporary. You'll paste them into Context7 later. + + + ![Azure app Overview showing client and tenant IDs](/images/enterprise/entra-sso/02-app-overview.png) + + + +These aren't secrets. The client ID is public information that's sent in every sign-in request; the tenant ID identifies your Entra directory. It's still good hygiene to treat them like configuration values rather than pasting them into public places. + + +### Step 3: Create a client secret + +From the app's left sidebar, open **Certificates & secrets**, stay on the **Client secrets** tab, then click **+ New client secret**. + +Give it a description (for example, `Context7 on-premise`), pick an expiry (180 days or 12 months are common), and click **Add**. + + + ![Client secrets tab with New client secret form](/images/enterprise/entra-sso/03-client-secret.png) + + + +The **Value** column is only shown once, right after you create the secret. Copy it immediately. If you navigate away before copying, you'll need to create a new secret and start over. + + +Copy the **Value**. This is what Context7 will use to authenticate itself when talking to Microsoft. Put it next to the client and tenant IDs you copied earlier. + +### Step 4: Define the two app roles + +Context7 maps Entra app roles to its own admin/member roles. You'll create one of each in the Entra app. + +From the left sidebar, click **App roles**, then **+ Create app role**. Fill in the first role: + +- **Display name**: `Context7 Admin` +- **Allowed member types**: *Users/Groups* +- **Value**: `Context7.Admin` +- **Description**: anything descriptive, like "Full admin access to the Context7 teamspace" +- Leave *Do you want to enable this app role?* checked. + +Click **Apply**. + +Repeat for the member role: + +- **Display name**: `Context7 Member` +- **Allowed member types**: *Users/Groups* +- **Value**: `Context7.Member` +- **Description**: "Standard member access" + + + ![App roles page showing Context7.Admin and Context7.Member](/images/enterprise/entra-sso/04-app-roles.png) + + + +The **Value** column is what ends up in the sign-in token's `roles` claim. Context7 defaults to looking for `Context7.Admin` and `Context7.Member`, but if your organization has a naming convention (for example, `CTX7_ADMIN`), you can use those values instead. Just remember what you chose so you can enter the same strings in Context7 later. + + +### Step 5: Require assignment and assign users + +By default, any user in your tenant can attempt to sign in to an Entra-registered app. You almost certainly want to restrict that to a known group of people. + +Go back to **Microsoft Entra ID → Enterprise applications** (a *different* section from App registrations, but the same app viewed differently). Find and click your **Context7** app, open **Properties**, set **Assignment required?** to **Yes**, and **Save**. + + + ![Enterprise app Properties page with Assignment required set to Yes](/images/enterprise/entra-sso/05-assignment-required.png) + + +Now open **Users and groups** on the same app and click **+ Add user/group**. For each person you want to grant access: + +1. Pick the user (or a group) under **Users**. +2. Pick a role: **Context7 Admin** for teamspace administrators, **Context7 Member** for everyone else. +3. Click **Assign**. + + + ![Assigning a user and selecting a role](/images/enterprise/entra-sso/06-assign-user-role.png) + + +At a minimum, assign yourself the **Context7 Admin** role so you can test the flow end-to-end. If you're rolling SSO out to a team, assign a second person as a **Context7 Member** for a realistic member-side sanity check. + +## Part 2: Configure Context7 + +### Step 1: Open the Entra SSO card + +Sign in to your Context7 dashboard with the password admin account. Open **Teamspace Settings**, and under **Authentication** you'll find a card titled **Microsoft Entra SSO**. + + + ![Context7 Teamspace Settings with the Microsoft Entra SSO card highlighted](/images/enterprise/entra-sso/07-context7-settings-card.png) + + +### Step 2: Fill in the credentials + +Paste the three values you copied from Azure into the form: + +- **Tenant ID** → the Directory (tenant) ID from the Azure Overview page +- **Client ID** → the Application (client) ID from the same page +- **Client Secret** → the secret *Value* from the Certificates & secrets page + +If your organization uses different role names from the defaults, update **Admin role value** and **Member role value** to match the strings you entered as **Value** when creating the app roles in Azure. + + +The **Callback URL** shown at the bottom of the card is exactly what Context7 will send to Microsoft during sign-in. If it doesn't match the redirect URI you registered in Step 1 of Part 1, go back to Azure → App registrations → Context7 → Authentication and fix it there. The copy button next to the URL makes it easy to paste into the Azure form verbatim. + + +### Step 3: Test the connection + +Before turning SSO on for your users, click **Test connection**. Context7 will make a server-to-server request to Microsoft using the credentials you entered. You'll see one of three results: + +- **Green banner**: credentials are valid. You're ready to flip the toggle on. +- **"Tenant ID is invalid"**: the Tenant ID doesn't match an Entra directory. Double-check you haven't pasted the Client ID into the Tenant field (an easy mistake, since both are GUIDs). +- **"Client ID was not found in this tenant"** or **"Client secret is invalid"**: recheck the values against the Azure Overview and Certificates & secrets pages. If the secret expired, generate a new one in Azure and paste the new value. + +### Step 4: Enable SSO + +Once the test passes, click the toggle at the top-right of the card, then **Save Microsoft Entra Settings** at the bottom. The status indicator should read **Configured · Sign-in button visible on /login**. + + + ![Entra SSO card with values filled, connection verified, and toggle on](/images/enterprise/entra-sso/08-filled-credentials.png) + + +## Part 3: Sign in + +Open `/login` in a new browser tab. Incognito is handy here because it guarantees you aren't reusing your existing admin session. You should see a **Continue with Microsoft Entra ID** button above the username/password form. + + + ![Login page showing Continue with Microsoft Entra ID button](/images/enterprise/entra-sso/10-login-page.png) + + +Click it. Microsoft handles the authentication. You may need to pick an account, consent to the app on first sign-in, or complete MFA depending on your tenant's policies. On success you're bounced back to Context7, a session cookie is set, and you're signed in. + +The first time each person signs in, Context7 creates a user record with the display name, email, and role sourced from their Entra account. On subsequent sign-ins, the existing record is updated with any changes to those fields (for example, if you reassign them from Member to Admin in Entra, the promotion takes effect on their next sign-in). + +## Managing roles after setup + +Role assignments live entirely in Entra. To change someone's access in Context7: + +- **Promote a member to admin**: in Entra, go to Enterprise applications → Context7 → Users and groups, remove their Member role, add the Admin role, and ask them to sign out and back in. +- **Revoke access**: remove the user from Users and groups in Entra. Existing browser sessions remain valid until they expire or sign out. If you need to cut them off immediately, restart Context7 (in-memory sessions are cleared on restart) or have an admin explicitly delete their user row from the teamspace. +- **Audit who signed in recently**: **Teamspace Settings → Users** shows every Context7 user with their auth provider and last-login timestamp. + + + ![Teamspace Users tab showing password and Entra users side by side](/images/enterprise/entra-sso/11-users-tab.png) + + +## Troubleshooting + +### `AADSTS50011: redirect URI mismatch` + +The redirect URI Context7 sent doesn't match any redirect URI registered on the Azure app. Open the app in Azure → **Authentication** and compare the list against the **Callback URL** shown on the Context7 SSO card. Check especially: + +- `http://` vs `https://` must match exactly. +- Port number: if you're running Context7 on a non-standard port, the Entra registration needs the same port. +- Path: must be `/api/auth/entra/callback` with no trailing characters. + +If you're running behind a reverse proxy, make sure it forwards the `Host` header unchanged; otherwise Context7 will build a callback URL for the internal host, not the public one your users see. + +### "This Microsoft Entra account is not assigned a supported Context7 app role" + +The user completed Microsoft sign-in but doesn't have either the Admin or Member app role assigned. Open Enterprise applications → Context7 → Users and groups, and verify they're listed with a role. If they are, confirm the role **Value** in the app registration matches the **Admin role value** / **Member role value** you entered in Context7 (they're case-sensitive). + +### "Microsoft sign-in session expired" + +This means the short-lived cookie Context7 uses to track the in-flight sign-in request was dropped or didn't come back. Most common causes: + +- The user started sign-in on one host (for example `localhost:3000`) and came back on a different one (`localhost:5173`). Stick to one host for the whole flow. +- A browser extension or strict privacy setting is blocking cookies. + +Have them retry in a clean browser window. + +### The Entra button doesn't appear on `/login` + +The card's status indicator tells you why: + +- **Not configured**: tenant ID, client ID, or client secret is missing. Fill them in and save. +- **Configured · Toggle on to show the sign-in button**: credentials are saved but the feature is off. Flip the toggle at the top of the card. + +### Client secret expired + +Entra rejects the test with `"Client secret has expired"` once the secret passes its expiry date. In Azure → Certificates & secrets, create a new secret and paste the new **Value** into the Context7 card. Then click **Test connection** to verify, and **Save**. + +## What this does *not* cover + +A few things that are out of scope for SSO itself but often come up when rolling it out: + +- **Personal MCP API keys**. Once a user signs in via Entra, they can create their own MCP API keys from **Personal Settings → API Keys**. Those are separate from SSO and covered in the main On-Premise guide. +- **Group-based role mapping**. Context7 reads app roles, not group membership. If your team assigns access via Entra security groups, add the group to Users and groups with one of the two Context7 roles. +- **SCIM provisioning**. Users are created lazily on first sign-in. There's no background sync pulling the whole directory. + +For help with Entra-side policies, conditional access, or MFA, work with your Entra admin. Those are tenant-wide concerns and Context7 respects whatever Microsoft returns at the end of the sign-in. + +If you run into something not covered above, contact [context7@upstash.com](mailto:context7@upstash.com) with the **Request Id** from any Microsoft error page and a screenshot of the Context7 SSO card's status indicator. diff --git a/docs/enterprise/security/oidc-sso.mdx b/docs/enterprise/security/oidc-sso.mdx new file mode 100644 index 0000000..b5c9b72 --- /dev/null +++ b/docs/enterprise/security/oidc-sso.mdx @@ -0,0 +1,172 @@ +--- +title: "OpenID Connect (OIDC) SSO" +sidebarTitle: "OIDC SSO" +description: "Let your team sign in with any OIDC-compatible identity provider instead of shared passwords." +--- + +Context7 On-Premise supports single sign-on with any provider that implements the OpenID Connect standard: Okta, Keycloak, Auth0, Ping Identity, on-premise LDAP-backed IdPs, and many others. Once you connect your provider, team members are redirected to your identity provider to authenticate, and Context7 creates or updates their user record automatically on each sign-in. + +The login flow uses the Authorization Code flow with PKCE, so no tokens are ever passed through the browser query string and no client secret is exposed to the frontend. + +## Before you start + +You will need: + +- Admin access to your identity provider so you can register a new application. +- A running Context7 On-Premise instance that you can reach in your browser. +- The Context7 admin password. On a fresh install it is `admin` / `admin` until you change it. + + +Only one SSO provider can be active at a time. If you already have Microsoft Entra ID configured, enabling OIDC will automatically disable Entra, and vice versa. + + +## Part 1: Register Context7 in your identity provider + +The exact steps depend on your provider, but the end result is the same in every case: you need a **client ID**, a **client secret**, and your provider's **issuer URL**. + +### What to configure in your IdP + +Create a new application or client in your identity provider and set the following: + +- **Application type**: Confidential (server-side) web application. +- **Allowed grant type**: Authorization Code. +- **Redirect URI / Callback URL**: `https:///api/auth/oidc/callback`. The exact URL is shown in the Context7 settings card once you open it, and there is a copy button next to it. + +If your provider supports PKCE (most modern ones do), leave it enabled. Context7 always sends a PKCE `code_challenge` regardless of whether the provider requires it. + +### Group claims (for role mapping) + +Context7 maps a group claim in the token to admin or member roles. Most providers let you include group membership in the ID token or expose it from the UserInfo endpoint. Either location works; Context7 checks both. + +In your IdP, configure the application to include the user's groups in the token. The default claim name Context7 looks for is `groups`. Common provider-specific steps: + +- **Okta**: add a Groups claim to the authorization server with a filter matching the groups you want to expose. +- **Keycloak**: enable the `groups` scope or add a Group Membership mapper to the client. +- **Auth0**: add a custom claim action that sets `groups` from the user's app metadata or roles. + +If your provider uses a different claim name, you can change what Context7 looks for in the **Groups claim** field in the settings card. + +## Part 2: Configure Context7 + + + + Sign in to your Context7 dashboard with the admin account. Open **Teamspace Settings**, scroll to the **Authentication** section, and click the **Single Sign-On** card. Select the **OIDC** tab. + + + ![Context7 Settings showing the Single Sign-On card with the OIDC tab selected](/images/enterprise/oidc-sso/02-sso-card-oidc.png) + + + + + Toggle **Enable OIDC** on, then fill in the fields: + + - **Button label**: the text shown on the sign-in button on the login page. Something like your company name or "Sign in with Acme" works well. + - **Issuer URL**: your provider's base URL. Context7 appends `/.well-known/openid-configuration` to discover endpoints automatically. For Okta this looks like `https://your-org.okta.com`, for Keycloak it is `https://keycloak.example.com/realms/your-realm`. + - **Client ID**: the client or application ID from your IdP registration. + - **Client Secret**: the secret generated by your IdP. Context7 stores this encrypted and never returns it to the browser after saving. + - **Scopes**: space-separated scopes to request. The default `openid profile email` works for most setups. Add `groups` or any custom scope your IdP requires to include group membership. + + The **Callback URL** at the bottom of the form is what you registered as the redirect URI in your IdP. If you need to update it, copy it with the button and paste it into your IdP's application settings. + + + + The **Group mapping** section controls which users get which role in Context7. + + + ![OIDC configuration card showing the Group mapping section](/images/enterprise/oidc-sso/03-group-mapping.png) + + + - **Groups claim**: the name of the claim in the token that contains the user's groups. Default is `groups`. + - **Admin group value**: the exact group name that maps to the Context7 admin role. Admins can open Teamspace Settings and manage other users. + - **Member group value**: the exact group name that maps to the member role. Members can use the workspace but cannot access settings. + + If you leave both group values blank, every authenticated user gets the member role automatically. This is useful when your IdP does not emit a groups claim and you want to allow any user from your organization in. + + + + Click **Test connection** before saving. Context7 fetches your provider's discovery document and confirms the required endpoints are present and reachable. A green banner means everything looks good. A red error usually means the issuer URL is wrong or the provider is not accessible from the Context7 server. + + + + Click **Save & Apply**. The status pill in the card header will change to **Live**. + + + +## Part 3: Sign in + +Open `/login` in a new browser window. You will see a **Continue with [your button label]** button at the top of the sign-in card. + + + ![Login page showing the SSO button and the optional password form below](/images/enterprise/oidc-sso/01-login-page.png) + + +Click it. You are redirected to your identity provider's login page. After authenticating there, your provider sends you back to Context7 with an authorization code. Context7 exchanges the code for tokens, validates the ID token signature and claims, and either creates a new user or updates the existing one. + +The first time someone signs in, Context7 creates a user record using their name, email, and role from the token claims. On subsequent sign-ins, the name, email, and role are refreshed from the latest token, so changes in your IdP take effect automatically on the next login. + +## Disabling password sign-in + +Once OIDC is live, you can turn off password-based sign-in entirely so that all users must authenticate through your IdP. + +Open the **Password sign-in** card directly below the SSO card and toggle it off. + + + ![Password sign-in card with the toggle in the Enabled state](/images/enterprise/oidc-sso/04-password-card.png) + + + +Disabling password sign-in means the default admin account and any manually created password users will no longer be able to sign in via the login form. Make sure at least one admin is mapped through OIDC before turning it off, so you do not lock yourself out. If you turn SSO off later, Context7 will automatically re-enable password sign-in as a safety measure. + + +## Managing users + +All users who have signed in appear in **Teamspace Settings → Users**, along with their authentication provider and last login time. + + + ![Teamspace Settings Users tab showing OIDC-provisioned users](/images/enterprise/oidc-sso/05-users-tab.png) + + +Roles are controlled by group membership in your IdP. To change someone's role, update their group assignment in your identity provider. The change takes effect on their next sign-in. + +To revoke access, remove the user from the relevant group in your IdP. Existing browser sessions remain valid until they expire naturally or the user signs out. If you need to cut access immediately, an admin can delete the user row from the Users tab in Teamspace Settings. + +## Troubleshooting + +### "OIDC SSO is not configured" + +The toggle is on but some required fields are missing or the config was not saved. Open the OIDC tab in the SSO card and check that Issuer URL, Client ID, and Client Secret are all filled in, then click **Save & Apply**. + +### Test connection fails + +The most common reasons are: + +- **Wrong issuer URL**: double-check it does not include a trailing slash and points to your realm root. For Keycloak, the format is `https://host/realms/realm-name`, not `https://host/auth/realms/realm-name` (the `/auth` prefix was removed in Keycloak 17). +- **Network access**: the Context7 server must be able to reach your IdP's HTTPS endpoint. If you are running air-gapped or on an internal network, confirm there is no firewall blocking outbound requests to your IdP from the server. + +### "This account is not assigned a supported Context7 group" + +The user authenticated successfully but their token did not contain either of the configured group values. Check that: + +1. The groups claim is included in the token from your IdP (use your IdP's token preview or decode the returned JWT at jwt.io). +2. The **Groups claim** field in Context7 matches the claim name exactly (case-sensitive). +3. The **Admin group value** or **Member group value** matches the group name exactly, including casing and spacing. + +### "Single sign-on session expired. Please try again." + +The short-lived cookie that tracks the in-progress sign-in was lost between the redirect to the IdP and the return. The most common causes are: + +- Starting the flow on one hostname and returning on a different one (for example, `localhost:3000` vs `localhost:5173`). +- A browser or proxy stripping the session cookie. +- Taking longer than 10 minutes to complete the IdP login, which is when the cookie expires. + +Having the user retry in a clean browser window usually resolves it. + +### Redirect URI mismatch + +If your IdP returns a redirect URI error, the callback URL you registered in the IdP does not exactly match what Context7 sends. Copy the **Callback URL** from the Context7 settings card using the copy button and paste it verbatim into your IdP's allowed redirect URIs. Pay attention to `http` vs `https` and the port number. + +If Context7 is behind a reverse proxy, make sure the proxy forwards the `Host` and `X-Forwarded-Proto` headers correctly so Context7 can build the right callback URL. + +--- + +For anything not covered here, contact [context7@upstash.com](mailto:context7@upstash.com). diff --git a/docs/howto/api-keys.mdx b/docs/howto/api-keys.mdx new file mode 100644 index 0000000..450a075 --- /dev/null +++ b/docs/howto/api-keys.mdx @@ -0,0 +1,50 @@ +--- +title: Manage API Keys +description: Create and manage API keys for Context7 authentication +--- + +API keys authenticate your requests to Context7's documentation services. + +## Managing API Keys + +![API Keys card showing list of keys with details](/images/dashboard/api-keys-card.png) + +### Creating API Keys + + + + Click **Create API Key** in the API Keys card. + + + Enter a name (optional but recommended). Descriptive names like "Cursor", "Claude", "VS Code", or "Devin Desktop" help you identify the key later. + + + Keys are shown only once for security. The format is `ctx7sk-**********************`. + + + Use it in your requests or MCP configuration: + + ```bash + curl "https://context7.com/api/v2/context?libraryId=/vercel/next.js&query=routing" \ + -H "Authorization: Bearer YOUR_API_KEY" + ``` + + + +Store your API key securely. You won't be able to see it again after creation. + +### Revoking Keys + + + + Click the delete button next to the key you no longer need. + + + Confirm in the modal. The key deactivates immediately — all requests using it will fail. + + + + + Revoking a key is permanent and cannot be undone. Update any applications using the key before + revoking. + diff --git a/docs/howto/chat-widget.mdx b/docs/howto/chat-widget.mdx new file mode 100644 index 0000000..4f4bbcc --- /dev/null +++ b/docs/howto/chat-widget.mdx @@ -0,0 +1,211 @@ +--- +title: Add the Chat Widget +description: Embed an AI-powered chat assistant on your documentation site +--- + +Add an AI chat widget to your documentation site so visitors can ask questions and get instant answers powered by your library's documentation on Context7. + +The widget is a lightweight JavaScript snippet that renders a floating chat button. When clicked, it opens a chat panel where users can ask questions about your library and receive AI-generated answers grounded in your documentation. + +The chat widget is available to library owners who have [claimed their library](/howto/claiming-libraries). + +![Chat widget panel showing AI-powered documentation assistant](/images/dashboard/chat-widget.png) + +## How It Works + +1. A visitor clicks the chat bubble on your site +2. They type a question about your library +3. The widget searches your library's documentation on Context7 +4. An AI model generates an answer using the relevant documentation +5. The response streams back in real time with markdown formatting + +## Setup + + + + You must be a verified owner of the library on Context7. If you haven't claimed it yet, follow the [Claim Your Library](/howto/claiming-libraries) guide. + + + + Navigate to your library's admin page: + + ``` + https://context7.com/{owner}/{repo}/admin + ``` + + Open the **Chat** tab and toggle **Widget enabled** on. + + + + Add the domains where the widget will be embedded. The widget will only work on domains you explicitly allow. + + Examples: + - `docs.example.com` — exact domain match + - `*.example.com` — matches all subdomains (e.g., `docs.example.com`, `blog.example.com`) + - `example.com` — matches the root domain only + + + The widget will not work on any external site until you add at least one allowed domain. + + + + + Click **Save** to persist your widget configuration. + + + + Copy the embed code from the admin panel and add it to your site's HTML: + + ```html + + ``` + + Place this tag in your root layout or HTML file so the widget loads on every page. The script loads asynchronously and does not block page rendering. + + + +## Adding with AI + +You can use an AI coding assistant to add the widget automatically. Copy the following prompt and paste it into Claude Code, Cursor, or any AI coding assistant. Replace `/owner/repo` with your library ID. The assistant will detect your framework and place the script tag in the correct location. + +``` +Add the Context7 chat widget to my documentation site. This is a lightweight +JavaScript widget that adds an AI-powered chat assistant to any webpage. It +loads asynchronously and renders a floating chat button. + +The widget is loaded via a script tag: + + +Detect which framework this project uses and add the widget accordingly. Place +it in the root layout or HTML file so it loads on every page. + +Optional attributes: data-color (hex color, default #059669), data-position +(bottom-right or bottom-left), data-placeholder (input placeholder text), +data-welcome-message (initial assistant message shown when the chat opens). +``` + +## Framework Examples + + + + Use the `next/script` component in your root layout so the widget loads on every page: + + ```tsx app/layout.tsx + import Script from "next/script"; + + export default function RootLayout({ children }) { + return ( + + + {children} + +``` + +**Custom placeholder text:** + +```html + +``` + +**Custom welcome message:** + +```html + +``` + +### Position Options + +| Value | Description | +| -------------- | --------------------------------- | +| `bottom-right` | Fixed to the bottom-right corner | +| `bottom-left` | Fixed to the bottom-left corner | + +## Domain Configuration + +### Allowed Domains + +You can configure up to **20 allowed domains** per library. The widget validates the requesting origin against this list on every chat request. + +| Pattern | Matches | +| ------------------ | --------------------------------------------------- | +| `docs.example.com` | Only `docs.example.com` | +| `*.example.com` | Any subdomain: `docs.example.com`, `blog.example.com`, and `example.com` itself | +| `example.com` | Only the root domain `example.com` | + + + Domain validation is enforced server-side. Requests from domains not in your allowed list are rejected with a 403 error. + + +### Adding and Removing Domains + +Manage domains from the **Chat** tab on your library's admin page: + +1. Click **Add domain** to add a new entry +2. Enter the domain (e.g., `docs.example.com` or `*.example.com`) +3. Click **Save** to apply changes + +To remove a domain, click the trash icon next to it and save. diff --git a/docs/howto/claiming-libraries.mdx b/docs/howto/claiming-libraries.mdx new file mode 100644 index 0000000..33bd5bf --- /dev/null +++ b/docs/howto/claiming-libraries.mdx @@ -0,0 +1,289 @@ +--- +title: Claim Your Library +description: Verify ownership and manage your library's configuration via the admin panel +--- + +As a library owner, you can claim your library on Context7 to unlock advanced configuration options through a web-based admin panel. This gives you full control over how your documentation is parsed and presented to developers. + +Library claiming is available for Git repositories, websites, and llms.txt sources. + +## Why Claim Your Library? + +Claiming ownership provides several benefits: + +- **Web-based configuration**: Edit settings through a user-friendly interface instead of committing changes +- **Teamspace management**: All project members can manage the library configuration +- **Version management**: Add and manage multiple versions of your library documentation +- **Usage analytics**: View metrics on how developers use your library's documentation +- **Higher refresh limits**: Get higher rate limits for refresh operations to better manage your content +- **Apply for verification**: Only owners can apply for the verified badge. [Learn more about verification](/howto/verification) + +## Claiming Process + + + + You can access the admin page in two ways: + + **From the Dashboard:** + Find your library in the dashboard and click the "Manage" button to open the admin configuration page. + + + Manage button on library card + + + **Via Direct URL:** + Go directly to your library's admin page at: + + ``` + https://context7.com/{owner}/{repo}/admin + ``` + + For example: `https://context7.com/vercel/next.js/admin` + + + + + If you haven't claimed the library yet, you'll see a "Claim Library" button in the header. Click it to open the claiming modal. + + + Claim Library button + + + + + + In the claiming modal, you'll see a generated `context7.json` configuration with your unique public key: + + + Claim library modal + + + The modal provides a JSON snippet like this: + + ```json + { + "url": "https://context7.com/vercel/next.js", + "public_key": "pk_abc123xyz..." + } + ``` + + Click "Copy" to copy the configuration to your clipboard. + + + + + + + Create a `context7.json` file in the **root** of your repository with the copied content: + + ```json + { + "url": "https://context7.com/vercel/next.js", + "public_key": "pk_abc123xyz..." + } + ``` + + + The `url` must exactly match your library's URL on Context7, and the `public_key` must match the key shown in the modal. + + + Commit and push the file to your repository's default branch. + + + Host the `context7.json` file anywhere under your library's base URL so it is publicly reachable. For example: + + ``` + https://docs.example.com/mylib/context7.json + ``` + + The file must contain the copied content: + + ```json + { + "url": "https://context7.com/websites/mylib", + "public_key": "pk_abc123xyz..." + } + ``` + + + The `url` must exactly match your library's URL on Context7, and the `public_key` must match the key shown in the modal. + + + Once the file is live, paste the full URL to your hosted `context7.json` into the input field shown in the modal. + + + + + + Click "Claim Library". Context7 will fetch your `context7.json`, verify the URL and public key, and grant you access to the admin panel. + + + +## Admin Panel Overview + +After claiming your library, the admin page shows a full configuration editor with five main tabs: + +- **Configuration**: Edit all library settings +- **Chat**: Embed an AI chat assistant on your documentation site +- **Benchmark**: Evaluation of the quality of your library's documentation +- **Metrics**: View usage statistics +- **Versions**: Manage different versions and tags of your library + +## Configuration Fields + +### Basic Information + +These fields are available for all library types. + +| Field | Description | Limits | +| ----------------- | --------------------------------------------------------------------------------------------------------- | ------------------ | +| **Project Title** | Display name for your library in Context7. Used when the LLM cannot generate a name with high confidence. | Max 100 characters | +| **Description** | Brief description of your library's purpose. | Max 500 characters | + +### Source Settings + + + + | Field | Description | Limits | + | ---------------------- | ----------------------------------------------------------------------------------------- | ------------------------------- | + | **Branch** | Git branch to parse. Leave empty for default branch. | Max 100 characters | + | **Folders to Include** | Specific folder paths to include when parsing. Leave empty to scan the entire repository. | Max 50 folders, 255 chars each | + | **Folders to Exclude** | Folder paths or patterns to exclude from parsing. Supports glob patterns. | Max 50 patterns, 255 chars each | + | **Files to Exclude** | Specific file names to exclude (filename only, not full path). | Max 100 files, 255 chars each | + + #### Exclusion Pattern Examples + + The exclusion fields support various pattern types: + + ``` + node_modules → Excludes any folder named "node_modules" anywhere + ./build → Excludes "build" only at repository root + **/dist → Excludes any "dist" folder anywhere (globstar) + docs/**/internal → Excludes "internal" folders under docs + *.test → Excludes folders ending with .test + ``` + + + `excludeFiles` only accepts filenames, not paths. Use `CHANGELOG.md` instead of + `docs/CHANGELOG.md`. + + + + | Field | Description | Limits | + | ---------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------- | + | **Base URL** | The root URL to crawl for documentation. | Max 100 characters | + | **Display URL** | Optional URL shown to users instead of the base URL. | Max 500 characters | + | **Keep Hash (URL Fragments)**| Whether to treat URLs with different hash fragments as distinct pages. Disabled by default. | Boolean | + | **Keep Query Parameters** | Whether to treat URLs with different query strings as distinct pages. Enabled by default. | Boolean | + | **Exclude URLs** | URL patterns to exclude from crawling. Supports wildcards. | Max 100 patterns | + + + +### AI Instructions + +| Field | Description | Limits | +| ---------------- | ------------------------------------------------------------------------------- | ---------------------------- | +| **Custom Rules** | Best practices and guidelines for AI coding assistants when using your library. | Max 50 rules, 255 chars each | + +Example rules: + +- "Always use TypeScript for better type safety" +- "Import components from the main package, not internal paths" +- "Use environment variables for API keys, never hardcode them" + +### Advanced Settings + +Available for Git repositories and websites. + +| Field | Description | Limits | +| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| **Skip Automatic Version Detection** | By default, outdated library versions are automatically detected and excluded from indexing. Enable to include all versions regardless of age. | Boolean | +| **Redirect URL** | Redirect users to a different library. Leave empty to disable. | Max 500 characters | +| **Disallow Indexing** | Opt-out from Context7. When enabled, documentation content is removed and the library becomes inaccessible. | Boolean | + +## Managing Versions + +The Versions tab lets you configure previous versions of your library that should be available in Context7. + + + Versions tab + + +You can add versions using either: + +- **Git tags**: Reference a specific release tag (e.g., `v1.2.0`) +- **Git branches**: Reference a branch for version-specific documentation (e.g., `release-1.x`) + +| Limit | Value | +| ---------------- | ----------------- | +| Maximum versions | 20 | +| Tag/branch name | Max 50 characters | + +## Library Metrics + +The Metrics tab provides insights into how developers are using your library through Context7. + + + Metrics tab + + +### Usage Statistics + +At the top of the metrics page, you'll see key usage numbers: + +| Metric | Description | +| ---------------------- | --------------------------------------------------------------------- | +| **Page Views** | Number of times your library page was viewed on Context7 | +| **API Requests (TXT)** | Documentation requests via the REST API | +| **MCP Requests** | Documentation requests via the MCP server (from AI coding assistants) | + +The metrics page also includes a usage chart showing trends over time, topic queries showing what developers ask about, and country distribution of requests. + +All team members can view library settings; owners and admins can edit them. See [Teamspace Management](/howto/teamspace) for role details. + +## Removing Ownership + + + + Navigate to your library's admin page at `https://context7.com/{owner}/{repo}/admin`. + + Click the ownership menu in the header area. + Select "Remove Ownership" and confirm the action. + + + + Removing ownership keeps the admin configuration intact. Another user can claim the library and + inherit the existing settings. + + +## Troubleshooting + +### "context7.json not found" + +Ensure the file is: + +- Named exactly `context7.json` (lowercase) +- Located in the repository root, not a subdirectory +- Committed and pushed to the default branch + +### "URL mismatch" + +The `url` field in your `context7.json` must exactly match: + +``` +https://context7.com/{owner}/{repo} +``` + +Check for typos, case sensitivity, and trailing slashes. + +### "Public key mismatch" + +The `public_key` in your file must match the key shown in the claiming modal. Copy the entire key including the `pk_` prefix. + +### Changes not appearing + +After saving configuration changes, you may need to: + +- Manually trigger a refresh from the library page +- Clear any cached documentation on your end + diff --git a/docs/howto/oauth.mdx b/docs/howto/oauth.mdx new file mode 100644 index 0000000..1fa6ce5 --- /dev/null +++ b/docs/howto/oauth.mdx @@ -0,0 +1,43 @@ +--- +title: Set Up OAuth +description: Authenticate with Context7 MCP server using OAuth 2.0 +--- + + + OAuth is only available for remote HTTP connections. For local MCP connections using stdio + transport, use [API key authentication](/howto/api-keys) instead. + + +Context7 MCP server supports OAuth 2.0 authentication for MCP clients that implement the [MCP OAuth specification](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization). + +## Why Use OAuth? + +| Feature | OAuth | API Keys | +| -------------------------- | ----- | -------- | +| No manual key management | ✅ | ❌ | +| Automatic token refresh | ✅ | ❌ | +| Works with stdio transport | ❌ | ✅ | + +## Configuration + +To use OAuth, change the endpoint from `/mcp` to `/mcp/oauth` in your client configuration: + +```diff +- "url": "https://mcp.context7.com/mcp" ++ "url": "https://mcp.context7.com/mcp/oauth" +``` + +## How It Works + +1. Your MCP client connects to the OAuth endpoint +2. You're redirected to Context7 to sign in +3. After signing in, you're redirected back to your client +4. Your client automatically handles token refresh + + +**Authentication required after setup.** Most clients won't authenticate automatically. After adding the OAuth endpoint, you'll need to explicitly authenticate through your client's MCP settings. For example, in Claude Code run `/mcp`, select the server, and choose "Authenticate". + + +## Client Support + +OAuth authentication requires your MCP client to support the [MCP OAuth specification](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization). If your client doesn't support OAuth, use [API key authentication](/howto/api-keys) instead. diff --git a/docs/howto/policies.mdx b/docs/howto/policies.mdx new file mode 100644 index 0000000..6daf4ec --- /dev/null +++ b/docs/howto/policies.mdx @@ -0,0 +1,62 @@ +--- +title: Manage Policies +description: Control which sources and libraries your teamspace can access +--- + +Policies let you control exactly which documentation your teamspace can pull from Context7. Configure them from the [policies tab](https://context7.com/dashboard?tab=policies) of your dashboard, or programmatically through the [Policies API](/api-reference/policies/get-teamspace-policies). + +Every search and MCP request made with one of the teamspace's API keys is filtered through these policies, so they apply to all members at once. + +Policies are scoped to a teamspace. Only owners and admins can change them; developers have read-only access. + +## Source Type Access + +The **Source Type Access** card toggles entire categories of sources on or off. Disabling a type removes all of its content from results for the whole teamspace. + +| Group | Source Type | What it covers | +| ----------------- | ------------------ | --------------------------------------- | +| Public Sources | Public Repositories | Public GitHub repositories | +| Public Sources | Websites | Indexed documentation websites | +| Public Sources | LLMs.txt | `llms.txt` sources | +| Connected Sources | Confluence | Atlassian Confluence workspace pages | +| Connected Sources | Uploaded Files | Uploaded OpenAPI specs and PDFs | +| Connected Sources | Notion | Connected Notion pages | +| Connected Sources | Private Sources | Privately parsed repositories | + +## Library Filters + +The **Library Filters** card decides which public libraries are accessible. Choose one of two modes: + +### Filter by Quality + +Allow any public library that clears the quality bar you set. Available filters: + +| Filter | Options | +| ----------------- | ------------------------------------ | +| Verification | All · Verified Only | +| Trust score | All · Medium (4+) · High (7+) | +| Freshness | All · 30 days · 90 days · 1 year | +| Repo stars | All · 100+ · 1,000+ · 10,000+ | +| Website backlinks | All · 500+ · 2,500+ · 5,000+ | +| Referring domains | All · 100+ · 500+ · 1,000+ | +| Organic traffic | All · 100+ · 1,000+ · 10,000+ | + +You can also maintain two override lists in quality mode: + +- **Blocked libraries** — always excluded, even if they pass every filter. +- **Excepted libraries** — always allowed, even if they fail the filters. + +### Select Manually + +Ignore the quality bar entirely and grant access only to a hand-picked list of libraries. Anything not on the list is inaccessible. + +The card shows the number of libraries currently accessible under your settings, so you can see the impact before saving. + +## Managing Policies via API + +The same configuration is available over the REST API using a teamspace API key: + +- [Get Policies](/api-reference/policies/get-teamspace-policies) — `GET /api/v2/policies` returns the current configuration and accessible library count. +- [Update Policies](/api-reference/policies/update-teamspace-policies) — `PATCH /api/v2/policies` applies an incremental update; only the fields you include are changed. + +See the [API Guide](/api-guide) for request and response details. diff --git a/docs/howto/private-sources.mdx b/docs/howto/private-sources.mdx new file mode 100644 index 0000000..ba6f89a --- /dev/null +++ b/docs/howto/private-sources.mdx @@ -0,0 +1,97 @@ +--- +title: Add Private Sources +description: Add and manage private source documentation +--- + +Add private sources to Context7 to make your internal documentation available to AI coding assistants. You can add sources from GitHub, GitLab, Bitbucket, other Git providers, Confluence, and OpenAPI specifications. + +![Private Sources card showing a table of added sources and source type options](/images/dashboard/private-sources-card.png) + +## Adding Private Sources + + + + Go to your teamspace's **Sources** tab. + + + Click **Add another** to open the source type selector. + + + - **GitHub** — connect your GitHub account and select a repository + - **GitLab** — connect your GitLab account and select a project + - **Bitbucket** — connect your Bitbucket account and select a repository + - **Other Git** — add any Git repository by URL + - **Confluence** — connect your Confluence workspace + - **OpenAPI** — add an OpenAPI specification + + + Authorize Context7 to access your source (if required). + + + For repositories with little or no written documentation, check **Generate docs** to have Context7 generate documentation from the source code. Also available as the `generateDocs` flag in the [API](/api-guide). + + + Submit the source for parsing. + + + +You must have a Pro or Enterprise plan to add private sources. Public sources can be added from the [Add Library](https://context7.com/add-library) page. + +## Source Management + +### Refreshing Documentation + +Keep your private documentation up to date: + +1. **Click the refresh icon** next to the source +2. Context7 re-parses the source +3. **You're only charged for changed content** — cached pages are free + +**When to refresh**: + +- After major documentation updates +- After releasing new features +- When you notice outdated information + +Refresh private sources only after significant documentation changes to minimize costs. + +### Removing Sources + + + + Click the trash icon next to the source. + + + Confirm in the modal. The source documentation becomes unavailable immediately. + + + + + This action is permanent. The source will no longer be accessible via the API. + + +## Permissions + +Access to private source management is restricted by role. Only Owners and Admins can add, refresh, or remove private sources. Developers can view source documentation but cannot manage sources. + +See [Teamspace Management](/howto/teamspace#roles) for the complete permissions table. + +## Configuration + +### Using `context7.json` + +Add a `context7.json` file to your repository root for better control over parsing: + +```json +{ + "$schema": "https://context7.com/schema/context7.json", + "projectTitle": "Your Project Name", + "description": "Brief description of your project", + "folders": ["docs", "guides"], + "excludeFolders": ["tests", "dist", "node_modules"], + "excludeFiles": ["CHANGELOG.md"], + "rules": ["Always validate user input", "Use TypeScript strict mode"] +} +``` + +See the [Library Owners](/library-owners) page for complete configuration options. diff --git a/docs/howto/rules.mdx b/docs/howto/rules.mdx new file mode 100644 index 0000000..e8d360d --- /dev/null +++ b/docs/howto/rules.mdx @@ -0,0 +1,42 @@ +--- +title: Manage Rules +description: Prepend custom guidelines to the documentation your teamspace retrieves +--- + +Rules are custom instructions that are automatically prepended to the documentation context whenever your teamspace retrieves library docs. Use them to set coding standards, define architectural patterns, or specify framework preferences so every result follows your team's conventions. + +Manage them from the [rules tab](https://context7.com/dashboard?tab=rules) of your dashboard. + +Teamspace Rules are a Pro and Enterprise feature. Only owners and admins can add, edit, or delete rules; developers have read-only access. + +## Rule Scopes + +Each rule applies at one of two scopes: + +- **Global Rules** — apply to every library your teamspace accesses. +- **Library-Specific Rules** — apply only when retrieving docs for a particular library. + +## Examples + +- "Always use TypeScript strict mode" +- "Prefer server components in Next.js" +- "Use the App Router, not the Pages Router" + +## Adding a Rule + + + + Open the [rules tab](https://context7.com/dashboard?tab=rules) and click **Add Rule...**. + + + Pick **Global** or a specific **Library**. + + + Write the instruction you want prepended to retrieved documentation. + + + Save the rule. It takes effect on the next documentation request made with the teamspace's API keys. + + + +Existing rules are grouped by scope in the list. Select **Global Rules** or any library entry to edit or remove its rules. diff --git a/docs/howto/teamspace.mdx b/docs/howto/teamspace.mdx new file mode 100644 index 0000000..a88abee --- /dev/null +++ b/docs/howto/teamspace.mdx @@ -0,0 +1,67 @@ +--- +title: Manage Your Teamspace +description: Invite members and manage teamspace permissions +--- + +Add team members, assign roles, and manage access to your Context7 dashboard from the [members tab](https://context7.com/dashboard?tab=members). + +![Members tab displaying team members list with owner, admins, and developers](/images/dashboard/members-tab.png) + +## Creating a Teamspace + +![Create teamspace dropdown](/images/dashboard/user-dropdown.png) + + + + Click **Create a teamspace** from the top-left dropdown. + + + Enter a teamspace name. + + + +You must have a Pro or Enterprise plan to create a teamspace. Only the teamspace owner needs a paid plan — invited members don't need their own subscription. Once added, all members automatically benefit from the team's Pro or Enterprise limits. + +## Roles + +| Permission | Owner | Admin | Developer | +| --------------------- | ----- | ----- | --------- | +| View dashboard | ✓ | ✓ | ✓ | +| Create API keys | ✓ | ✓ | ✓ | +| Manage team members | ✓ | ✓ | ✗ | +| Manage library access | ✓ | ✓ | ✗ | +| Manage private sources | ✓ | ✓ | ✗ | +| Rename teamspace | ✓ | ✗ | ✗ | +| Delete teamspace | ✓ | ✗ | ✗ | + +## Inviting Members + + + + Enter the email address of the person you want to invite. + + + Choose **Developer** or **Admin**. + + + Click **Add**. The member receives an invitation email and is automatically added to the teamspace once they sign in. + + + +The invitation will remain pending until they sign in. + +## Teamspace Settings + +If you are the owner of the teamspace, you can rename or delete the teamspace under the overview tab. + +![Teamspace management card](/images/dashboard/teamspace-management.png) + +Deleting a teamspace is permanent. All members lose access immediately. + +## Limits + +| Plan | Max Members | +| ---------- | ----------------- | +| Free | 1 (personal only) | +| Pro | 10 | +| Enterprise | Unlimited | diff --git a/docs/howto/usage.mdx b/docs/howto/usage.mdx new file mode 100644 index 0000000..dcb7e0d --- /dev/null +++ b/docs/howto/usage.mdx @@ -0,0 +1,40 @@ +--- +title: Monitor Usage +description: Monitor your Context7 API usage and track costs +--- + +Track your Context7 usage with real-time metrics from the **Overview** tab on your teamspace dashboard. + +![Usage statistics card showing requests, parsing tokens, seats, and cost breakdown](/images/dashboard/usage-stats.png) + +## Metrics Overview + +The Overview tab displays four metrics: + +### Requests + +The total number of API calls made to Context7, shown against your plan's included quota. Requests within your quota are free; excess requests are billed based on your plan. + +### Parsing Tokens + +The total tokens processed when parsing private source documentation (Pro and Enterprise only). + +- Charged when adding a new private source +- Charged for changed content when refreshing +- No charge for cached content when refreshing + +### Seats + +The number of members in your teamspace. Each seat is billed monthly based on your plan. + +### Cost + +Your total monthly cost in USD, with a breakdown of each component: request overages, parsing tokens, and seats. + +See [Plans & Pricing](https://context7.com/plans) for current rates and included quotas. + +## Reporting Periods + +**Free Plan**: Metrics display daily usage (resets every 24 hours) + +**Pro & Enterprise Plans**: Metrics display monthly usage (resets on your billing date) diff --git a/docs/howto/verification.mdx b/docs/howto/verification.mdx new file mode 100644 index 0000000..339c657 --- /dev/null +++ b/docs/howto/verification.mdx @@ -0,0 +1,153 @@ +--- +title: Verify Your Library +description: Get your library verified to increase visibility and build trust with developers +--- + +Verified libraries receive a special badge that signals quality and trustworthiness to developers. Verification helps your library rank higher in search results and gives users confidence that your documentation is reliable. + +Only library owners can apply for verification. You must [claim your library](/howto/claiming-libraries) before applying. + +## Why Get Verified? + +Verification provides several benefits for your library: + +- **Higher search ranking**: Verified libraries are prioritized in search results and recommendations +- **Trust badge**: A verified badge is displayed on your library page, building confidence with users +- **Increased visibility**: Verified libraries appear more prominently across Context7 +- **Broader access**: Teamspaces can restrict their library access to "verified only" - without verification, your library won't be accessible to these users + +## Verification Badge + +Once verified, your library displays a green checkmark badge next to its name: + + + Verified badge on library + + +This badge appears on: +- Your library's main page +- Search results +- Library listings and tables + +## How to Get Verified + +There are two paths to verification: + +### Automatic Verification + +Libraries are automatically verified when they meet certain quality thresholds: + +- **High trust score**: Libraries with a trust score of 9 or above. Trust score is calculated based on the GitHub organization/user profile, considering factors like total stars, number of repositories, account age, recent activity, followers, and profile completeness. +- **Top 100 libraries**: Most-used libraries by API requests + +Automatic verification is checked daily. If your library qualifies, it will be verified automatically without any action required. + +### Manual Verification + +If your library doesn't qualify for automatic verification, you can apply manually: + + + + You must be a verified owner of the library. See [Claim Your Library](/howto/claiming-libraries) for instructions. + + + + Navigate to your library's admin page at: + + ``` + https://context7.com/{owner}/{repo}/admin + ``` + + + + If your library is not yet verified, you'll see a banner at the top of the configuration page with an "Apply for Verification" button. Click it to start the process. + + + Apply for Verification button + + + + + When you initiate a verification request, Context7 automatically checks a set of quality criteria. If your library meets **any one** of the following criteria, it is verified instantly — no form required: + + - **Trust score above 7**: Calculated from your GitHub organization/user profile, including stars, repository count, account age, recent activity, followers, and profile completeness. + - **250+ GitHub stars** *(repositories only)*: Indicates a strong and established community. + - **Top 1% by popularity ranking**: Your library is among the most in-demand sources indexed on Context7. + - **200+ referring domains** *(websites and llms.txt sources only)*: Your source is cited or linked to by more than 200 unique external domains, demonstrating broad recognition across the web. + + If any of these thresholds are met, verification is granted immediately. + + + + If none of the quality thresholds are met, you'll be prompted to fill out the verification application form: + + | Field | Description | Required | + | --- | --- | --- | + | **Website/Docs URL** | Link to your library's official website or documentation | Yes | + | **Library Description** | Brief description of what your library does | Yes | + | **Developer Value** | How your library helps developers | No | + + + Verification application modal + + + + + Click "Submit Application" to send your request. Your application will be reviewed immediately. + + + +## Verification Requirements + +To be approved for manual verification, your library should: + +- **Be a legitimate project**: Real libraries with actual users and documentation +- **Have quality documentation**: Well-organized, up-to-date documentation that helps developers +- **Be actively maintained**: Regular updates and responsive to issues +- **Follow best practices**: Clear README, proper licensing, and good code organization + + + Verification is free and always will be. We verify libraries based on quality, not payment. + + +## Verification Status + +You can check your library's verification status on the admin page: + +| Status | Description | +| --- | --- | +| **Verified** | Green badge displayed, full verification benefits | +| **Not Verified** | No badge, apply to get verified | + +## FAQ + +### How long does manual verification take? + +If your library meets one of the quality thresholds, verification is instant. Otherwise, your application is reviewed immediately after submission. If it's not automatically accepted, you can [open a GitHub issue](https://github.com/upstash/context7/issues/new/choose) to request a manual review. + +### Can verification be revoked? + +Yes, in rare cases. Verification may be revoked if: +- The library becomes abandoned or unmaintained +- Documentation quality significantly degrades +- The library violates Context7's terms of service + +### Does verification cost anything? + +No. Verification is completely free and based solely on library quality. + +### I was automatically verified. Can I lose it? + +Automatic verification is recalculated daily. If your library no longer meets the automatic criteria, you'll retain your verification status but may need to apply manually if it's ever revoked. + +### My library is popular but not verified. Why? + +Automatic verification considers multiple factors including trust score and usage statistics. When you apply manually, Context7 also checks quality criteria like GitHub stars, popularity ranking, and referring domains. If you believe your library meets any of these thresholds, please apply manually and the check will run immediately. + +## Need Help? + +If you have questions about verification or encounter issues with the application process: + +- [Open a GitHub issue](https://github.com/upstash/context7/issues/new/choose) +- Join our [Discord community](https://upstash.com/discord) +- Contact us at [support@context7.com](mailto:support@context7.com) diff --git a/docs/images/clients/claude-code/mcp-details.png b/docs/images/clients/claude-code/mcp-details.png new file mode 100644 index 0000000000000000000000000000000000000000..f4e5b21b76e33432e8047f4f05c3efa3a9ff05ed GIT binary patch literal 50376 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 z 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 z z24gC?e9tS!(+IJ0#bJSrTtB7J7}5Qk(dkM18y3csU9M=^=9?3yS0blBZIST#Yu4mv z5se3L7u=3%z0dPCk&hxOD!4blZYl)8Omun}qafJhsUo*pC4xdvUOqb4=)m{gG6+)De?u2AvktX-wI$}Un7FoN}TU~ zc_kkL22wY1@!Gcn6B8WTmwp0u5r=g~KEH5^JH!ARr2d}&PrbF&nR`K#+$O7DzDgHO zT#t6B)v)k!loWz6g1|EQTENVAxzswJ6}U0ieD>*TC;QhTc*d^5{F@;8e>ZC48tfp& z&EI-xzgg_VLL$(j2?Qv%(cW_T`o%E2rSgfZ#&^d)pvYXnTB-Bht20VK^~sG=G$$@t zG`&GX&omxIUJS>NKNYf|kX$%?%NRYXL75qwU=ovlcwF87OvK48mr{??vek|lXV^+{ z`ueJ(Z8Q78yoIRG9qa!Hyu!e@YFDa-gziB8Sx~(cIQAr`w@Hhw+M1>claI5?}=M4_#e!=n5k>s zxpw)w+@&kG-d-ZWgGLwQ!v0VClo1FTU>+LByVkE!6zYA>sPJEdF-02zR_2@tQ z0ObfN1h+i-<(+8>F227wR4)y%m+vm+UdW|C+xTzX-FX?b#P{b^ci(}4y$+W+R&V@s z`j_N#i*N$C`9)KHAL_2z^}9PbxXu8@Kd0}y|MnB~M%33or+O>bc}s3_1zMcK{^wM; zB2+I0(oj%_%m33tUly$t5Cz0(FGI+=J@F>(3m`LZ>!f2p>MP-nvANp+gkj$qd*oJL zB{Tm+oM~1%aCe#0;d{jG$#Q+oWB2pR=o)9(c0orEIluEkXRLQm%4ohrSA_Z5yJaN1 z0~!y?ySXNO@yo<-+vwA^FP)uY;mjXj0J>0|Zam3p1Km_@+Tq=R408ZAlF@3tly#Od z!2QZ^{8g)bGF(BISc`G6XFz$k8{B$yGfmc`k;nTNi=^-O2<&uAznz^OL#zYV!0tzL z;+d_g`ge&?UmSK0<%vZJOS&9IQyhP-^wo}^`wdWF#Zyp=}`^}NVCA0|!eSq~JAI1<_p=y_3b-S4N`T&o? z>WzAp#lZ})ExSf${ps;`yN&c#oh)+etNn73W?E(_?^{J_@9D+QEAFcUhMVZ(xPZ8> zZ;4#`6)tNUA|69mMI3r>jlcP}=BR4XGc-4dKb{zaZ%s3b^xo)+;?KuoW?=ZODaCm0hP53r;kTR3~2lzzL%C{IZsR{%xa?dw)=87sbs)bdmOeE>c)F)?4*_~ z#YC@WZgP`J>Q!OkRm|#Oy3Ey|^K~nYuRr^?xvtmo7;U4+E8OI{vwZ^<79DBa$xw z-iU(`Ir+Fe@W(cEmZTeJy>&L&POwN5_LsgUZY9}F)HjF7Px@pe7#yKmBRmCg*R6+} z&#sYj!3wGJSW7tT>F8Lnn`V!5Z8x!J8(;`mw#qourEK#u#r(f)@PdT~ zO@ml_@5>zZKH}osFwgcqN^KkQz@I*S?V`7;NQ25LP1zP$C*dK!Ri!w2pJehav_gDn>!_ufsVO#G*W-I;Nwr%bN3Wo&zV5GuGg`HuL6_FaY?h`x zzM*SeVECWwS_>P3_Ys||Lum7_Vcyy;_<@j!ylvAWsQhC3OD*ac-5=lyx1MpG?Ygn- z*S(n1rWGbUs0~@$;ska5JkJXyI~wR)#L44-VT(r=4;$_0Vy0C+WHQ{onC#|J!^fF#;mRxh7~C9{;Jyid&O>Mcnu8;UoQol) zS)bqyxo5aZQDIKaClI3}>clp`g^G$wT-!N&*u>OLE#c@cNs>K1W6FNcbY$}tc9k+y zY982Nx*!?^vnv&`F*>qy3=Zafhe#mUf7&sJvobf&9lp*d_9!c2%38=#FWa0-xJ+*P1Q~IFnxr2-t%R--T^I%#z^M zXXwHOQ&TMBoQe$Y#jK`HTPUK`iLR2!gGL$-E%gLKUZd|!qhrW>g3(&Ml$Gd1w&P?cl;}QiEe-m z<79l~o+jz^b?B+3_E#ANpmTDW=XA_-)cQKTBL$4!fz1~ecB6d&n$b-s#6u%}`ki8n z*T33qW5Q9LDzQ4Ur1-A~Mi_yoMrr+&Z@ep;%5_^ZShk)oxSt-8mbda01RYqPBN=g{ z`91VmlSCUU{rc@%3=*$ujGwi#sk@D4$T~IB6p(w^k-M*GEOPifU`aLIE9w+&V=EmH zd8N|gw~qva$X&I~_yV$ED`g+Ai;99%uts0XQG1D}$8!gQ;ZdjOwfRWBZM%*otDXCt zLI9@_Lk-vIS$+AnQlfx2<|IMdaeBFC_e~5<f75M3w|qkil?IOnmn)4va{I@ZoRtSW$WmL25Sfs+Hk1_Pg(vWjIp`W&7uM0K z=jY^HsWiHN21IdANN&;{3#s#2n8+;h>nmP<`*|RilcH_A4Kki78Pe!a27p$z^!n;m zMqN1^up)7;KCd?ScJEc` zJ>Pvl_vIx=G;{+KMAEcmX!!lE0&SNOo^~eASnxr8-;-2l%LxzhTo3&0Oc+D`!>kz> zg#T<(XUq|I1P+qm7nNMHCo=s)+t{V`+X=$zlg01Ol}Om2oK^Bu{!_uq zK(b|`wsw(R>Mc`l<9u6vo4XhzRCZl#T5?EXl9+D50W{g)F5nQ&@Ibz3a@NzlakHb$ zzQW_)X4J9maAhUrIzu(vZl004rMj+5su#s*ybKyPY$Vb2R!yWjXMr#4^QL(KdaP+M zGu_-}Vow{t((lD!$y^P*G>2+ArZ?Js;lF~{vYZX8yd}SH9ksPq#MYS^&rVf13;Bl}Jcfi(hlqJp6Z{?3v<06r#`B%4y02;~R`JLh(``b@y&B6R+f2*CqpSR@}3y0SXNdBm?FMx_7 z-+D0+{6`@90U~OBPn`PV;$Enxcdr5E6(UKy_eUS8Fau3F@{NW6Y25t`K;wP8*)8?w iH~oJz{_k9k^Q(A1-Ic-Q#gI$DM^#bdan++2LH`3b{Q;o> literal 0 HcmV?d00001 diff --git a/docs/images/clients/claude-code/mcp-unauthenticated.png b/docs/images/clients/claude-code/mcp-unauthenticated.png new file mode 100644 index 0000000000000000000000000000000000000000..cef670ece48cce4e1f12e6b5540d86553a1062bd GIT binary patch literal 38798 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 literal 0 HcmV?d00001 diff --git a/docs/images/clients/cursor/logo.png b/docs/images/clients/cursor/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..690b4c3d9a8d1303c1f3a0ae036e663ee2ca4b6b GIT binary patch literal 40415 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

v4jEon(VuzAr>r{)7D&0e=nI1K-C{ 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 Y^mx(Ze=d%*pTa-(dWSD_zTh1DKOvnjlmGw# literal 0 HcmV?d00001 diff --git a/docs/images/clients/cursor/mcp-settings.png b/docs/images/clients/cursor/mcp-settings.png new file mode 100644 index 0000000000000000000000000000000000000000..30cad4ff48412ac5ba5651f368ce4dca7faddb94 GIT binary patch literal 69202 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 literal 0 HcmV?d00001 diff --git a/docs/images/clients/cursor/rules.png b/docs/images/clients/cursor/rules.png new file mode 100644 index 0000000000000000000000000000000000000000..ec975fddcc22fce09431013b0f2d43654f7aae0f GIT binary patch literal 126692 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�`Y3O@R*JU2|+JFNhyN0 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