├── pnpm-workspace.yaml ├── public ├── cover.png ├── icon.png ├── context7-icon.svg ├── context7-icon-green.svg └── context7-logo.svg ├── docs ├── public │ ├── favicon.ico │ └── logo │ │ ├── logo.png │ │ ├── logo.svg │ │ └── logo-dark.svg ├── images │ ├── dashboard │ │ ├── members-tab.png │ │ ├── usage-stats.png │ │ ├── api-keys-card.png │ │ ├── billing-page.png │ │ ├── manage-cards.png │ │ ├── user-dropdown.png │ │ ├── add-payment-method.png │ │ ├── admin │ │ │ ├── claim-modal.png │ │ │ ├── config-overview.png │ │ │ ├── library-metrics.png │ │ │ ├── managing-versions.png │ │ │ ├── claim-library-button.png │ │ │ └── library-manage-button.png │ │ ├── private-repos-card.png │ │ ├── library-access-card.png │ │ ├── team-management-card.png │ │ └── library-access-selector.png │ └── integrations │ │ └── coderabbit │ │ ├── add-server-modal.png │ │ ├── integrations-tab.png │ │ ├── server-connected.png │ │ └── update-mcp-settings.png ├── dashboard │ ├── libraries.mdx │ ├── billing.mdx │ ├── api-keys.mdx │ ├── usage.mdx │ ├── team.mdx │ └── private-repositories.mdx ├── overview.mdx ├── contact.mdx ├── integrations │ └── code-rabbit.mdx ├── docs.json ├── sdks │ └── ts │ │ ├── getting-started.mdx │ │ └── commands │ │ └── search-library.mdx ├── api-guide.mdx ├── plans-pricing.mdx ├── security.mdx ├── adding-libraries.mdx └── usage.mdx ├── packages ├── sdk │ ├── src │ │ ├── commands │ │ │ ├── index.ts │ │ │ ├── search-library │ │ │ │ ├── index.ts │ │ │ │ └── index.test.ts │ │ │ ├── command.ts │ │ │ ├── types.ts │ │ │ └── get-docs │ │ │ │ ├── index.ts │ │ │ │ └── index.test.ts │ │ ├── error │ │ │ └── index.ts │ │ ├── utils │ │ │ └── test-utils.ts │ │ ├── client.ts │ │ └── http │ │ │ └── index.ts │ ├── tsup.config.ts │ ├── prettier.config.mjs │ ├── CHANGELOG.md │ ├── vitest.config.ts │ ├── tsconfig.json │ ├── LICENSE │ ├── package.json │ ├── eslint.config.js │ └── README.md ├── mcp │ ├── mcpb │ │ ├── context7.mcpb │ │ ├── .mcpbignore │ │ └── manifest.json │ ├── CHANGELOG.md │ ├── .prettierignore │ ├── prettier.config.mjs │ ├── tsconfig.json │ ├── smithery.yaml │ ├── Dockerfile │ ├── src │ │ └── lib │ │ │ ├── types.ts │ │ │ ├── encryption.ts │ │ │ ├── utils.ts │ │ │ └── api.ts │ ├── LICENSE │ ├── eslint.config.js │ ├── package.json │ └── schema │ │ └── context7.json └── tools-ai-sdk │ ├── src │ ├── agents │ │ ├── index.ts │ │ └── context7.ts │ ├── prompts │ │ ├── index.ts │ │ └── system.ts │ ├── tools │ │ ├── index.ts │ │ ├── types.ts │ │ ├── resolve-library.ts │ │ └── get-library-docs.ts │ ├── index.ts │ └── index.test.ts │ ├── tsup.config.ts │ ├── vitest.config.ts │ ├── tsconfig.json │ ├── eslint.config.js │ ├── package.json │ └── README.md ├── .changeset ├── good-geese-start.md ├── config.json ├── slimy-dancers-wait.md └── README.md ├── prettier.config.mjs ├── gemini-extension.json ├── tsconfig.json ├── .prettierignore ├── .github ├── dependabot.yml ├── workflows │ ├── canary-release.yml │ ├── test.yml │ ├── changeset-check.yml │ ├── ecr-deploy.yml │ ├── publish-mcp.yml │ └── release.yml └── ISSUE_TEMPLATE │ ├── documentation.yml │ ├── feature_request.yml │ └── bug_report.yml ├── server.json ├── LICENSE ├── eslint.config.js ├── SECURITY.md ├── package.json ├── .gitignore └── i18n └── README.ar.md /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "packages/*" 3 | -------------------------------------------------------------------------------- /public/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/public/cover.png -------------------------------------------------------------------------------- /public/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/public/icon.png -------------------------------------------------------------------------------- /docs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/public/favicon.ico -------------------------------------------------------------------------------- /docs/public/logo/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/public/logo/logo.png -------------------------------------------------------------------------------- /packages/sdk/src/commands/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./get-docs"; 2 | export * from "./search-library"; 3 | -------------------------------------------------------------------------------- /packages/mcp/mcpb/context7.mcpb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/packages/mcp/mcpb/context7.mcpb -------------------------------------------------------------------------------- /packages/tools-ai-sdk/src/agents/index.ts: -------------------------------------------------------------------------------- 1 | export { Context7Agent, type Context7AgentConfig } from "./context7"; 2 | -------------------------------------------------------------------------------- /docs/images/dashboard/members-tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/members-tab.png -------------------------------------------------------------------------------- /docs/images/dashboard/usage-stats.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/usage-stats.png -------------------------------------------------------------------------------- /docs/images/dashboard/api-keys-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/api-keys-card.png -------------------------------------------------------------------------------- /docs/images/dashboard/billing-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/billing-page.png -------------------------------------------------------------------------------- /docs/images/dashboard/manage-cards.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/manage-cards.png -------------------------------------------------------------------------------- /docs/images/dashboard/user-dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/user-dropdown.png -------------------------------------------------------------------------------- /docs/images/dashboard/add-payment-method.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/add-payment-method.png -------------------------------------------------------------------------------- /docs/images/dashboard/admin/claim-modal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/admin/claim-modal.png -------------------------------------------------------------------------------- /docs/images/dashboard/private-repos-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/private-repos-card.png -------------------------------------------------------------------------------- /docs/images/dashboard/admin/config-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/admin/config-overview.png -------------------------------------------------------------------------------- /docs/images/dashboard/admin/library-metrics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/admin/library-metrics.png -------------------------------------------------------------------------------- /docs/images/dashboard/library-access-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/library-access-card.png -------------------------------------------------------------------------------- /docs/images/dashboard/team-management-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/team-management-card.png -------------------------------------------------------------------------------- /docs/images/dashboard/admin/managing-versions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/admin/managing-versions.png -------------------------------------------------------------------------------- /docs/images/dashboard/library-access-selector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/library-access-selector.png -------------------------------------------------------------------------------- /.changeset/good-geese-start.md: -------------------------------------------------------------------------------- 1 | --- 2 | "@upstash/context7-mcp": patch 3 | --- 4 | 5 | Remove masked API key display from unauthorized error responses 6 | -------------------------------------------------------------------------------- /docs/images/dashboard/admin/claim-library-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/admin/claim-library-button.png -------------------------------------------------------------------------------- /packages/mcp/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @upstash/context7-mcp 2 | 3 | ## 1.0.31 4 | 5 | ### Patch Changes 6 | 7 | - 6255e26: Migrate to pnpm monorepo structure 8 | -------------------------------------------------------------------------------- /docs/images/dashboard/admin/library-manage-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/dashboard/admin/library-manage-button.png -------------------------------------------------------------------------------- /docs/images/integrations/coderabbit/add-server-modal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/integrations/coderabbit/add-server-modal.png -------------------------------------------------------------------------------- /docs/images/integrations/coderabbit/integrations-tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/integrations/coderabbit/integrations-tab.png -------------------------------------------------------------------------------- /docs/images/integrations/coderabbit/server-connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/integrations/coderabbit/server-connected.png -------------------------------------------------------------------------------- /docs/images/integrations/coderabbit/update-mcp-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/context7/master/docs/images/integrations/coderabbit/update-mcp-settings.png -------------------------------------------------------------------------------- /packages/mcp/mcpb/.mcpbignore: -------------------------------------------------------------------------------- 1 | schema/context7.json 2 | prettier.config.mjs 3 | smithery.yaml 4 | Dockerfile 5 | eslint.config.js 6 | *.md 7 | *.ts 8 | LICENSE 9 | public/* -------------------------------------------------------------------------------- /packages/mcp/.prettierignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules 3 | 4 | # Build outputs 5 | dist 6 | 7 | # Logs 8 | *.log 9 | 10 | # Environment files 11 | .env 12 | .env.* 13 | -------------------------------------------------------------------------------- /packages/sdk/src/error/index.ts: -------------------------------------------------------------------------------- 1 | export class Context7Error extends Error { 2 | constructor(message: string) { 3 | super(message); 4 | this.name = "Context7Error"; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/tools-ai-sdk/src/prompts/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | SYSTEM_PROMPT, 3 | AGENT_PROMPT, 4 | RESOLVE_LIBRARY_DESCRIPTION, 5 | GET_LIBRARY_DOCS_DESCRIPTION, 6 | } from "./system"; 7 | -------------------------------------------------------------------------------- /packages/tools-ai-sdk/src/tools/index.ts: -------------------------------------------------------------------------------- 1 | export { resolveLibrary } from "./resolve-library"; 2 | export { getLibraryDocs } from "./get-library-docs"; 3 | export type { Context7ToolsConfig } from "./types"; 4 | -------------------------------------------------------------------------------- /packages/sdk/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "tsup"; 2 | 3 | export default defineConfig({ 4 | entry: ["./src/client.ts"], 5 | format: ["cjs", "esm"], 6 | clean: true, 7 | dts: true, 8 | }); 9 | -------------------------------------------------------------------------------- /prettier.config.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('prettier').Config} 3 | */ 4 | const config = { 5 | endOfLine: "lf", 6 | singleQuote: false, 7 | tabWidth: 2, 8 | trailingComma: "es5", 9 | printWidth: 100, 10 | arrowParens: "always", 11 | }; 12 | 13 | export default config; 14 | -------------------------------------------------------------------------------- /packages/mcp/prettier.config.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('prettier').Config} 3 | */ 4 | const config = { 5 | endOfLine: "lf", 6 | singleQuote: false, 7 | tabWidth: 2, 8 | trailingComma: "es5", 9 | printWidth: 100, 10 | arrowParens: "always", 11 | }; 12 | 13 | export default config; 14 | -------------------------------------------------------------------------------- /packages/mcp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "module": "Node16", 5 | "moduleResolution": "Node16", 6 | "outDir": "./dist", 7 | "rootDir": "./src" 8 | }, 9 | "include": ["src/**/*"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/sdk/prettier.config.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('prettier').Config} 3 | */ 4 | const config = { 5 | endOfLine: "lf", 6 | singleQuote: false, 7 | tabWidth: 2, 8 | trailingComma: "es5", 9 | printWidth: 100, 10 | arrowParens: "always", 11 | }; 12 | 13 | export default config; 14 | -------------------------------------------------------------------------------- /gemini-extension.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "context7", 3 | "description": "Up-to-date code docs for any prompt", 4 | "version": "1.0.0", 5 | "mcpServers": { 6 | "context7": { 7 | "command": "npx", 8 | "args": ["-y", "@upstash/context7-mcp", "--api-key", "${CONTEXT7_API_KEY}"] 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/mcp/smithery.yaml: -------------------------------------------------------------------------------- 1 | # Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml 2 | 3 | startCommand: 4 | type: http 5 | configSchema: 6 | # JSON Schema defining the configuration options for the MCP. 7 | type: object 8 | description: No configuration required 9 | exampleConfig: {} 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "lib": ["ES2022"], 5 | "moduleResolution": "Node16", 6 | "module": "Node16", 7 | "strict": true, 8 | "esModuleInterop": true, 9 | "skipLibCheck": true, 10 | "forceConsistentCasingInFileNames": true 11 | }, 12 | "exclude": ["node_modules", "dist", "build"] 13 | } 14 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules 3 | 4 | # Lock files 5 | pnpm-lock.yaml 6 | package-lock.json 7 | yarn.lock 8 | bun.lockb 9 | 10 | # Build outputs 11 | dist 12 | build 13 | .next 14 | out 15 | 16 | # Logs 17 | *.log 18 | 19 | # Environment files 20 | .env 21 | .env.* 22 | 23 | # IDE 24 | .vscode 25 | .idea 26 | 27 | # Changesets 28 | .changeset/*.md 29 | -------------------------------------------------------------------------------- /packages/sdk/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @upstash/context7-sdk 2 | 3 | ## 0.1.0 4 | 5 | ### Minor Changes 6 | 7 | - 5e11d35: Initial release of the Context7 TypeScript SDK 8 | - HTTP/REST client for the Context7 API 9 | - `searchLibrary()` - Search for libraries in the Context7 database 10 | - `getDocs()` - Retrieve documentation with filtering options 11 | - Environment variable support for API key configuration 12 | -------------------------------------------------------------------------------- /packages/tools-ai-sdk/src/tools/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Configuration for Context7 tools 3 | */ 4 | export interface Context7ToolsConfig { 5 | /** 6 | * Context7 API key. If not provided, will use CONTEXT7_API_KEY environment variable. 7 | */ 8 | apiKey?: string; 9 | /** 10 | * Default maximum number of documentation results per page. 11 | * @default 10 12 | */ 13 | defaultMaxResults?: number; 14 | } 15 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "master", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [], 11 | "snapshot": { 12 | "useCalculatedVersion": true, 13 | "prereleaseTemplate": "{tag}-{datetime}" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: / 5 | schedule: 6 | interval: monthly 7 | - package-ecosystem: bun 8 | directory: / 9 | schedule: 10 | interval: monthly 11 | - package-ecosystem: docker 12 | directory: / 13 | schedule: 14 | interval: monthly 15 | - package-ecosystem: github-actions 16 | directory: / 17 | schedule: 18 | interval: monthly 19 | -------------------------------------------------------------------------------- /.changeset/slimy-dancers-wait.md: -------------------------------------------------------------------------------- 1 | --- 2 | "@upstash/context7-tools-ai-sdk": minor 3 | --- 4 | 5 | Initial release of `@upstash/context7-tools-ai-sdk` - Vercel AI SDK integration for Context7. 6 | 7 | ### Features 8 | 9 | - **Tools**: `resolveLibrary()` and `getLibraryDocs()` tools compatible with AI SDK's `generateText` and `streamText` 10 | - **Agent**: Pre-configured `Context7Agent` that handles the multi-step documentation retrieval workflow automatically 11 | 12 | -------------------------------------------------------------------------------- /packages/tools-ai-sdk/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "tsup"; 2 | 3 | export default defineConfig({ 4 | entry: { 5 | index: "./src/index.ts", 6 | agent: "./src/agents/index.ts", 7 | }, 8 | format: ["cjs", "esm"], 9 | clean: true, 10 | dts: true, 11 | esbuildOptions(options) { 12 | options.alias = { 13 | "@tools": "./src/tools/index.ts", 14 | "@agents": "./src/agents/index.ts", 15 | "@prompts": "./src/prompts/index.ts", 16 | }; 17 | }, 18 | }); 19 | -------------------------------------------------------------------------------- /packages/sdk/src/commands/search-library/index.ts: -------------------------------------------------------------------------------- 1 | import { Command } from "@commands/command"; 2 | import type { SearchLibraryResponse } from "@commands/types"; 3 | 4 | export class SearchLibraryCommand extends Command { 5 | constructor(query: string) { 6 | const queryParams: Record = {}; 7 | 8 | if (query) { 9 | queryParams.query = query; 10 | } 11 | 12 | super({ method: "GET", query: queryParams }, "v2/search"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /packages/sdk/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import path from "path"; 3 | import dotenv from "dotenv"; 4 | 5 | dotenv.config(); 6 | 7 | export default defineConfig({ 8 | test: { 9 | globals: true, 10 | environment: "node", 11 | include: ["src/**/*.test.ts"], 12 | env: process.env, 13 | }, 14 | resolve: { 15 | alias: { 16 | "@commands": path.resolve(__dirname, "./src/commands"), 17 | "@http": path.resolve(__dirname, "./src/http"), 18 | "@error": path.resolve(__dirname, "./src/error/index.ts"), 19 | }, 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /packages/tools-ai-sdk/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import path from "path"; 3 | import { config } from "dotenv"; 4 | 5 | config(); 6 | 7 | export default defineConfig({ 8 | test: { 9 | globals: true, 10 | environment: "node", 11 | include: ["src/**/*.test.ts"], 12 | }, 13 | resolve: { 14 | alias: { 15 | "@tools": path.resolve(__dirname, "./src/tools/index.ts"), 16 | "@agents": path.resolve(__dirname, "./src/agents/index.ts"), 17 | "@prompts": path.resolve(__dirname, "./src/prompts/index.ts"), 18 | }, 19 | }, 20 | }); 21 | -------------------------------------------------------------------------------- /packages/tools-ai-sdk/src/index.ts: -------------------------------------------------------------------------------- 1 | // Agents 2 | export { Context7Agent, type Context7AgentConfig } from "@agents"; 3 | 4 | // Tools 5 | export { resolveLibrary, getLibraryDocs, type Context7ToolsConfig } from "@tools"; 6 | 7 | // Prompts 8 | export { 9 | SYSTEM_PROMPT, 10 | AGENT_PROMPT, 11 | RESOLVE_LIBRARY_DESCRIPTION, 12 | GET_LIBRARY_DOCS_DESCRIPTION, 13 | } from "@prompts"; 14 | 15 | // Re-export useful types from SDK 16 | export type { 17 | SearchResult, 18 | SearchLibraryResponse, 19 | CodeDocsResponse, 20 | TextDocsResponse, 21 | InfoDocsResponse, 22 | Pagination, 23 | } from "@upstash/context7-sdk"; 24 | -------------------------------------------------------------------------------- /packages/sdk/src/utils/test-utils.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from "@http"; 2 | 3 | export function newHttpClient(): HttpClient { 4 | const apiKey = process.env.CONTEXT7_API_KEY || process.env.API_KEY; 5 | 6 | if (!apiKey) { 7 | throw new Error("CONTEXT7_API_KEY or API_KEY environment variable is required for tests"); 8 | } 9 | 10 | return new HttpClient({ 11 | baseUrl: process.env.CONTEXT7_BASE_URL || "https://context7.com/api", 12 | headers: { 13 | Authorization: `Bearer ${apiKey}`, 14 | }, 15 | retry: { 16 | retries: 3, 17 | backoff: (retryCount) => Math.exp(retryCount) * 50, 18 | }, 19 | cache: "no-store", 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /packages/sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["ESNext"], 4 | "module": "esnext", 5 | "target": "esnext", 6 | "moduleResolution": "bundler", 7 | "moduleDetection": "force", 8 | "allowImportingTsExtensions": true, 9 | "noEmit": true, 10 | "strict": true, 11 | "downlevelIteration": true, 12 | "skipLibCheck": true, 13 | "allowSyntheticDefaultImports": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "allowJs": true, 16 | "paths": { 17 | "@error": ["./src/error/index.ts"], 18 | "@http": ["./src/http/index.ts"], 19 | "@commands/*": ["./src/commands/*"] 20 | } 21 | }, 22 | "include": ["src/**/*", "tsup.config.ts", "vitest.config.ts", "eslint.config.js"], 23 | "exclude": ["node_modules", "dist"] 24 | } 25 | -------------------------------------------------------------------------------- /packages/tools-ai-sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["ESNext"], 4 | "module": "esnext", 5 | "target": "esnext", 6 | "moduleResolution": "bundler", 7 | "moduleDetection": "force", 8 | "allowImportingTsExtensions": true, 9 | "noEmit": true, 10 | "strict": true, 11 | "downlevelIteration": true, 12 | "skipLibCheck": true, 13 | "allowSyntheticDefaultImports": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "allowJs": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "@tools": ["./src/tools/index.ts"], 19 | "@agents": ["./src/agents/index.ts"], 20 | "@prompts": ["./src/prompts/index.ts"] 21 | } 22 | }, 23 | "include": ["src/**/*", "tsup.config.ts", "vitest.config.ts", "eslint.config.js"], 24 | "exclude": ["node_modules", "dist", "examples"] 25 | } 26 | -------------------------------------------------------------------------------- /server.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://static.modelcontextprotocol.io/schemas/2025-10-17/server.schema.json", 3 | "name": "io.github.upstash/context7", 4 | "title": "Context7", 5 | "description": "Up-to-date code docs for any prompt", 6 | "repository": { 7 | "url": "https://github.com/upstash/context7", 8 | "source": "github" 9 | }, 10 | "version": "1.0.0", 11 | "packages": [ 12 | { 13 | "registryType": "npm", 14 | "identifier": "@upstash/context7-mcp", 15 | "version": "1.0.26", 16 | "transport": { 17 | "type": "stdio" 18 | }, 19 | "environmentVariables": [ 20 | { 21 | "description": "API key for authentication", 22 | "isRequired": false, 23 | "format": "string", 24 | "isSecret": true, 25 | "name": "CONTEXT7_API_KEY" 26 | } 27 | ] 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /packages/mcp/Dockerfile: -------------------------------------------------------------------------------- 1 | # Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile 2 | # ----- Build Stage ----- 3 | FROM node:lts-alpine AS builder 4 | WORKDIR /app 5 | 6 | # Copy package and configuration 7 | COPY package.json bun.lock tsconfig.json ./ 8 | 9 | # Copy source code 10 | COPY src ./src 11 | 12 | # Install dependencies and build 13 | RUN npm install && npm run build 14 | 15 | # ----- Production Stage ----- 16 | FROM node:lts-alpine 17 | WORKDIR /app 18 | 19 | # Copy built artifacts 20 | COPY --from=builder /app/dist ./dist 21 | 22 | # Copy package.json for production install 23 | COPY package.json ./ 24 | 25 | # Install only production dependencies 26 | RUN npm install --production --ignore-scripts 27 | 28 | # Expose HTTP port 29 | EXPOSE 8080 30 | 31 | # Default command using CLI flags 32 | CMD ["node", "dist/index.js", "--transport", "http", "--port", "8080"] 33 | -------------------------------------------------------------------------------- /packages/mcp/src/lib/types.ts: -------------------------------------------------------------------------------- 1 | export interface SearchResult { 2 | id: string; 3 | title: string; 4 | description: string; 5 | branch: string; 6 | lastUpdateDate: string; 7 | state: DocumentState; 8 | totalTokens: number; 9 | totalSnippets: number; 10 | stars?: number; 11 | trustScore?: number; 12 | benchmarkScore?: number; 13 | versions?: string[]; 14 | } 15 | 16 | export interface SearchResponse { 17 | error?: string; 18 | results: SearchResult[]; 19 | } 20 | 21 | // Version state is still needed for validating search results 22 | export type DocumentState = "initial" | "finalized" | "error" | "delete"; 23 | 24 | /** 25 | * Documentation modes for fetching library documentation 26 | */ 27 | export const DOCUMENTATION_MODES = { 28 | CODE: "code", 29 | INFO: "info", 30 | } as const; 31 | 32 | export type DocumentationMode = (typeof DOCUMENTATION_MODES)[keyof typeof DOCUMENTATION_MODES]; 33 | -------------------------------------------------------------------------------- /docs/dashboard/libraries.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Library Access 3 | description: Configure which libraries your team can access 4 | --- 5 | 6 | Control which public libraries your team can access from the [libraries tab](https://context7.com/dashboard?tab=libraries). 7 | 8 | ## Public Library Access 9 | 10 | ![Public Library Access card](/images/dashboard/library-access-card.png) 11 | 12 | Configure which public libraries your team can access: 13 | 14 | ![Library access options](/images/dashboard/library-access-selector.png) 15 | 16 | **All Sources** (Default): Access to all public libraries, including future additions 17 | 18 | **Select Specific**: Choose individual libraries or organizations 19 | 20 | **Disable Public**: Private repos only (requires at least one private repo) 21 | 22 | Only owners and admins can change these settings. 23 | 24 | 25 | For private repositories, see the [Private Repositories](/dashboard/private-repositories) page. 26 | 27 | -------------------------------------------------------------------------------- /public/context7-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Upstash, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /packages/mcp/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Upstash, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /packages/sdk/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Upstash, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /public/context7-icon-green.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/sdk/src/commands/command.ts: -------------------------------------------------------------------------------- 1 | import type { Requester } from "@http"; 2 | 3 | export const _ENDPOINTS = ["v2/search", "v2/docs/info", "v2/docs/code"]; 4 | 5 | export type EndpointVariants = (typeof _ENDPOINTS)[number]; 6 | 7 | export interface CommandRequest { 8 | method?: "GET" | "POST"; 9 | body?: unknown; 10 | query?: Record; 11 | } 12 | 13 | export class Command { 14 | public readonly request: CommandRequest; 15 | public readonly endpoint: EndpointVariants; 16 | 17 | constructor(request: CommandRequest, endpoint: EndpointVariants | string) { 18 | this.request = request; 19 | this.endpoint = endpoint; 20 | } 21 | 22 | /** 23 | * Execute the command using a client. 24 | */ 25 | public async exec(client: Requester): Promise { 26 | const { result } = await client.request({ 27 | method: this.request.method || "POST", 28 | path: [this.endpoint], 29 | query: this.request.query, 30 | body: this.request.body, 31 | }); 32 | 33 | if (result === undefined) { 34 | throw new TypeError("Request did not return a result"); 35 | } 36 | 37 | return result; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import tseslint from "typescript-eslint"; 2 | import eslintPluginPrettier from "eslint-plugin-prettier"; 3 | 4 | export default tseslint.config({ 5 | // Base ESLint configuration 6 | ignores: ["node_modules/**", "build/**", "dist/**", ".git/**", ".github/**"], 7 | languageOptions: { 8 | ecmaVersion: 2020, 9 | sourceType: "module", 10 | parser: tseslint.parser, 11 | parserOptions: {}, 12 | globals: { 13 | // Add Node.js globals 14 | process: "readonly", 15 | require: "readonly", 16 | module: "writable", 17 | console: "readonly", 18 | }, 19 | }, 20 | // Settings for all files 21 | linterOptions: { 22 | reportUnusedDisableDirectives: true, 23 | }, 24 | // Apply ESLint recommended rules 25 | extends: [tseslint.configs.recommended], 26 | plugins: { 27 | prettier: eslintPluginPrettier, 28 | }, 29 | rules: { 30 | // TypeScript rules 31 | "@typescript-eslint/explicit-module-boundary-types": "off", 32 | "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }], 33 | "@typescript-eslint/no-explicit-any": "warn", 34 | // Prettier integration 35 | "prettier/prettier": "error", 36 | }, 37 | }); 38 | -------------------------------------------------------------------------------- /.github/workflows/canary-release.yml: -------------------------------------------------------------------------------- 1 | name: Canary Release 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | branch: 7 | description: "Branch to release from (defaults to current branch)" 8 | required: false 9 | type: string 10 | 11 | jobs: 12 | canary-release: 13 | name: Canary Release 14 | runs-on: ubuntu-latest 15 | permissions: 16 | contents: read 17 | steps: 18 | - name: Checkout Repo 19 | uses: actions/checkout@v6 20 | with: 21 | ref: ${{ inputs.branch || github.ref }} 22 | 23 | - name: Setup Node 24 | uses: actions/setup-node@v4 25 | with: 26 | node-version: "20" 27 | 28 | - name: Setup pnpm 29 | uses: pnpm/action-setup@v4 30 | with: 31 | version: 10 32 | 33 | - name: Configure npm authentication 34 | run: | 35 | echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc 36 | 37 | - name: Install Dependencies 38 | run: pnpm install --frozen-lockfile 39 | 40 | - name: Build all packages 41 | run: pnpm build 42 | 43 | - name: Publish Snapshot 44 | run: pnpm release:snapshot 45 | env: 46 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 47 | -------------------------------------------------------------------------------- /docs/dashboard/billing.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Billing & Payments 3 | description: Manage payment methods and subscriptions 4 | --- 5 | 6 | Add payment methods and manage your Context7 subscription on the [billing page](https://context7.com/dashboard/billing), which you can access from the dropdown menu in the top left corner of the dashboard. 7 | 8 | ![Billing page showing payment methods card and management options](/images/dashboard/billing-page.png) 9 | 10 | ![Billing page dropdown menu](/images/dashboard/user-dropdown.png) 11 | 12 | ## Payment Methods 13 | 14 | ### Adding a Payment Method 15 | 16 | 1. Click "Add payment method" 17 | 2. Enter card details in Stripe form 18 | 3. Complete 3D Secure if required 19 | 4. Card appears in your list 20 | 21 | ![Add payment method modal](/images/dashboard/add-payment-method.png) 22 | 23 | 24 | Your full card details are never stored by Context7. All payment data is handled securely by 25 | Stripe. 26 | 27 | 28 | ### Managing Cards 29 | 30 | **Set Default**: You can set a default card to be charged for future payments. 31 | 32 | **Remove**: You can remove a card by clicking the delete icon. 33 | 34 | ![Manage cards modal](/images/dashboard/manage-cards.png) 35 | 36 | ## Plans 37 | 38 | To learn more about our plans and see the FAQ, visit [Plans](/plans-pricing). 39 | -------------------------------------------------------------------------------- /packages/sdk/src/commands/search-library/index.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test, expect } from "vitest"; 2 | import { SearchLibraryCommand } from "./index"; 3 | import { newHttpClient } from "../../utils/test-utils"; 4 | import { Context7 } from "../../client"; 5 | 6 | const httpClient = newHttpClient(); 7 | 8 | describe("SearchLibraryCommand", () => { 9 | test("should search for a library", async () => { 10 | const command = new SearchLibraryCommand("react"); 11 | const result = await command.exec(httpClient); 12 | 13 | expect(result).toBeDefined(); 14 | expect(result.results).toBeDefined(); 15 | expect(Array.isArray(result.results)).toBe(true); 16 | expect(result.results.length).toBeGreaterThan(0); 17 | expect(result.metadata).toBeDefined(); 18 | expect(typeof result.metadata.authentication).toBe("string"); 19 | }); 20 | 21 | test("should search for a library using client", async () => { 22 | const client = new Context7({ 23 | apiKey: process.env.CONTEXT7_API_KEY || process.env.API_KEY!, 24 | }); 25 | 26 | const result = await client.searchLibrary("react"); 27 | 28 | expect(result).toBeDefined(); 29 | expect(result.results).toBeDefined(); 30 | expect(Array.isArray(result.results)).toBe(true); 31 | expect(result.results.length).toBeGreaterThan(0); 32 | expect(result.metadata).toBeDefined(); 33 | expect(typeof result.metadata.authentication).toBe("string"); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /packages/sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@upstash/context7-sdk", 3 | "version": "0.1.0", 4 | "description": "JavaScript/TypeScript SDK for Context7", 5 | "scripts": { 6 | "build": "tsup", 7 | "test": "vitest run", 8 | "test:watch": "vitest", 9 | "typecheck": "tsc --noEmit", 10 | "dev": "tsup --watch", 11 | "clean": "rm -rf dist", 12 | "lint": "eslint .", 13 | "lint:check": "eslint ." 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/upstash/context7.git", 18 | "directory": "packages/sdk" 19 | }, 20 | "keywords": [ 21 | "context7", 22 | "sdk", 23 | "documentation", 24 | "ai", 25 | "upstash" 26 | ], 27 | "author": "Upstash", 28 | "license": "MIT", 29 | "type": "module", 30 | "exports": { 31 | ".": { 32 | "import": "./dist/client.js", 33 | "require": "./dist/client.cjs" 34 | } 35 | }, 36 | "main": "./dist/client.cjs", 37 | "module": "./dist/client.js", 38 | "types": "./dist/client.d.ts", 39 | "files": [ 40 | "dist" 41 | ], 42 | "bugs": { 43 | "url": "https://github.com/upstash/context7/issues" 44 | }, 45 | "homepage": "https://github.com/upstash/context7#readme", 46 | "publishConfig": { 47 | "access": "public" 48 | }, 49 | "devDependencies": { 50 | "@types/node": "^22.13.14", 51 | "dotenv": "^17.2.3", 52 | "tsup": "^8.5.1", 53 | "typescript": "^5.8.2", 54 | "vitest": "^4.0.13" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /docs/dashboard/api-keys.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: API Keys 3 | description: Create and manage API keys for Context7 authentication 4 | --- 5 | 6 | API keys authenticate your requests to Context7's documentation services. 7 | 8 | ## Managing API Keys 9 | 10 | ![API Keys card showing list of keys with details](/images/dashboard/api-keys-card.png) 11 | 12 | ### Creating API Keys 13 | 14 | Generate a new API key in four simple steps: 15 | 16 | 1. **Click "Create API Key"** in the API Keys card 17 | 2. **Enter a name** (optional but recommended) 18 | - Use descriptive names like "Cursor", "Claude", "VS Code", or "Windsurf" 19 | - This helps you identify keys later 20 | 3. **Copy the key immediately** 21 | - Keys are shown only once for security 22 | - Format: `ctx7sk-**********************` 23 | 4. **Use in your requests or add to your MCP configuration**: 24 | 25 | ```bash 26 | curl "https://context7.com/api/v2/docs/code/vercel/next.js" \ 27 | -H "Authorization: Bearer YOUR_API_KEY" 28 | ``` 29 | 30 | Store your API key securely. You won't be able to see it again after creation. 31 | 32 | ### Revoking Keys 33 | 34 | Remove API keys you no longer need: 35 | 36 | 1. **Click the delete button** next to the key 37 | 2. **Confirm deletion** in the modal 38 | 3. **Key deactivates immediately** - all requests using it will fail 39 | 40 | 41 | Revoking a key is permanent and cannot be undone. Update any applications using the key before 42 | revoking. 43 | 44 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation.yml: -------------------------------------------------------------------------------- 1 | name: Documentation Issue 2 | description: Report incorrect or missing documentation 3 | title: "[Docs]: " 4 | labels: ["documentation"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Found an issue with Context7 documentation? Let us know! 10 | 11 | - type: dropdown 12 | id: doc-type 13 | attributes: 14 | label: Documentation Type 15 | description: Where is the issue? 16 | options: 17 | - README 18 | - Installation instructions 19 | - API documentation 20 | - Library-specific docs 21 | - Configuration examples 22 | validations: 23 | required: true 24 | 25 | - type: textarea 26 | id: issue 27 | attributes: 28 | label: Issue Description 29 | description: What's wrong or missing? 30 | validations: 31 | required: true 32 | 33 | - type: input 34 | id: location 35 | attributes: 36 | label: Documentation Location 37 | description: Link or section name where the issue exists 38 | placeholder: e.g., README.md line 45, or "Installation via Smithery" section 39 | 40 | - type: textarea 41 | id: suggestion 42 | attributes: 43 | label: Suggested Fix 44 | description: How should it be corrected or what should be added? 45 | 46 | - type: textarea 47 | id: additional 48 | attributes: 49 | label: Additional Context 50 | description: Any other relevant information 51 | -------------------------------------------------------------------------------- /packages/mcp/eslint.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "eslint/config"; 2 | import tseslint from "typescript-eslint"; 3 | import eslintPluginPrettier from "eslint-plugin-prettier"; 4 | 5 | export default defineConfig( 6 | { 7 | // Base ESLint configuration 8 | ignores: ["node_modules/**", "build/**", "dist/**", ".git/**", ".github/**"], 9 | }, 10 | { 11 | files: ["**/*.ts", "**/*.tsx"], 12 | languageOptions: { 13 | ecmaVersion: 2020, 14 | sourceType: "module", 15 | parser: tseslint.parser, 16 | parserOptions: { 17 | project: "./tsconfig.json", 18 | tsconfigRootDir: import.meta.dirname, 19 | }, 20 | globals: { 21 | // Add Node.js globals 22 | process: "readonly", 23 | require: "readonly", 24 | module: "writable", 25 | console: "readonly", 26 | }, 27 | }, 28 | // Settings for all files 29 | linterOptions: { 30 | reportUnusedDisableDirectives: true, 31 | }, 32 | plugins: { 33 | "@typescript-eslint": tseslint.plugin, 34 | prettier: eslintPluginPrettier, 35 | }, 36 | rules: { 37 | // TypeScript recommended rules 38 | ...tseslint.configs.recommended.rules, 39 | // TypeScript rules 40 | "@typescript-eslint/explicit-module-boundary-types": "off", 41 | "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }], 42 | "@typescript-eslint/no-explicit-any": "warn", 43 | // Prettier integration 44 | "prettier/prettier": "error", 45 | }, 46 | } 47 | ); 48 | -------------------------------------------------------------------------------- /packages/sdk/eslint.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "eslint/config"; 2 | import tseslint from "typescript-eslint"; 3 | import eslintPluginPrettier from "eslint-plugin-prettier"; 4 | 5 | export default defineConfig( 6 | { 7 | // Base ESLint configuration 8 | ignores: ["node_modules/**", "build/**", "dist/**", ".git/**", ".github/**"], 9 | }, 10 | { 11 | files: ["**/*.ts", "**/*.tsx"], 12 | languageOptions: { 13 | ecmaVersion: 2020, 14 | sourceType: "module", 15 | parser: tseslint.parser, 16 | parserOptions: { 17 | project: "./tsconfig.json", 18 | tsconfigRootDir: import.meta.dirname, 19 | }, 20 | globals: { 21 | // Add Node.js globals 22 | process: "readonly", 23 | require: "readonly", 24 | module: "writable", 25 | console: "readonly", 26 | }, 27 | }, 28 | // Settings for all files 29 | linterOptions: { 30 | reportUnusedDisableDirectives: true, 31 | }, 32 | plugins: { 33 | "@typescript-eslint": tseslint.plugin, 34 | prettier: eslintPluginPrettier, 35 | }, 36 | rules: { 37 | // TypeScript recommended rules 38 | ...tseslint.configs.recommended.rules, 39 | // TypeScript rules 40 | "@typescript-eslint/explicit-module-boundary-types": "off", 41 | "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }], 42 | "@typescript-eslint/no-explicit-any": "warn", 43 | // Prettier integration 44 | "prettier/prettier": "error", 45 | }, 46 | } 47 | ); 48 | -------------------------------------------------------------------------------- /packages/tools-ai-sdk/eslint.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "eslint/config"; 2 | import tseslint from "typescript-eslint"; 3 | import eslintPluginPrettier from "eslint-plugin-prettier"; 4 | 5 | export default defineConfig( 6 | { 7 | // Base ESLint configuration 8 | ignores: ["node_modules/**", "build/**", "dist/**", ".git/**", ".github/**"], 9 | }, 10 | { 11 | files: ["**/*.ts", "**/*.tsx"], 12 | languageOptions: { 13 | ecmaVersion: 2020, 14 | sourceType: "module", 15 | parser: tseslint.parser, 16 | parserOptions: { 17 | project: "./tsconfig.json", 18 | tsconfigRootDir: import.meta.dirname, 19 | }, 20 | globals: { 21 | // Add Node.js globals 22 | process: "readonly", 23 | require: "readonly", 24 | module: "writable", 25 | console: "readonly", 26 | }, 27 | }, 28 | // Settings for all files 29 | linterOptions: { 30 | reportUnusedDisableDirectives: true, 31 | }, 32 | plugins: { 33 | "@typescript-eslint": tseslint.plugin, 34 | prettier: eslintPluginPrettier, 35 | }, 36 | rules: { 37 | // TypeScript recommended rules 38 | ...tseslint.configs.recommended.rules, 39 | // TypeScript rules 40 | "@typescript-eslint/explicit-module-boundary-types": "off", 41 | "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }], 42 | "@typescript-eslint/no-explicit-any": "warn", 43 | // Prettier integration 44 | "prettier/prettier": "error", 45 | }, 46 | } 47 | ); 48 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: Suggest a new feature or improvement 3 | title: "[Feature]: " 4 | labels: ["enhancement"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for suggesting a feature! We appreciate your input. 10 | 11 | - type: textarea 12 | id: problem 13 | attributes: 14 | label: Problem Description 15 | description: Is your feature request related to a problem? Please describe. 16 | placeholder: I'm frustrated when... 17 | validations: 18 | required: true 19 | 20 | - type: textarea 21 | id: solution 22 | attributes: 23 | label: Proposed Solution 24 | description: Describe the solution you'd like 25 | placeholder: I would like Context7 to... 26 | validations: 27 | required: true 28 | 29 | - type: textarea 30 | id: alternatives 31 | attributes: 32 | label: Alternatives Considered 33 | description: Describe any alternative solutions or features you've considered 34 | 35 | - type: dropdown 36 | id: priority 37 | attributes: 38 | label: Priority 39 | description: How important is this feature to you? 40 | options: 41 | - Nice to have 42 | - Would improve my workflow 43 | - Blocking my usage 44 | validations: 45 | required: true 46 | 47 | - type: textarea 48 | id: additional 49 | attributes: 50 | label: Additional Context 51 | description: Add any other context, screenshots, or examples about the feature request 52 | -------------------------------------------------------------------------------- /packages/mcp/mcpb/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "dxt_version": "0.1", 3 | "name": "context7", 4 | "display_name": "Context7", 5 | "version": "1.0.1", 6 | "description": "Up-to-date Code Docs For Any Prompt", 7 | "long_description": "Context7 MCP pulls up-to-date, version-specific documentation and code examples straight from the source — and places them directly into your prompt.", 8 | "author": { 9 | "name": "Upstash", 10 | "email": "context7@upstash.com", 11 | "url": "https://upstash.com" 12 | }, 13 | "homepage": "https://context7.com", 14 | "documentation": "https://github.com/upstash/context7", 15 | "icon": "icon.png", 16 | "server": { 17 | "type": "node", 18 | "entry_point": "dist/index.js", 19 | "mcp_config": { 20 | "command": "node", 21 | "args": ["${__dirname}/dist/index.js"], 22 | "env": {} 23 | } 24 | }, 25 | "tools": [ 26 | { 27 | "name": "Resolve Context7 Library ID", 28 | "description": "Resolves a package/product name to a Context7-compatible library ID and returns a list of matching libraries." 29 | }, 30 | { 31 | "name": "Get Library Docs", 32 | "description": "Fetches up-to-date documentation for a library." 33 | } 34 | ], 35 | "compatibility": { 36 | "platforms": ["darwin", "win32", "linux"], 37 | "runtimes": { 38 | "node": ">=v18.0.0" 39 | } 40 | }, 41 | "keywords": ["vibe-coding", "developer tools", "documentation", "context"], 42 | "license": "MIT", 43 | "repository": { 44 | "type": "git", 45 | "url": "git+https://github.com/upstash/context7.git" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: [master] 7 | workflow_dispatch: 8 | 9 | concurrency: 10 | group: ${{ github.workflow }}-${{ github.ref }} 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | test: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | 19 | - name: Setup Node 20 | uses: actions/setup-node@v4 21 | with: 22 | node-version: "20" 23 | 24 | - name: Setup pnpm 25 | uses: pnpm/action-setup@v4 26 | with: 27 | version: 10 28 | 29 | - name: Get pnpm store directory 30 | id: pnpm-cache 31 | shell: bash 32 | run: | 33 | echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT 34 | 35 | - name: Cache pnpm dependencies 36 | uses: actions/cache@v4 37 | with: 38 | path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} 39 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} 40 | restore-keys: | 41 | ${{ runner.os }}-pnpm-store- 42 | 43 | - name: Install Dependencies 44 | run: pnpm install --frozen-lockfile 45 | 46 | - name: Lint 47 | run: pnpm lint:check 48 | 49 | - name: Format 50 | run: pnpm format:check 51 | 52 | - name: Build 53 | run: pnpm build 54 | 55 | - name: Typecheck 56 | run: pnpm typecheck 57 | 58 | - name: Test 59 | run: pnpm test 60 | env: 61 | AWS_REGION: ${{ secrets.AWS_REGION }} 62 | AWS_BEARER_TOKEN_BEDROCK: ${{ secrets.AWS_BEARER_TOKEN_BEDROCK }} 63 | CONTEXT7_API_KEY: ${{ secrets.CONTEXT7_API_KEY }} 64 | -------------------------------------------------------------------------------- /.github/workflows/changeset-check.yml: -------------------------------------------------------------------------------- 1 | name: Changeset Check 2 | 3 | on: 4 | pull_request: 5 | types: [opened, synchronize, reopened, labeled, unlabeled] 6 | 7 | jobs: 8 | check: 9 | name: Check for Changeset 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout Repo 13 | uses: actions/checkout@v6 14 | with: 15 | fetch-depth: 0 16 | 17 | - name: Check for changeset 18 | uses: actions/github-script@v7 19 | with: 20 | script: | 21 | const { execSync } = require('child_process'); 22 | 23 | const labels = context.payload.pull_request.labels.map(l => l.name); 24 | if (labels.includes('skip-changeset')) { 25 | console.log('Skipping changeset check for PR with skip-changeset label'); 26 | return; 27 | } 28 | 29 | const baseSha = context.payload.pull_request.base.sha; 30 | const headSha = context.payload.pull_request.head.sha; 31 | 32 | const diff = execSync( 33 | `git diff --name-only ${baseSha}...${headSha}`, 34 | { encoding: 'utf-8' } 35 | ); 36 | 37 | const hasChangeset = diff 38 | .split('\n') 39 | .some(file => file.startsWith('.changeset/') && file.endsWith('.md') && !file.includes('README')); 40 | 41 | if (!hasChangeset) { 42 | core.setFailed( 43 | 'No changeset found. Please add a changeset using `pnpm changeset` or add the "skip-changeset" label if this PR doesn\'t need one (e.g., docs, CI changes).' 44 | ); 45 | } else { 46 | console.log('Changeset found!'); 47 | } 48 | -------------------------------------------------------------------------------- /packages/mcp/src/lib/encryption.ts: -------------------------------------------------------------------------------- 1 | import { createCipheriv, randomBytes } from "crypto"; 2 | 3 | const DEFAULT_ENCRYPTION_KEY = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"; 4 | const ENCRYPTION_KEY = process.env.CLIENT_IP_ENCRYPTION_KEY || DEFAULT_ENCRYPTION_KEY; 5 | const ALGORITHM = "aes-256-cbc"; 6 | 7 | if (ENCRYPTION_KEY === DEFAULT_ENCRYPTION_KEY) { 8 | console.warn("WARNING: Using default CLIENT_IP_ENCRYPTION_KEY."); 9 | } 10 | 11 | function validateEncryptionKey(key: string): boolean { 12 | // Must be exactly 64 hex characters (32 bytes) 13 | return /^[0-9a-fA-F]{64}$/.test(key); 14 | } 15 | 16 | function encryptClientIp(clientIp: string): string { 17 | if (!validateEncryptionKey(ENCRYPTION_KEY)) { 18 | console.error("Invalid encryption key format. Must be 64 hex characters."); 19 | return clientIp; // Fallback to unencrypted 20 | } 21 | 22 | try { 23 | const iv = randomBytes(16); 24 | const cipher = createCipheriv(ALGORITHM, Buffer.from(ENCRYPTION_KEY, "hex"), iv); 25 | let encrypted = cipher.update(clientIp, "utf8", "hex"); 26 | encrypted += cipher.final("hex"); 27 | return iv.toString("hex") + ":" + encrypted; 28 | } catch (error) { 29 | console.error("Error encrypting client IP:", error); 30 | return clientIp; // Fallback to unencrypted 31 | } 32 | } 33 | 34 | export function generateHeaders( 35 | clientIp?: string, 36 | apiKey?: string, 37 | extraHeaders: Record = {} 38 | ): Record { 39 | const headers: Record = { ...extraHeaders }; 40 | if (clientIp) { 41 | headers["mcp-client-ip"] = encryptClientIp(clientIp); 42 | } 43 | if (apiKey) { 44 | headers["Authorization"] = `Bearer ${apiKey}`; 45 | } 46 | return headers; 47 | } 48 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | The following versions of Context7 MCP are currently supported with security updates: 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | 1.0.x | :white_check_mark: | 10 | 11 | We recommend always using the latest version (`@upstash/context7-mcp@latest`) to ensure you have the most recent security patches and features. 12 | 13 | ## Reporting a Vulnerability 14 | 15 | We take the security of Context7 seriously. If you discover a security vulnerability, please report it responsibly. 16 | 17 | ### How to Report 18 | 19 | - Please use GitHub's [private vulnerability reporting](https://github.com/upstash/context7/security/advisories/new) feature to submit your report 20 | - Alternatively, you can email security concerns to [context7@upstash.com](mailto:context7@upstash.com) 21 | 22 | ### What to Include 23 | 24 | - A description of the vulnerability 25 | - Steps to reproduce the issue 26 | - Potential impact of the vulnerability 27 | - Any suggested fixes (optional) 28 | 29 | ### What to Expect 30 | 31 | - **Initial Response**: We aim to acknowledge your report within 48 hours 32 | - **Status Updates**: You can expect updates on the progress every 5-7 business days 33 | - **Resolution Timeline**: We strive to resolve critical vulnerabilities within 30 days 34 | 35 | ### After Reporting 36 | 37 | - If the vulnerability is accepted, we will work on a fix and coordinate disclosure with you 38 | - We will credit reporters in our release notes (unless you prefer to remain anonymous) 39 | - If the report is declined, we will provide an explanation 40 | 41 | ### Please Do Not 42 | 43 | - Disclose the vulnerability publicly before we have addressed it 44 | - Exploit the vulnerability beyond what is necessary to demonstrate it 45 | -------------------------------------------------------------------------------- /.github/workflows/ecr-deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to AWS ECR 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | version: 7 | description: "Docker image version tag (e.g., v0.0.22)" 8 | required: true 9 | type: string 10 | 11 | jobs: 12 | build-and-push: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Checkout code 17 | uses: actions/checkout@v6 18 | 19 | - name: Configure AWS credentials 20 | uses: aws-actions/configure-aws-credentials@v5 21 | with: 22 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 23 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 24 | aws-region: ${{ secrets.AWS_REGION }} 25 | 26 | - name: Login to Amazon ECR 27 | id: login-ecr 28 | uses: aws-actions/amazon-ecr-login@v2 29 | 30 | - name: Set up Docker Buildx 31 | uses: docker/setup-buildx-action@v3 32 | 33 | - name: Build and push Docker image 34 | id: build-push 35 | uses: docker/build-push-action@v6 36 | with: 37 | context: packages/mcp 38 | file: packages/mcp/Dockerfile 39 | platforms: linux/amd64 40 | push: true 41 | tags: | 42 | ${{ secrets.ECR_REGISTRY }}/${{ secrets.ECR_REPOSITORY }}:${{ inputs.version }} 43 | cache-from: type=gha 44 | cache-to: type=gha,mode=max 45 | 46 | - name: Create GitHub Summary 47 | run: | 48 | echo "## Docker Image Deployed Successfully" >> $GITHUB_STEP_SUMMARY 49 | echo "" >> $GITHUB_STEP_SUMMARY 50 | echo "**Image Tag:** \`${{ inputs.version }}\`" >> $GITHUB_STEP_SUMMARY 51 | echo "" >> $GITHUB_STEP_SUMMARY 52 | echo "**Status:** ✅ Image pushed to AWS ECR" >> $GITHUB_STEP_SUMMARY 53 | -------------------------------------------------------------------------------- /packages/tools-ai-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@upstash/context7-tools-ai-sdk", 3 | "version": "0.1.0", 4 | "description": "Context7 tools for Vercel AI SDK", 5 | "type": "module", 6 | "main": "./dist/index.cjs", 7 | "module": "./dist/index.js", 8 | "types": "./dist/index.d.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./dist/index.d.ts", 12 | "import": "./dist/index.js", 13 | "require": "./dist/index.cjs" 14 | }, 15 | "./agent": { 16 | "types": "./dist/agent.d.ts", 17 | "import": "./dist/agent.js", 18 | "require": "./dist/agent.cjs" 19 | } 20 | }, 21 | "files": [ 22 | "dist" 23 | ], 24 | "scripts": { 25 | "build": "tsup", 26 | "dev": "tsup --watch", 27 | "test": "vitest run", 28 | "typecheck": "tsc --noEmit", 29 | "clean": "rm -rf dist" 30 | }, 31 | "peerDependencies": { 32 | "@upstash/context7-sdk": ">=0.1.0", 33 | "ai": ">=5.0.0", 34 | "zod": ">=3.24.0" 35 | }, 36 | "devDependencies": { 37 | "@upstash/context7-sdk": "workspace:*", 38 | "ai": "^5.0.0", 39 | "zod": "^3.24.0", 40 | "@ai-sdk/amazon-bedrock": "^3.0.55", 41 | "@types/node": "^22.13.14", 42 | "dotenv": "^17.2.3", 43 | "tsup": "^8.5.1", 44 | "typescript": "^5.8.2", 45 | "vitest": "^4.0.13" 46 | }, 47 | "repository": { 48 | "type": "git", 49 | "url": "git+https://github.com/upstash/context7.git", 50 | "directory": "packages/tools-ai-sdk" 51 | }, 52 | "keywords": [ 53 | "context7", 54 | "ai-sdk", 55 | "vercel", 56 | "documentation", 57 | "agent", 58 | "upstash" 59 | ], 60 | "author": "Upstash", 61 | "license": "MIT", 62 | "bugs": { 63 | "url": "https://github.com/upstash/context7/issues" 64 | }, 65 | "homepage": "https://github.com/upstash/context7#readme", 66 | "publishConfig": { 67 | "access": "public" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /docs/overview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Intro 3 | sidebarTitle: Intro 4 | --- 5 | 6 | Context7 brings up-to-date, version-specific documentation and code examples directly into your AI coding assistant. That means no more outdated code or hallucinated APIs. 7 | 8 | ## ❌ Without Context7 9 | 10 | LLMs rely on outdated or generic information about the libraries you use: 11 | 12 | - ❌ Code examples based on old training data 13 | - ❌ Hallucinated APIs that don't even exist 14 | - ❌ Generic answers for old package versions 15 | 16 | ## ✅ With Context7 17 | 18 | Context7 MCP pulls up-to-date, version-specific documentation and code examples straight from the source — and places them directly into your prompt. 19 | 20 | Add `use context7` to your prompt in Cursor: 21 | 22 | ```txt 23 | Create a Next.js middleware that checks for a valid JWT in cookies and redirects unauthenticated users to `/login`. use context7 24 | ``` 25 | 26 | ```txt 27 | Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7 28 | ``` 29 | 30 | Context7 grounds your LLM with up-to-date documentation, ensuring that it always writes high quality code. 31 | 32 | - 1️⃣ Write your prompt naturally 33 | - 2️⃣ Add `use context7` to your prompt 34 | - 3️⃣ Get working code with current APIs 35 | 36 | No tab-switching, no hallucinated APIs that don't exist, no outdated code generation. 37 | 38 | ## Next Steps 39 | 40 | 41 | 42 | Get set up in 2 minutes with your preferred AI coding assistant 43 | 44 | 45 | Master Context7 features and usage patterns 46 | 47 | 48 | Unlock higher rate limits and use yourprivate repositories 49 | 50 | 51 | -------------------------------------------------------------------------------- /docs/dashboard/usage.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Usage Statistics 3 | description: Monitor your Context7 API usage and track costs 4 | --- 5 | 6 | Track your Context7 usage with real-time metrics from the Overview tab. 7 | 8 | ![Usage statistics card showing metrics and cost breakdown](/images/dashboard/usage-stats.png) 9 | 10 | ## Metrics Overview 11 | 12 | Context7 tracks four key metrics to help you understand your usage patterns: 13 | 14 | ### Search & Query Requests 15 | 16 | The total number of API calls made to Context7: 17 | 18 | - **Search Requests**: Library search queries 19 | - **Query Requests**: Documentation retrieval calls 20 | 21 | ### Query Tokens 22 | 23 | The total number of tokens returned in API responses. This reflects how much documentation content you've retrieved. 24 | 25 | Search requests, Query requests, and Query tokens do not affect cost. 26 | 27 | ### Parsing Tokens 28 | 29 | The total tokens processed when parsing private repository documentation (Pro and Enterprise only). 30 | 31 | **How it works**: 32 | 33 | - Charged when adding a new private repository 34 | - Charged for changed content when refreshing 35 | - No charge for cached content when refreshing 36 | 37 | **Cost**: $15 per 1M tokens 38 | 39 | ### Total Cost 40 | 41 | Your monthly cost in USD (Pro and Enterprise only). 42 | 43 | **Calculation**: 44 | 45 | ``` 46 | Total Cost = Parsing Cost + Team Cost 47 | 48 | Parsing Cost = (Parsing Tokens / 1,000,000) × $15 49 | Team Cost = Number of Members × $7 50 | ``` 51 | 52 | **Example**: 53 | 54 | - Team: 4 members 55 | - Parsing: 800K tokens this month 56 | - Cost: (800K / 1M × $15) + (4 × $7) = $12 + $28 = **$40** 57 | 58 | Hover over the Total Cost to see the detailed breakdown. 59 | 60 | ## Reporting Periods 61 | 62 | **Free Plan**: Metrics display daily usage (resets every 24 hours) 63 | 64 | **Pro & Enterprise Plans**: Metrics display monthly usage (resets on your billing date) 65 | -------------------------------------------------------------------------------- /.github/workflows/publish-mcp.yml: -------------------------------------------------------------------------------- 1 | name: Publish to MCP Registry 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | version: 7 | description: "Version to publish (defaults to package.json version)" 8 | required: false 9 | type: string 10 | 11 | jobs: 12 | publish-mcp: 13 | name: Publish to MCP Registry 14 | runs-on: ubuntu-latest 15 | permissions: 16 | id-token: write # Required for OIDC authentication with MCP Registry 17 | contents: read 18 | steps: 19 | - name: Checkout Repo 20 | uses: actions/checkout@v6 21 | 22 | - name: Setup Node 23 | uses: actions/setup-node@v4 24 | with: 25 | node-version: lts/* 26 | 27 | - name: Set version 28 | run: | 29 | if [ -n "${{ inputs.version }}" ]; then 30 | VERSION="${{ inputs.version }}" 31 | # Remove 'v' prefix if it exists 32 | VERSION="${VERSION#v}" 33 | else 34 | VERSION=$(node -p "require('./packages/mcp/package.json').version") 35 | fi 36 | echo "VERSION=$VERSION" >> $GITHUB_ENV 37 | echo "Publishing version: $VERSION" 38 | 39 | - name: Update package version in server.json 40 | run: | 41 | echo $(jq --arg v "${{ env.VERSION }}" '.version = $v | .packages[0].version = $v' server.json) > server.json 42 | 43 | - name: Validate server.json 44 | run: npx mcp-registry-validator validate server.json 45 | 46 | - name: Install MCP Publisher 47 | run: | 48 | curl -L "https://github.com/modelcontextprotocol/registry/releases/download/v1.3.3/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher 49 | 50 | - name: Login to MCP Registry 51 | run: ./mcp-publisher login github-oidc 52 | 53 | - name: Publish to MCP Registry 54 | run: ./mcp-publisher publish 55 | -------------------------------------------------------------------------------- /packages/mcp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@upstash/context7-mcp", 3 | "version": "1.0.31", 4 | "mcpName": "io.github.upstash/context7", 5 | "description": "MCP server for Context7", 6 | "scripts": { 7 | "build": "tsc && chmod 755 dist/index.js", 8 | "test": "echo \"No tests yet\"", 9 | "typecheck": "tsc --noEmit", 10 | "lint": "eslint .", 11 | "lint:check": "eslint .", 12 | "format": "prettier --write .", 13 | "format:check": "prettier --check .", 14 | "dev": "tsc --watch", 15 | "start": "node dist/index.js --transport http", 16 | "pack-mcpb": "pnpm install && pnpm run build && rm -rf node_modules && pnpm install --prod && mv mcpb/.mcpbignore .mcpbignore && mv mcpb/manifest.json manifest.json && mv public/icon.png icon.png && mcpb validate manifest.json && mcpb pack . mcpb/context7.mcpb && mv manifest.json mcpb/manifest.json && mv .mcpbignore mcpb/.mcpbignore && mv icon.png public/icon.png && bun install" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "git+https://github.com/upstash/context7.git", 21 | "directory": "packages/mcp" 22 | }, 23 | "keywords": [ 24 | "modelcontextprotocol", 25 | "mcp", 26 | "context7", 27 | "vibe-coding", 28 | "developer tools", 29 | "documentation", 30 | "context" 31 | ], 32 | "author": "abdush", 33 | "license": "MIT", 34 | "type": "module", 35 | "bin": { 36 | "context7-mcp": "dist/index.js" 37 | }, 38 | "files": [ 39 | "dist", 40 | "LICENSE", 41 | "README.md" 42 | ], 43 | "bugs": { 44 | "url": "https://github.com/upstash/context7/issues" 45 | }, 46 | "homepage": "https://github.com/upstash/context7#readme", 47 | "dependencies": { 48 | "@modelcontextprotocol/sdk": "^1.17.5", 49 | "@types/express": "^5.0.4", 50 | "commander": "^14.0.0", 51 | "express": "^5.1.0", 52 | "undici": "^6.6.3", 53 | "zod": "^3.24.2" 54 | }, 55 | "devDependencies": { 56 | "@types/node": "^22.13.14", 57 | "typescript": "^5.8.2" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@upstash/context7", 3 | "private": true, 4 | "version": "1.0.0", 5 | "description": "Context7 monorepo - Documentation tools and SDKs", 6 | "workspaces": [ 7 | "packages/*" 8 | ], 9 | "scripts": { 10 | "build": "pnpm -r run build", 11 | "build:sdk": "pnpm --filter @upstash/context7-sdk build", 12 | "build:mcp": "pnpm --filter @upstash/context7-mcp build", 13 | "build:ai-sdk": "pnpm --filter @upstash/context7-tools-ai-sdk build", 14 | "typecheck": "pnpm -r run typecheck", 15 | "test": "pnpm -r run test", 16 | "test:sdk": "pnpm --filter @upstash/context7-sdk test", 17 | "test:tools-ai-sdk": "pnpm --filter @upstash/context7-tools-ai-sdk test", 18 | "clean": "pnpm -r run clean && rm -rf node_modules", 19 | "lint": "pnpm -r run lint", 20 | "lint:check": "pnpm -r run lint:check", 21 | "format": "pnpm -r run format", 22 | "format:check": "pnpm -r run format:check", 23 | "release": "pnpm build && changeset publish", 24 | "release:snapshot": "changeset version --snapshot canary && pnpm build && changeset publish --tag canary --no-git-tag" 25 | }, 26 | "repository": { 27 | "type": "git", 28 | "url": "git+https://github.com/upstash/context7.git" 29 | }, 30 | "keywords": [ 31 | "modelcontextprotocol", 32 | "mcp", 33 | "context7", 34 | "vibe-coding", 35 | "developer tools", 36 | "documentation", 37 | "context" 38 | ], 39 | "author": "abdush", 40 | "license": "MIT", 41 | "bugs": { 42 | "url": "https://github.com/upstash/context7/issues" 43 | }, 44 | "homepage": "https://github.com/upstash/context7#readme", 45 | "devDependencies": { 46 | "@changesets/cli": "^2.29.7", 47 | "@types/node": "^22.13.14", 48 | "@typescript-eslint/eslint-plugin": "^8.28.0", 49 | "@typescript-eslint/parser": "^8.28.0", 50 | "eslint": "^9.34.0", 51 | "eslint-config-prettier": "^10.1.1", 52 | "eslint-plugin-prettier": "^5.2.5", 53 | "prettier": "^3.6.2", 54 | "typescript": "^5.8.2", 55 | "typescript-eslint": "^8.28.0" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/tools-ai-sdk/src/agents/context7.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Experimental_Agent as Agent, 3 | type Experimental_AgentSettings as AgentSettings, 4 | type ToolSet, 5 | stepCountIs, 6 | } from "ai"; 7 | import { resolveLibrary, getLibraryDocs } from "@tools"; 8 | import { AGENT_PROMPT } from "@prompts"; 9 | 10 | /** 11 | * Configuration for Context7 agent. 12 | */ 13 | export interface Context7AgentConfig extends AgentSettings { 14 | /** 15 | * Context7 API key. If not provided, uses the CONTEXT7_API_KEY environment variable. 16 | */ 17 | apiKey?: string; 18 | 19 | /** 20 | * Default maximum number of documentation results per request. 21 | * @default 10 22 | */ 23 | defaultMaxResults?: number; 24 | } 25 | 26 | /** 27 | * Context7 documentation search agent 28 | * 29 | * The agent follows a multi-step workflow: 30 | * 1. Resolves library names to Context7 library IDs 31 | * 2. Fetches documentation for the resolved library 32 | * 3. Provides answers with code examples 33 | * 34 | * @example 35 | * ```typescript 36 | * import { Context7Agent } from '@upstash/context7-tools-ai-sdk'; 37 | * import { anthropic } from '@ai-sdk/anthropic'; 38 | * 39 | * const agent = new Context7Agent({ 40 | * model: anthropic('claude-sonnet-4-20250514'), 41 | * apiKey: 'your-context7-api-key', 42 | * }); 43 | * 44 | * const result = await agent.generate({ 45 | * prompt: 'How do I use React Server Components?', 46 | * }); 47 | * ``` 48 | */ 49 | export class Context7Agent extends Agent { 50 | constructor(config: Context7AgentConfig) { 51 | const { 52 | model, 53 | stopWhen = stepCountIs(5), 54 | system, 55 | apiKey, 56 | defaultMaxResults, 57 | tools, 58 | ...agentSettings 59 | } = config; 60 | 61 | const context7Config = { apiKey, defaultMaxResults }; 62 | 63 | super({ 64 | ...agentSettings, 65 | model, 66 | system: system || AGENT_PROMPT, 67 | tools: { 68 | ...tools, 69 | resolveLibrary: resolveLibrary(context7Config), 70 | getLibraryDocs: getLibraryDocs(context7Config), 71 | }, 72 | stopWhen, 73 | }); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /docs/dashboard/team.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Team Management 3 | description: Invite members and manage team permissions 4 | --- 5 | 6 | Add team members, assign roles, and manage access to your Context7 dashboard from the [members tab](https://context7.com/dashboard?tab=members). 7 | 8 | ![Members tab displaying team members list with owner, admins, and developers](/images/dashboard/members-tab.png) 9 | 10 | ## Creating a Team 11 | 12 | ![Create team dropdown](/images/dashboard/user-dropdown.png) 13 | 14 | 1. Click "Create a team" from the top left dropdown 15 | 2. Enter team name 16 | 17 | You must have a Pro or Enterprise plan to create a team. 18 | 19 | ## Roles 20 | 21 | | Permission | Owner | Admin | Developer | 22 | | --------------------- | ----- | ----- | --------- | 23 | | View dashboard | ✓ | ✓ | ✓ | 24 | | Create API keys | ✓ | ✓ | ✓ | 25 | | Manage team members | ✓ | ✓ | ✗ | 26 | | Manage library access | ✓ | ✓ | ✗ | 27 | | Manage private repos | ✓ | ✓ | ✗ | 28 | | Rename team | ✓ | ✗ | ✗ | 29 | | Delete team | ✓ | ✗ | ✗ | 30 | 31 | ## Inviting Members 32 | 33 | 1. Enter member email 34 | 2. Select role (Developer or Admin) 35 | 3. Click "Add" 36 | 4. Member receives an invitation email 37 | 5. Once they sign in, they are automatically added to the team 38 | 39 | The invitation will remain pending until they sign in. 40 | 41 | ## Team Settings 42 | 43 | If you are the owner of the team, you can rename or delete the team under the overview tab. 44 | 45 | ![Team management card](/images/dashboard/team-management-card.png) 46 | 47 | Deleting a team is permanent. All members lose access immediately. 48 | 49 | ## Billing 50 | 51 | **Pro Plan**: $7 per member per month 52 | 53 | Example: Owner + 3 members = $28/month 54 | 55 | See [Billing](/dashboard/billing) for payment management. 56 | 57 | ## Limits 58 | 59 | | Plan | Max Members | 60 | | ---------- | ----------------- | 61 | | Free | 1 (personal only) | 62 | | Pro | 20 | 63 | | Enterprise | Unlimited | 64 | -------------------------------------------------------------------------------- /docs/contact.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Contact & Support 3 | sidebarTitle: Contact 4 | --- 5 | 6 | Get help and support for Context7. 7 | 8 | ## Community Support 9 | 10 | ### Discord 11 | 12 | Join our Discord community for: 13 | 14 | - Quick answers to common questions 15 | - Tips and best practices from other users 16 | - Announcements about new features and updates 17 | - Direct interaction with the team 18 | 19 | [Join Discord](https://upstash.com/discord) 20 | 21 | ### GitHub 22 | 23 | For bug reports, feature requests, and technical discussions: 24 | 25 | - **Report Issues**: [github.com/upstash/context7/issues](https://github.com/upstash/context7/issues) 26 | - **View Source Code**: [github.com/upstash/context7](https://github.com/upstash/context7) 27 | - **Contribute**: Submit pull requests to improve Context7 28 | 29 | ## Social Media 30 | 31 | Stay updated with the latest news and updates: 32 | 33 | - **X (Twitter)**: [@context7ai](https://x.com/context7ai) 34 | - **Website**: [context7.com](https://context7.com) 35 | 36 | ## Enterprise Support 37 | 38 | For enterprise customers and custom solutions: 39 | 40 | - **Email**: context7@upstash.com 41 | - **Enterprise Plans**: Contact us for dedicated support, custom SLAs, and advanced features 42 | 43 | ## Documentation 44 | 45 | Explore our comprehensive documentation: 46 | 47 | - [Getting Started](/overview) - Quick introduction to Context7 48 | - [Installation Guide](/installation) - Setup instructions for all platforms 49 | - [Usage Guide](/usage) - Tips and best practices 50 | - [API Reference](/api) - Complete API documentation 51 | - [Troubleshooting](/troubleshooting) - Common issues and solutions 52 | - [Security & Privacy](/security) - Security practices and compliance 53 | 54 | ## Report Security Issues 55 | 56 | If you discover a security vulnerability: 57 | 58 | 1. **Do not** publicly disclose the issue 59 | 2. Report via [GitHub Security](https://github.com/upstash/context7/security) 60 | 3. Include detailed steps to reproduce 61 | 4. Allow reasonable time for us to address the issue 62 | 63 | We take all security reports seriously and will respond promptly. 64 | 65 | ## Feedback 66 | 67 | Help us improve Context7: 68 | 69 | - Use the thumbs rating on documentation pages 70 | - Suggest edits directly on any page 71 | - Raise issues for bugs or feature requests 72 | -------------------------------------------------------------------------------- /packages/sdk/src/client.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | Context7Config, 3 | SearchLibraryResponse, 4 | GetDocsOptions, 5 | CodeDocsResponse, 6 | InfoDocsResponse, 7 | TextDocsResponse, 8 | } from "@commands/types"; 9 | import { Context7Error } from "@error"; 10 | import { HttpClient } from "@http"; 11 | import { SearchLibraryCommand, GetDocsCommand } from "@commands/index"; 12 | 13 | const DEFAULT_BASE_URL = "https://context7.com/api"; 14 | const API_KEY_PREFIX = "ctx7sk"; 15 | 16 | export type * from "@commands/types"; 17 | export * from "@error"; 18 | 19 | export class Context7 { 20 | private httpClient: HttpClient; 21 | 22 | constructor(config: Context7Config = {}) { 23 | const apiKey = config.apiKey || process.env.CONTEXT7_API_KEY; 24 | 25 | if (!apiKey) { 26 | throw new Context7Error( 27 | "API key is required. Pass it in the config or set CONTEXT7_API_KEY environment variable." 28 | ); 29 | } 30 | 31 | if (!apiKey.startsWith(API_KEY_PREFIX)) { 32 | console.warn(`API key should start with '${API_KEY_PREFIX}'`); 33 | } 34 | 35 | this.httpClient = new HttpClient({ 36 | baseUrl: DEFAULT_BASE_URL, 37 | headers: { 38 | Authorization: `Bearer ${apiKey}`, 39 | }, 40 | retry: { 41 | retries: 5, 42 | backoff: (retryCount) => Math.exp(retryCount) * 50, 43 | }, 44 | cache: "no-store", 45 | }); 46 | } 47 | 48 | async searchLibrary(query: string): Promise { 49 | const command = new SearchLibraryCommand(query); 50 | return await command.exec(this.httpClient); 51 | } 52 | 53 | async getDocs( 54 | libraryId: string, 55 | options: GetDocsOptions & { format: "txt" } 56 | ): Promise; 57 | 58 | async getDocs( 59 | libraryId: string, 60 | options: GetDocsOptions & { format?: "json"; mode: "info" } 61 | ): Promise; 62 | 63 | async getDocs( 64 | libraryId: string, 65 | options?: GetDocsOptions & { format?: "json"; mode?: "code" } 66 | ): Promise; 67 | 68 | async getDocs( 69 | libraryId: string, 70 | options?: GetDocsOptions 71 | ): Promise { 72 | const command = new GetDocsCommand(libraryId, options); 73 | return await command.exec(this.httpClient); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /packages/sdk/README.md: -------------------------------------------------------------------------------- 1 | # Upstash Context7 SDK 2 | 3 | > ⚠️ **Work in Progress**: This SDK is currently under active development. The API is subject to change and may introduce breaking changes in future releases. 4 | 5 | `@upstash/context7-sdk` is an HTTP/REST based client for TypeScript, built on top of the [Context7 API](https://context7.com). 6 | 7 | ## Why Context7? 8 | 9 | LLMs rely on outdated or generic training data about the libraries you use. This leads to: 10 | 11 | - Code examples based on year-old training data 12 | - Hallucinated APIs that don't exist 13 | - Generic answers for old package versions 14 | 15 | Context7 solves this by providing up-to-date, version-specific documentation and code examples directly from the source. Use this SDK to: 16 | 17 | - Build AI agents with accurate, current documentation context 18 | - Create RAG pipelines with reliable library documentation 19 | - Power code generation tools with real API references 20 | 21 | ## Quick Start 22 | 23 | ### Install 24 | 25 | ```bash 26 | npm install @upstash/context7-sdk 27 | ``` 28 | 29 | ### Get API Key 30 | 31 | Get your API key from [Context7](https://context7.com) 32 | 33 | ## Basic Usage 34 | 35 | ```ts 36 | import { Context7 } from "@upstash/context7-sdk"; 37 | 38 | const client = new Context7({ 39 | apiKey: "", 40 | }); 41 | 42 | // Search for libraries in the Context7 database 43 | const libraries = await client.searchLibrary("react"); 44 | console.log(libraries.results); 45 | 46 | // Query the documentation with specific topics 47 | const filteredDocs = await client.getDocs("/facebook/react", { 48 | topic: "hooks", 49 | limit: 10, 50 | page: 1, 51 | }); 52 | 53 | // Get documentation as JSON by default 54 | const docs = await client.getDocs("/vercel/next.js"); 55 | console.log(docs.snippets); 56 | 57 | // Get documentation as TXT 58 | const codeDocs = await client.getDocs("/mongodb/docs", { 59 | format: "txt", 60 | mode: "code", 61 | }); 62 | console.log(codeDocs.content); 63 | ``` 64 | 65 | ## Configuration 66 | 67 | ### Environment Variables 68 | 69 | You can set your API key via environment variable: 70 | 71 | ```sh 72 | CONTEXT7_API_KEY=ctx7sk-... 73 | ``` 74 | 75 | Then initialize without options: 76 | 77 | ```ts 78 | const client = new Context7(); 79 | ``` 80 | 81 | ## Docs 82 | 83 | See the [documentation](https://context7.com/docs/sdks/ts/getting-started) for details. 84 | 85 | ## Contributing 86 | 87 | ### Running tests 88 | 89 | ```sh 90 | pnpm test 91 | ``` 92 | 93 | ### Building 94 | 95 | ```sh 96 | pnpm build 97 | ``` 98 | -------------------------------------------------------------------------------- /docs/integrations/code-rabbit.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: CodeRabbit 3 | sidebarTitle: CodeRabbit 4 | description: AI-powered code review tool 5 | --- 6 | 7 | [CodeRabbit](https://coderabbit.ai) is an AI-powered code review tool that automatically reviews pull requests. By connecting Context7 as an MCP server, CodeRabbit can access up-to-date library documentation during reviews, helping it verify implementations against the latest API references and best practices. 8 | 9 | ## Setup 10 | 11 | 12 | 13 | Go to your [CodeRabbit dashboard](https://app.coderabbit.ai) and navigate to **Integrations** → **MCP Servers**. 14 | 15 | ![Integrations tab](/images/integrations/coderabbit/integrations-tab.png) 16 | 17 | 18 | Click the **Add** button next to **Context7** MCP server. 19 | 20 | Add the following header for higher rate limits: 21 | 22 | | Header | Value | 23 | |--------|-------| 24 | | `CONTEXT7_API_KEY` | Your API key from the [Context7 dashboard](https://context7.com/dashboard) | 25 | 26 | ```json 27 | { 28 | "CONTEXT7_API_KEY": "YOUR_API_KEY" 29 | } 30 | ``` 31 | 32 | ![Add server modal](/images/integrations/coderabbit/add-server-modal.png) 33 | 34 | 35 | Click the **Connect** button to connect the server. 36 | 37 | ![Server connected](/images/integrations/coderabbit/server-connected.png) 38 | 39 | 40 | To use Context7 with public repositories, go to **Organization Settings** → **Configuration** → **Knowledge Base**. In the MCP section, select **Enabled** instead of **Auto** and click **Apply Changes**. 41 | 42 | ![Update MCP settings](/images/integrations/coderabbit/update-mcp-settings.png) 43 | 44 | 45 | 46 | ## Usage Guidance 47 | 48 | In the **Usage Guidance** field, you can instruct CodeRabbit on how to use Context7 during reviews. For example: 49 | 50 | ``` 51 | Use Context7 to look up documentation for any libraries used in the code being reviewed. 52 | Verify that API usage matches the latest documentation and flag any deprecated patterns. 53 | ``` 54 | 55 | ## How It Works 56 | 57 | Once connected, CodeRabbit will query Context7 for relevant library documentation when reviewing pull requests. This helps CodeRabbit: 58 | 59 | - Verify correct API usage against the latest documentation 60 | - Identify deprecated methods or patterns 61 | - Suggest improvements based on library best practices 62 | - Provide more accurate and informed review comments 63 | -------------------------------------------------------------------------------- /packages/tools-ai-sdk/src/tools/resolve-library.ts: -------------------------------------------------------------------------------- 1 | import { tool } from "ai"; 2 | import { z } from "zod"; 3 | import { Context7 } from "@upstash/context7-sdk"; 4 | import { RESOLVE_LIBRARY_DESCRIPTION } from "@prompts"; 5 | import type { Context7ToolsConfig } from "./types"; 6 | 7 | /** 8 | * Tool to resolve a library name to a Context7-compatible library ID. 9 | * 10 | * Can be called with or without configuration. Uses CONTEXT7_API_KEY environment 11 | * variable for authentication when no API key is provided. 12 | * 13 | * @param config Optional configuration options 14 | * @returns AI SDK tool for library resolution 15 | * 16 | * @example 17 | * ```typescript 18 | * import { resolveLibrary, getLibraryDocs } from '@upstash/context7-tools-ai-sdk'; 19 | * import { generateText, stepCountIs } from 'ai'; 20 | * import { openai } from '@ai-sdk/openai'; 21 | * 22 | * const { text } = await generateText({ 23 | * model: openai('gpt-4o'), 24 | * prompt: 'Find React documentation about hooks', 25 | * tools: { 26 | * resolveLibrary: resolveLibrary(), 27 | * getLibraryDocs: getLibraryDocs(), 28 | * }, 29 | * stopWhen: stepCountIs(5), 30 | * }); 31 | * ``` 32 | */ 33 | export function resolveLibrary(config: Context7ToolsConfig = {}) { 34 | const { apiKey } = config; 35 | const getClient = () => new Context7({ apiKey }); 36 | 37 | return tool({ 38 | description: RESOLVE_LIBRARY_DESCRIPTION, 39 | inputSchema: z.object({ 40 | libraryName: z 41 | .string() 42 | .describe("Library name to search for and retrieve a Context7-compatible library ID."), 43 | }), 44 | execute: async ({ libraryName }: { libraryName: string }) => { 45 | try { 46 | const client = getClient(); 47 | const response = await client.searchLibrary(libraryName); 48 | 49 | if (!response.results || response.results.length === 0) { 50 | return { 51 | success: false, 52 | error: "No libraries found matching your query.", 53 | suggestions: "Try a different search term or check the library name.", 54 | }; 55 | } 56 | 57 | return { 58 | success: true, 59 | results: response.results, 60 | totalResults: response.results.length, 61 | }; 62 | } catch (error) { 63 | return { 64 | success: false, 65 | error: error instanceof Error ? error.message : "Failed to search libraries", 66 | suggestions: "Check your API key and try again, or try a different search term.", 67 | }; 68 | } 69 | }, 70 | }); 71 | } 72 | -------------------------------------------------------------------------------- /packages/sdk/src/commands/types.ts: -------------------------------------------------------------------------------- 1 | export interface Context7Config { 2 | apiKey?: string; 3 | } 4 | 5 | export interface SearchResult { 6 | id: string; 7 | title: string; 8 | description: string; 9 | branch: string; 10 | lastUpdateDate: string; 11 | state: "initial" | "finalized" | "processing" | "error" | "delete"; 12 | totalTokens: number; 13 | totalSnippets: number; 14 | stars?: number; 15 | trustScore?: number; 16 | benchmarkScore?: number; 17 | versions?: string[]; 18 | } 19 | 20 | export interface APIResponseMetadata { 21 | authentication: "none" | "personal" | "team"; 22 | } 23 | 24 | export interface SearchLibraryResponse { 25 | results: SearchResult[]; 26 | metadata: APIResponseMetadata; 27 | } 28 | 29 | export interface CodeExample { 30 | language: string; 31 | code: string; 32 | } 33 | 34 | export interface CodeSnippet { 35 | codeTitle: string; 36 | codeDescription: string; 37 | codeLanguage: string; 38 | codeTokens: number; 39 | codeId: string; 40 | pageTitle: string; 41 | codeList: CodeExample[]; 42 | } 43 | 44 | export interface InfoSnippet { 45 | pageId?: string; 46 | breadcrumb?: string; 47 | content: string; 48 | contentTokens: number; 49 | } 50 | 51 | export interface Pagination { 52 | page: number; 53 | limit: number; 54 | totalPages: number; 55 | hasNext: boolean; 56 | hasPrev: boolean; 57 | } 58 | 59 | export interface DocsResponseBase { 60 | pagination: Pagination; 61 | totalTokens: number; 62 | } 63 | 64 | export interface CodeDocsResponse extends DocsResponseBase { 65 | snippets: CodeSnippet[]; 66 | } 67 | 68 | export interface InfoDocsResponse extends DocsResponseBase { 69 | snippets: InfoSnippet[]; 70 | } 71 | 72 | export interface TextDocsResponse extends DocsResponseBase { 73 | content: string; 74 | } 75 | 76 | export interface GetDocsOptions { 77 | /** 78 | * Library version to fetch docs for. 79 | * @example "18.0.0" 80 | */ 81 | version?: string; 82 | /** 83 | * Page number for pagination. 84 | */ 85 | page?: number; 86 | /** 87 | * Filter docs by topic. 88 | */ 89 | topic?: string; 90 | /** 91 | * Number of results per page. 92 | */ 93 | limit?: number; 94 | /** 95 | * Type of documentation to fetch. 96 | * @default "code" 97 | */ 98 | mode?: "info" | "code"; 99 | /** 100 | * Response format. 101 | * @default "json" 102 | */ 103 | format?: "json" | "txt"; 104 | } 105 | 106 | export type QueryParams = Record; 107 | -------------------------------------------------------------------------------- /packages/mcp/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { SearchResponse, SearchResult } from "./types.js"; 2 | 3 | /** 4 | * Maps numeric source reputation score to an interpretable label for LLM consumption. 5 | * 6 | * @returns One of: "High", "Medium", "Low", or "Unknown" 7 | */ 8 | function getSourceReputationLabel( 9 | sourceReputation?: number 10 | ): "High" | "Medium" | "Low" | "Unknown" { 11 | if (sourceReputation === undefined || sourceReputation < 0) return "Unknown"; 12 | if (sourceReputation >= 7) return "High"; 13 | if (sourceReputation >= 4) return "Medium"; 14 | return "Low"; 15 | } 16 | 17 | /** 18 | * Formats a search result into a human-readable string representation. 19 | * Only shows code snippet count and GitHub stars when available (not equal to -1). 20 | * 21 | * @param result The SearchResult object to format 22 | * @returns A formatted string with library information 23 | */ 24 | export function formatSearchResult(result: SearchResult): string { 25 | // Always include these basic details 26 | const formattedResult = [ 27 | `- Title: ${result.title}`, 28 | `- Context7-compatible library ID: ${result.id}`, 29 | `- Description: ${result.description}`, 30 | ]; 31 | 32 | // Only add code snippets count if it's a valid value 33 | if (result.totalSnippets !== -1 && result.totalSnippets !== undefined) { 34 | formattedResult.push(`- Code Snippets: ${result.totalSnippets}`); 35 | } 36 | 37 | // Always add categorized source reputation 38 | const reputationLabel = getSourceReputationLabel(result.trustScore); 39 | formattedResult.push(`- Source Reputation: ${reputationLabel}`); 40 | 41 | // Only add benchmark score if it's a valid value 42 | if (result.benchmarkScore !== undefined && result.benchmarkScore > 0) { 43 | formattedResult.push(`- Benchmark Score: ${result.benchmarkScore}`); 44 | } 45 | 46 | // Only add versions if it's a valid value 47 | if (result.versions !== undefined && result.versions.length > 0) { 48 | formattedResult.push(`- Versions: ${result.versions.join(", ")}`); 49 | } 50 | 51 | // Join all parts with newlines 52 | return formattedResult.join("\n"); 53 | } 54 | 55 | /** 56 | * Formats a search response into a human-readable string representation. 57 | * Each result is formatted using formatSearchResult. 58 | * 59 | * @param searchResponse The SearchResponse object to format 60 | * @returns A formatted string with search results 61 | */ 62 | export function formatSearchResults(searchResponse: SearchResponse): string { 63 | if (!searchResponse.results || searchResponse.results.length === 0) { 64 | return "No documentation libraries found matching your query."; 65 | } 66 | 67 | const formattedResults = searchResponse.results.map(formatSearchResult); 68 | return formattedResults.join("\n----------\n"); 69 | } 70 | -------------------------------------------------------------------------------- /docs/dashboard/private-repositories.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Private Repositories 3 | description: Add and manage private repository documentation 4 | --- 5 | 6 | Add your private GitHub, GitLab, or Bitbucket repositories to Context7 to make your internal documentation available to AI coding assistants. 7 | 8 | ![Private Repositories card showing a table of added repositories](/images/dashboard/private-repos-card.png) 9 | 10 | ## Adding Private Repositories 11 | 12 | Follow these steps to add a private repository: 13 | 14 | 1. Go to the [Add Library](https://context7.com/add-library) page 15 | 2. **Connect your account** 16 | - Choose GitHub, GitLab, or Bitbucket 17 | - Authorize Context7 to access your repositories 18 | 3. **Select a repository** from your account 19 | 4. **Submit** for parsing 20 | 21 | You must have a Pro or Enterprise plan to add private repositories. 22 | 23 | ## Repository Management 24 | 25 | ### Refreshing Documentation 26 | 27 | Keep your private documentation up to date: 28 | 29 | 1. **Click "Refresh"** next to the repository 30 | 2. Context7 re-parses the repository 31 | 3. **You're only charged for changed content** - cached pages are free 32 | 33 | **When to refresh**: 34 | 35 | - After major documentation updates 36 | - After releasing new features 37 | - When you notice outdated information 38 | 39 | Refresh private repos only after significant documentation changes to minimize costs. 40 | 41 | ### Removing Repositories 42 | 43 | To remove a private repository: 44 | 45 | 1. **Click "Remove"** next to the repository 46 | 2. **Confirm deletion** in the modal 47 | 3. Repository documentation becomes unavailable immediately 48 | 49 | 50 | This action is permanent. The repository will no longer be accessible via the API. 51 | 52 | 53 | ## Permissions 54 | 55 | Access to private repository management is restricted by role. Only Owners and Admins can add, refresh, or remove private repositories. Developers can view repository documentation but cannot manage repositories. 56 | 57 | See [Team Management](/dashboard/team#roles) for the complete permissions table for all team roles. 58 | 59 | ## Configuration 60 | 61 | ### Using `context7.json` 62 | 63 | Add a `context7.json` file to your repository root for better control over parsing: 64 | 65 | ```json 66 | { 67 | "$schema": "https://context7.com/schema/context7.json", 68 | "projectTitle": "Your Project Name", 69 | "description": "Brief description of your project", 70 | "folders": ["docs", "guides"], 71 | "excludeFolders": ["tests", "dist", "node_modules"], 72 | "excludeFiles": ["CHANGELOG.md"], 73 | "rules": ["Always validate user input", "Use TypeScript strict mode"] 74 | } 75 | ``` 76 | 77 | See the [Adding Libraries](/adding-libraries) page for complete configuration options. 78 | -------------------------------------------------------------------------------- /packages/tools-ai-sdk/README.md: -------------------------------------------------------------------------------- 1 | # Upstash Context7 AI SDK 2 | 3 | `@upstash/context7-tools-ai-sdk` provides [Vercel AI SDK](https://ai-sdk.dev/) compatible tools and agents that give your AI applications access to up to date library documentation through Context7. 4 | 5 | Use this package to: 6 | 7 | - Add documentation lookup tools to your AI SDK workflows with `generateText` or `streamText` 8 | - Create documentation aware agents using the pre-configured `Context7Agent` 9 | - Build RAG pipelines that retrieve accurate, version specific code examples 10 | 11 | The package provides two main tools: 12 | 13 | - `resolveLibrary` - Searches Context7's database to find the correct library ID 14 | - `getLibraryDocs` - Fetches documentation for a specific library with optional topic filtering 15 | 16 | ## Quick Start 17 | 18 | ### Install 19 | 20 | ```bash 21 | npm install @upstash/context7-tools-ai-sdk @upstash/context7-sdk ai zod 22 | ``` 23 | 24 | ### Get API Key 25 | 26 | Get your API key from [Context7](https://context7.com) 27 | 28 | ## Usage 29 | 30 | ### Using Tools with `generateText` 31 | 32 | ```typescript 33 | import { resolveLibrary, getLibraryDocs } from "@upstash/context7-tools-ai-sdk"; 34 | import { generateText, stepCountIs } from "ai"; 35 | import { openai } from "@ai-sdk/openai"; 36 | 37 | const { text } = await generateText({ 38 | model: openai("gpt-4o"), 39 | prompt: "How do I use React Server Components?", 40 | tools: { 41 | resolveLibrary: resolveLibrary(), 42 | getLibraryDocs: getLibraryDocs(), 43 | }, 44 | stopWhen: stepCountIs(5), 45 | }); 46 | 47 | console.log(text); 48 | ``` 49 | 50 | ### Using the Context7 Agent 51 | 52 | The package provides a pre-configured agent that handles the multi-step workflow automatically: 53 | 54 | ```typescript 55 | import { Context7Agent } from "@upstash/context7-tools-ai-sdk"; 56 | import { anthropic } from "@ai-sdk/anthropic"; 57 | 58 | const agent = new Context7Agent({ 59 | model: anthropic("claude-sonnet-4-20250514"), 60 | }); 61 | 62 | const { text } = await agent.generate({ 63 | prompt: "How do I set up routing in Next.js?", 64 | }); 65 | 66 | console.log(text); 67 | ``` 68 | 69 | ## Configuration 70 | 71 | ### Environment Variables 72 | 73 | Set your API key via environment variable: 74 | 75 | ```sh 76 | CONTEXT7_API_KEY=ctx7sk-... 77 | ``` 78 | 79 | Then use tools and agents without explicit configuration: 80 | 81 | ```typescript 82 | const tool = resolveLibrary(); // Uses CONTEXT7_API_KEY automatically 83 | ``` 84 | 85 | ## Docs 86 | 87 | See the [documentation](https://context7.com/docs/agentic-tools/ai-sdk/getting-started) for details. 88 | 89 | ## Contributing 90 | 91 | ### Running tests 92 | 93 | ```sh 94 | pnpm test 95 | ``` 96 | 97 | ### Building 98 | 99 | ```sh 100 | pnpm build 101 | ``` 102 | -------------------------------------------------------------------------------- /public/context7-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/public/logo/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/public/logo/logo-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore 2 | 3 | # Logs 4 | 5 | logs 6 | _.log 7 | npm-debug.log_ 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | .pnpm-debug.log* 12 | 13 | # Caches 14 | 15 | .cache 16 | 17 | # Diagnostic reports (https://nodejs.org/api/report.html) 18 | 19 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json 20 | 21 | # Runtime data 22 | 23 | pids 24 | _.pid 25 | _.seed 26 | *.pid.lock 27 | 28 | # Directory for instrumented libs generated by jscoverage/JSCover 29 | 30 | lib-cov 31 | 32 | # Coverage directory used by tools like istanbul 33 | 34 | coverage 35 | *.lcov 36 | 37 | # nyc test coverage 38 | 39 | .nyc_output 40 | 41 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 42 | 43 | .grunt 44 | 45 | # Bower dependency directory (https://bower.io/) 46 | 47 | bower_components 48 | 49 | # node-waf configuration 50 | 51 | .lock-wscript 52 | 53 | # Compiled binary addons (https://nodejs.org/api/addons.html) 54 | 55 | build/Release 56 | 57 | # Dependency directories 58 | 59 | node_modules/ 60 | jspm_packages/ 61 | 62 | # Snowpack dependency directory (https://snowpack.dev/) 63 | 64 | web_modules/ 65 | 66 | # TypeScript cache 67 | 68 | *.tsbuildinfo 69 | 70 | # Optional npm cache directory 71 | 72 | .npm 73 | 74 | # Optional eslint cache 75 | 76 | .eslintcache 77 | 78 | # Optional stylelint cache 79 | 80 | .stylelintcache 81 | 82 | # Microbundle cache 83 | 84 | .rpt2_cache/ 85 | .rts2_cache_cjs/ 86 | .rts2_cache_es/ 87 | .rts2_cache_umd/ 88 | 89 | # Optional REPL history 90 | 91 | .node_repl_history 92 | 93 | # Output of 'npm pack' 94 | 95 | *.tgz 96 | 97 | # Yarn Integrity file 98 | 99 | .yarn-integrity 100 | 101 | # dotenv environment variable files 102 | 103 | .env 104 | .env.development.local 105 | .env.test.local 106 | .env.production.local 107 | .env.local 108 | 109 | # parcel-bundler cache (https://parceljs.org/) 110 | 111 | .parcel-cache 112 | 113 | # Next.js build output 114 | 115 | .next 116 | out 117 | 118 | # Nuxt.js build / generate output 119 | 120 | .nuxt 121 | dist 122 | 123 | # Gatsby files 124 | 125 | # Comment in the public line in if your project uses Gatsby and not Next.js 126 | 127 | # https://nextjs.org/blog/next-9-1#public-directory-support 128 | 129 | # public 130 | 131 | # vuepress build output 132 | 133 | .vuepress/dist 134 | 135 | # vuepress v2.x temp and cache directory 136 | 137 | .temp 138 | 139 | # Docusaurus cache and generated files 140 | 141 | .docusaurus 142 | 143 | # Serverless directories 144 | 145 | .serverless/ 146 | 147 | # FuseBox cache 148 | 149 | .fusebox/ 150 | 151 | # DynamoDB Local files 152 | 153 | .dynamodb/ 154 | 155 | # TernJS port file 156 | 157 | .tern-port 158 | 159 | # Stores VSCode versions used for testing VSCode extensions 160 | 161 | .vscode-test 162 | 163 | # yarn v2 164 | 165 | .yarn/cache 166 | .yarn/unplugged 167 | .yarn/build-state.yml 168 | .yarn/install-state.gz 169 | .pnp.* 170 | 171 | # IntelliJ based IDEs 172 | .idea 173 | 174 | .cursor 175 | 176 | # Finder (MacOS) folder config 177 | .DS_Store 178 | package-lock.json 179 | 180 | prompt.txt 181 | 182 | reports 183 | reports-old 184 | src/test/questions* 185 | -------------------------------------------------------------------------------- /packages/sdk/src/commands/get-docs/index.ts: -------------------------------------------------------------------------------- 1 | import { Command } from "@commands/command"; 2 | import type { 3 | GetDocsOptions, 4 | CodeDocsResponse, 5 | InfoDocsResponse, 6 | TextDocsResponse, 7 | QueryParams, 8 | } from "@commands/types"; 9 | import type { Requester } from "@http"; 10 | 11 | const DEFAULT_DOC_TYPE = "code"; 12 | const DEFAULT_FORMAT = "json"; 13 | 14 | export class GetDocsCommand extends Command< 15 | TextDocsResponse | CodeDocsResponse | InfoDocsResponse 16 | > { 17 | private readonly format: "json" | "txt"; 18 | 19 | constructor(libraryId: string, options?: GetDocsOptions) { 20 | const cleaned = libraryId.startsWith("/") ? libraryId.slice(1) : libraryId; 21 | const parts = cleaned.split("/"); 22 | 23 | if (parts.length !== 2) { 24 | throw new Error( 25 | `Invalid library ID format: ${libraryId}. Expected format: /username/library` 26 | ); 27 | } 28 | 29 | const [owner, repo] = parts; 30 | 31 | const version = options?.version; 32 | const mode = options?.mode || DEFAULT_DOC_TYPE; 33 | 34 | const endpointParts = ["v2", "docs", mode, owner, repo]; 35 | if (version) { 36 | endpointParts.push(version); 37 | } 38 | const endpoint = endpointParts.join("/"); 39 | 40 | const queryParams: QueryParams = {}; 41 | 42 | if (options?.topic) { 43 | queryParams.topic = options.topic; 44 | } 45 | 46 | const format = options?.format ?? DEFAULT_FORMAT; 47 | queryParams.type = format; 48 | 49 | if (options?.page !== undefined) { 50 | queryParams.page = options.page; 51 | } 52 | 53 | if (options?.limit !== undefined) { 54 | queryParams.limit = options.limit; 55 | } 56 | 57 | super( 58 | { 59 | method: "GET", 60 | query: queryParams, 61 | }, 62 | endpoint 63 | ); 64 | 65 | this.format = format; 66 | } 67 | 68 | public override async exec( 69 | client: Requester 70 | ): Promise { 71 | const { result, headers } = await client.request({ 72 | method: this.request.method || "POST", 73 | path: [this.endpoint], 74 | query: this.request.query, 75 | body: this.request.body, 76 | }); 77 | 78 | if (result === undefined) { 79 | throw new TypeError("Request did not return a result"); 80 | } 81 | 82 | if (this.format === "txt" && typeof result === "string") { 83 | const defaultPagination = { 84 | page: 1, 85 | limit: 10, 86 | totalPages: 1, 87 | hasNext: false, 88 | hasPrev: false, 89 | }; 90 | 91 | return { 92 | content: result, 93 | pagination: { 94 | page: headers?.page ?? defaultPagination.page, 95 | limit: headers?.limit ?? defaultPagination.limit, 96 | totalPages: headers?.totalPages ?? defaultPagination.totalPages, 97 | hasNext: headers?.hasNext ?? defaultPagination.hasNext, 98 | hasPrev: headers?.hasPrev ?? defaultPagination.hasPrev, 99 | }, 100 | totalTokens: headers?.totalTokens ?? 0, 101 | } satisfies TextDocsResponse; 102 | } 103 | 104 | return result as CodeDocsResponse | InfoDocsResponse; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | concurrency: ${{ github.workflow }}-${{ github.ref }} 9 | 10 | jobs: 11 | release: 12 | name: Release 13 | runs-on: ubuntu-latest 14 | permissions: 15 | id-token: write # Required for OIDC authentication with MCP Registry 16 | contents: write 17 | pull-requests: write 18 | steps: 19 | - name: Checkout Repo 20 | uses: actions/checkout@v6 21 | 22 | - name: Setup Node 23 | uses: actions/setup-node@v4 24 | with: 25 | node-version: "20" 26 | 27 | - name: Setup pnpm 28 | uses: pnpm/action-setup@v4 29 | with: 30 | version: 10 31 | 32 | - name: Configure npm authentication 33 | run: | 34 | echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc 35 | 36 | - name: Install Dependencies 37 | run: pnpm install --frozen-lockfile 38 | 39 | - name: Build all packages 40 | run: pnpm build 41 | 42 | - name: Create Release PR or Publish 43 | id: changesets 44 | uses: changesets/action@v1 45 | with: 46 | publish: pnpm release 47 | commit: "chore(release): version packages" 48 | title: "chore(release): version packages" 49 | env: 50 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 51 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 52 | 53 | - name: Check if MCP was published 54 | id: check-mcp 55 | if: steps.changesets.outputs.published == 'true' 56 | run: | 57 | PUBLISHED='${{ steps.changesets.outputs.publishedPackages }}' 58 | if echo "$PUBLISHED" | jq -e '.[] | select(.name == "@upstash/context7-mcp")' > /dev/null; then 59 | VERSION=$(echo "$PUBLISHED" | jq -r '.[] | select(.name == "@upstash/context7-mcp") | .version') 60 | echo "mcp_published=true" >> $GITHUB_OUTPUT 61 | echo "mcp_version=$VERSION" >> $GITHUB_OUTPUT 62 | fi 63 | 64 | - name: Update version in MCP source file 65 | if: steps.check-mcp.outputs.mcp_published == 'true' 66 | run: | 67 | VERSION="${{ steps.check-mcp.outputs.mcp_version }}" 68 | sed -i "s/version: \"[0-9]*\.[0-9]*\.[0-9]*\"/version: \"$VERSION\"/" packages/mcp/src/index.ts 69 | git config user.name "github-actions[bot]" 70 | git config user.email "github-actions[bot]@users.noreply.github.com" 71 | git add packages/mcp/src/index.ts 72 | git commit -m "chore: update MCP version in source to $VERSION" || true 73 | git push || true 74 | 75 | - name: Update server.json 76 | if: steps.check-mcp.outputs.mcp_published == 'true' 77 | run: | 78 | VERSION="${{ steps.check-mcp.outputs.mcp_version }}" 79 | echo $(jq --arg v "$VERSION" '.version = $v | .packages[0].version = $v' server.json) > server.json 80 | git add server.json 81 | git commit -m "chore: update server.json to v$VERSION" || true 82 | git push || true 83 | 84 | - name: Publish to MCP Registry 85 | if: steps.check-mcp.outputs.mcp_published == 'true' 86 | run: | 87 | curl -L "https://github.com/modelcontextprotocol/registry/releases/download/v1.3.3/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher 88 | ./mcp-publisher login github-oidc 89 | ./mcp-publisher publish 90 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Report a bug or issue with Context7 MCP 3 | title: "[Bug]: " 4 | labels: ["bug", "needs-triage"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to report this issue! Please fill out the form below to help us investigate. 10 | 11 | - type: dropdown 12 | id: client 13 | attributes: 14 | label: MCP Client 15 | description: Which MCP client are you using? 16 | options: 17 | - Cursor 18 | - Claude Desktop 19 | - Claude Code 20 | - Windsurf 21 | - VS Code 22 | - Cline 23 | - Zed 24 | - Other (specify in description) 25 | validations: 26 | required: true 27 | 28 | - type: input 29 | id: version 30 | attributes: 31 | label: Context7 MCP Version 32 | description: Which version of Context7 MCP are you using? (Check package.json or npm list) 33 | placeholder: e.g., 1.0.21 34 | validations: 35 | required: true 36 | 37 | - type: textarea 38 | id: description 39 | attributes: 40 | label: Bug Description 41 | description: A clear description of what the bug is 42 | placeholder: When I try to... 43 | validations: 44 | required: true 45 | 46 | - type: textarea 47 | id: steps 48 | attributes: 49 | label: Steps to Reproduce 50 | description: Steps to reproduce the behavior 51 | placeholder: | 52 | 1. Install Context7 MCP via... 53 | 2. Run the command... 54 | 3. See error... 55 | validations: 56 | required: true 57 | 58 | - type: textarea 59 | id: expected 60 | attributes: 61 | label: Expected Behavior 62 | description: What you expected to happen 63 | validations: 64 | required: true 65 | 66 | - type: textarea 67 | id: actual 68 | attributes: 69 | label: Actual Behavior 70 | description: What actually happened 71 | validations: 72 | required: true 73 | 74 | - type: textarea 75 | id: logs 76 | attributes: 77 | label: Error Messages / Logs 78 | description: Please copy and paste any relevant error messages or logs 79 | render: shell 80 | 81 | - type: dropdown 82 | id: transport 83 | attributes: 84 | label: Transport Method 85 | description: Which transport method are you using? 86 | options: 87 | - stdio (default) 88 | - http 89 | - SSE (deprecated) 90 | validations: 91 | required: true 92 | 93 | - type: input 94 | id: node-version 95 | attributes: 96 | label: Node.js Version 97 | description: Output of `node --version` 98 | placeholder: e.g., v20.10.0 99 | 100 | - type: input 101 | id: os 102 | attributes: 103 | label: Operating System 104 | description: Which OS are you running? 105 | placeholder: e.g., macOS 14.2, Windows 11, Ubuntu 22.04 106 | 107 | - type: textarea 108 | id: config 109 | attributes: 110 | label: Configuration 111 | description: Your Context7 MCP configuration (remove any API keys!) 112 | render: json 113 | placeholder: | 114 | { 115 | "mcpServers": { 116 | "context7": { 117 | "command": "npx", 118 | "args": ["-y", "@upstash/context7-mcp"] 119 | } 120 | } 121 | } 122 | 123 | - type: textarea 124 | id: additional 125 | attributes: 126 | label: Additional Context 127 | description: Any other context about the problem (proxy settings, firewalls, etc.) 128 | -------------------------------------------------------------------------------- /docs/docs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://mintlify.com/docs.json", 3 | "theme": "maple", 4 | "name": "Context7 MCP", 5 | "description": "Up-to-date code docs for any prompt.", 6 | "colors": { 7 | "primary": "#10B981", 8 | "light": "#ECFDF5", 9 | "dark": "#064E3B" 10 | }, 11 | "navigation": { 12 | "groups": [ 13 | { 14 | "group": "Overview", 15 | "pages": [ 16 | "overview", 17 | "installation", 18 | "usage", 19 | "adding-libraries", 20 | "plans-pricing", 21 | "api-guide" 22 | ] 23 | }, 24 | { 25 | "group": "Dashboard", 26 | "pages": [ 27 | "dashboard/api-keys", 28 | "dashboard/libraries", 29 | "dashboard/claiming-libraries", 30 | "dashboard/private-repositories", 31 | "dashboard/team", 32 | "dashboard/usage", 33 | "dashboard/billing" 34 | ] 35 | }, 36 | { 37 | "group": "SDKs", 38 | "pages": [ 39 | { 40 | "group": "TypeScript", 41 | "pages": [ 42 | "sdks/ts/getting-started", 43 | { 44 | "group": "Commands", 45 | "pages": ["sdks/ts/commands/search-library", "sdks/ts/commands/get-docs"] 46 | } 47 | ] 48 | } 49 | ] 50 | }, 51 | { 52 | "group": "API Reference", 53 | "openapi": "openapi.json" 54 | }, 55 | { 56 | "group": "Integrations", 57 | "pages": ["integrations/code-rabbit"] 58 | }, 59 | { 60 | "group": "Resources", 61 | "pages": ["security", "troubleshooting", "contact"] 62 | } 63 | ] 64 | }, 65 | "api": { 66 | "playground": { "display": "simple" } 67 | }, 68 | "logo": { 69 | "light": "/public/logo/logo.svg", 70 | "dark": "/public/logo/logo-dark.svg", 71 | "href": "https://context7.com" 72 | }, 73 | "favicon": "/public/favicon.ico", 74 | "navbar": { 75 | "links": [ 76 | { 77 | "label": "Discord", 78 | "href": "https://upstash.com/discord" 79 | }, 80 | { 81 | "label": "GitHub", 82 | "href": "https://github.com/upstash/context7" 83 | } 84 | ], 85 | "primary": { 86 | "type": "button", 87 | "label": "Dashboard", 88 | "href": "https://context7.com" 89 | } 90 | }, 91 | "footer": { 92 | "socials": { 93 | "x": "https://x.com/context7ai", 94 | "github": "https://github.com/upstash/context7", 95 | "discord": "https://upstash.com/discord" 96 | }, 97 | "links": [ 98 | { 99 | "header": "Resources", 100 | "items": [ 101 | { 102 | "label": "Website", 103 | "href": "https://context7.com" 104 | }, 105 | { 106 | "label": "Submit a Library", 107 | "href": "https://context7.com/add-library" 108 | }, 109 | { 110 | "label": "Dashboard", 111 | "href": "https://context7.com/dashboard" 112 | } 113 | ] 114 | }, 115 | { 116 | "header": "Community", 117 | "items": [ 118 | { 119 | "label": "GitHub", 120 | "href": "https://github.com/upstash/context7" 121 | }, 122 | { 123 | "label": "Discord", 124 | "href": "https://upstash.com/discord" 125 | }, 126 | { 127 | "label": "Twitter", 128 | "href": "https://x.com/context7ai" 129 | } 130 | ] 131 | } 132 | ] 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /packages/tools-ai-sdk/src/prompts/system.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * System prompts for Context7 AI SDK agents 3 | */ 4 | 5 | /** 6 | * Basic documentation assistant prompt 7 | */ 8 | export const SYSTEM_PROMPT = `You are a documentation search assistant powered by Context7. 9 | 10 | Your role is to help users find accurate, up-to-date documentation for libraries and frameworks. 11 | 12 | When answering questions: 13 | 1. Search for the relevant library documentation 14 | 2. Provide code examples when available 15 | 3. Cite your sources by mentioning the library ID used`; 16 | 17 | /** 18 | * Detailed multi-step workflow prompt for comprehensive documentation retrieval 19 | */ 20 | export const AGENT_PROMPT = `You are a documentation search assistant powered by Context7. 21 | 22 | CRITICAL WORKFLOW - YOU MUST FOLLOW THESE STEPS: 23 | 24 | Step 1: ALWAYS start by calling 'resolveLibrary' with the library name from the user's query 25 | - Extract the main library/framework name (e.g., "React", "Next.js", "Vue") 26 | - Call resolveLibrary with just the library name 27 | - Review ALL the search results returned 28 | 29 | Step 2: Analyze the results from resolveLibrary and select the BEST library ID based on: 30 | - Official sources (e.g., /reactjs/react.dev for React, /vercel/next.js for Next.js) 31 | - Name similarity to what the user is looking for 32 | - Description relevance 33 | - Source reputation (High/Medium is better) 34 | - Code snippet coverage (higher is better) 35 | - Benchmark score (higher is better) 36 | 37 | Step 3: Call 'getLibraryDocs' with the selected library ID 38 | - Use the exact library ID from the resolveLibrary results 39 | - ALWAYS extract and include a relevant topic from the user's query (e.g., "Server-Side Rendering", "routing", "authentication") 40 | - Start with page=1 (default) 41 | 42 | Step 4: If the documentation from page 1 isn't sufficient, call 'getLibraryDocs' again with page=2 43 | - Use the same library ID and the SAME topic from step 3 44 | - This gives you more comprehensive documentation 45 | 46 | Step 5: Provide a clear answer with code examples from the documentation 47 | 48 | IMPORTANT: 49 | - You MUST call resolveLibrary first before calling getLibraryDocs 50 | - Do NOT skip resolveLibrary - it helps you find the correct official documentation 51 | - Always cite which library ID you used`; 52 | 53 | /** 54 | * Library resolution tool description 55 | */ 56 | export const RESOLVE_LIBRARY_DESCRIPTION = `Resolves a package/product name to a Context7-compatible library ID and returns a list of matching libraries. 57 | 58 | You MUST call this function before 'getLibraryDocs' to obtain a valid Context7-compatible library ID UNLESS the user explicitly provides a library ID in the format '/org/project' or '/org/project/version' in their query. 59 | 60 | Selection Process: 61 | 1. Analyze the query to understand what library/package the user is looking for 62 | 2. Return the most relevant match based on: 63 | - Name similarity to the query (exact matches prioritized) 64 | - Description relevance to the query's intent 65 | - Documentation coverage (prioritize libraries with higher Code Snippet counts) 66 | - Source reputation (consider libraries with High or Medium reputation more authoritative) 67 | - Benchmark Score: Quality indicator (100 is the highest score) 68 | 69 | Response Format: 70 | - Return the selected library ID in a clearly marked section 71 | - Provide a brief explanation for why this library was chosen 72 | - If multiple good matches exist, acknowledge this but proceed with the most relevant one 73 | - If no good matches exist, clearly state this and suggest query refinements 74 | 75 | For ambiguous queries, request clarification before proceeding with a best-guess match.`; 76 | 77 | /** 78 | * Get library docs tool description 79 | */ 80 | export const GET_LIBRARY_DOCS_DESCRIPTION = 81 | "Fetches up-to-date documentation for a library. You must call 'resolveLibrary' first to obtain the exact Context7-compatible library ID required to use this tool, UNLESS the user explicitly provides a library ID in the format '/org/project' or '/org/project/version' in their query. Use mode='code' (default) for API references and code examples, or mode='info' for conceptual guides, narrative information, and architectural questions."; 82 | -------------------------------------------------------------------------------- /docs/sdks/ts/getting-started.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Getting Started" 3 | description: "Get started with the Context7 TypeScript SDK" 4 | --- 5 | 6 | 7 | **Work in Progress**: This SDK is currently under active development. The API is subject to change and may introduce breaking changes in future releases. 8 | 9 | 10 | # Getting Started 11 | 12 | `@upstash/context7-sdk` is a TypeScript SDK for Context7, enabling easier access to library documentation with full type coverage. 13 | 14 | Using `@upstash/context7-sdk` you can: 15 | 16 | - Search across available libraries 17 | - Retrieve code documentation with contextual examples 18 | - Fetch informational documentation and guides 19 | - Access library metadata and versioning information 20 | - Filter documentation by topic and pagination 21 | 22 | You can find the Github Repository [here](https://github.com/upstash/context7/tree/master/packages/sdk). 23 | 24 | ## Install 25 | 26 | 27 | ```shell npm 28 | npm install @upstash/context7-sdk 29 | ``` 30 | 31 | ```shell pnpm 32 | pnpm add @upstash/context7-sdk 33 | ``` 34 | 35 | ```shell yarn 36 | yarn add @upstash/context7-sdk 37 | ``` 38 | 39 | ```shell bun 40 | bun add @upstash/context7-sdk 41 | ``` 42 | 43 | 44 | 45 | ## Usage 46 | 47 | ### Initializing the Client 48 | 49 | To use the Context7 SDK, you need an API key. You can get your API key from the [Context7 Dashboard](https://context7.com/dashboard). 50 | 51 | #### Using environment variables 52 | 53 | The SDK automatically reads from environment variables if no API key is provided in the config: 54 | 55 | ```bash 56 | CONTEXT7_API_KEY="your_api_key_here" 57 | ``` 58 | 59 | When an environment variable is set, you can initialize the client without any parameters: 60 | 61 | ```typescript 62 | import { Context7 } from "@upstash/context7-sdk"; 63 | 64 | const client = new Context7(); 65 | ``` 66 | 67 | #### Using a configuration object 68 | 69 | If you prefer to pass configuration in code, the constructor accepts a config object containing the apiKey value. This could be useful if your application needs to interact with multiple projects, each with a different configuration. 70 | 71 | ```typescript 72 | import { Context7 } from "@upstash/context7-sdk"; 73 | 74 | const client = new Context7({ 75 | apiKey: , 76 | }); 77 | ``` 78 | 79 | 80 | The SDK checks for API keys in this order: 1. `config.apiKey` (if provided) 2. 81 | `process.env.CONTEXT7_API_KEY` 82 | 83 | 84 | ## Quick Start Example 85 | 86 | ```typescript 87 | import { Context7 } from "@upstash/context7-sdk"; 88 | 89 | const client = new Context7(); 90 | 91 | const searchResponse = await client.searchLibrary("react"); 92 | console.log(`Found ${searchResponse.results.length} libraries`); 93 | 94 | // Get code documentation (JSON is the default format) 95 | const codeDocs = await client.getDocs("/facebook/react", { 96 | mode: "code", 97 | limit: 5, 98 | }); 99 | 100 | console.log(`Retrieved ${codeDocs.snippets.length} code snippets`); 101 | console.log(`Total tokens: ${codeDocs.totalTokens}`); 102 | 103 | // Get info documentation as text 104 | const textDocs = await client.getDocs("/facebook/react", { 105 | mode: "info", 106 | format: "txt", 107 | limit: 3, 108 | }); 109 | 110 | console.log(textDocs.content); 111 | ``` 112 | 113 | ## Error Handling 114 | 115 | The SDK throws `Context7Error` for API errors: 116 | 117 | ```typescript 118 | import { Context7, Context7Error } from "@upstash/context7-sdk"; 119 | 120 | const client = new Context7({ 121 | apiKey: process.env.CONTEXT7_API_KEY!, 122 | }); 123 | 124 | try { 125 | const docs = await client.getDocs("/invalid/library", { 126 | mode: "code", 127 | format: "txt", 128 | }); 129 | } catch (error) { 130 | if (error instanceof Context7Error) { 131 | console.error("Context7 API Error:", error.message); 132 | } else { 133 | console.error("Unexpected error:", error); 134 | } 135 | } 136 | ``` 137 | 138 | ## Next Steps 139 | 140 | Explore the SDK commands: 141 | 142 | - [Search Library](/sdks/ts/commands/search-library) - Search for libraries 143 | - [Get Docs](/sdks/ts/commands/get-docs) - Retrieve library documentation 144 | -------------------------------------------------------------------------------- /packages/tools-ai-sdk/src/tools/get-library-docs.ts: -------------------------------------------------------------------------------- 1 | import { tool } from "ai"; 2 | import { z } from "zod"; 3 | import { Context7 } from "@upstash/context7-sdk"; 4 | import type { Context7ToolsConfig } from "./types"; 5 | import { GET_LIBRARY_DOCS_DESCRIPTION } from "@prompts"; 6 | 7 | /** 8 | * Tool to fetch documentation for a library using its Context7 library ID. 9 | * 10 | * Can be called with or without configuration. Uses CONTEXT7_API_KEY environment 11 | * variable for authentication when no API key is provided. 12 | * 13 | * @param config Optional configuration options 14 | * @returns AI SDK tool for fetching library documentation 15 | * 16 | * @example 17 | * ```typescript 18 | * import { resolveLibrary, getLibraryDocs } from '@upstash/context7-tools-ai-sdk'; 19 | * import { generateText, stepCountIs } from 'ai'; 20 | * import { openai } from '@ai-sdk/openai'; 21 | * 22 | * const { text } = await generateText({ 23 | * model: openai('gpt-4o'), 24 | * prompt: 'Find React documentation about hooks', 25 | * tools: { 26 | * resolveLibrary: resolveLibrary(), 27 | * getLibraryDocs: getLibraryDocs(), 28 | * }, 29 | * stopWhen: stepCountIs(5), 30 | * }); 31 | * ``` 32 | */ 33 | export function getLibraryDocs(config: Context7ToolsConfig = {}) { 34 | const { apiKey, defaultMaxResults = 10 } = config; 35 | const getClient = () => new Context7({ apiKey }); 36 | 37 | return tool({ 38 | description: GET_LIBRARY_DOCS_DESCRIPTION, 39 | inputSchema: z.object({ 40 | libraryId: z 41 | .string() 42 | .describe( 43 | "Exact Context7-compatible library ID (e.g., '/mongodb/docs', '/vercel/next.js', '/supabase/supabase', '/vercel/next.js/v14.3.0-canary.87') retrieved from 'resolveLibrary' or directly from user query in the format '/org/project' or '/org/project/version'." 44 | ), 45 | mode: z 46 | .enum(["code", "info"]) 47 | .optional() 48 | .default("code") 49 | .describe( 50 | "Documentation mode: 'code' for API references and code examples (default), 'info' for conceptual guides, narrative information, and architectural questions." 51 | ), 52 | topic: z 53 | .string() 54 | .optional() 55 | .describe("Topic to focus documentation on (e.g., 'hooks', 'routing')."), 56 | page: z 57 | .number() 58 | .int() 59 | .min(1) 60 | .max(10) 61 | .optional() 62 | .describe( 63 | "Page number for pagination (start: 1, default: 1). If the context is not sufficient, try page=2, page=3, page=4, etc. with the same topic." 64 | ), 65 | }), 66 | execute: async ({ 67 | libraryId, 68 | mode = "code", 69 | topic, 70 | page = 1, 71 | }: { 72 | libraryId: string; 73 | mode?: "code" | "info"; 74 | topic?: string; 75 | page?: number; 76 | }) => { 77 | try { 78 | const client = getClient(); 79 | const baseOptions = { 80 | page, 81 | limit: defaultMaxResults, 82 | topic: topic?.trim() || undefined, 83 | }; 84 | 85 | const response = 86 | mode === "info" 87 | ? await client.getDocs(libraryId, { ...baseOptions, mode: "info" }) 88 | : await client.getDocs(libraryId, { ...baseOptions, mode: "code" }); 89 | 90 | if (!response.snippets?.length) { 91 | return { 92 | success: false, 93 | error: 94 | "Documentation not found or not finalized for this library. This might have happened because you used an invalid Context7-compatible library ID. To get a valid Context7-compatible library ID, use the 'resolveLibrary' with the package name you wish to retrieve documentation for.", 95 | libraryId, 96 | }; 97 | } 98 | 99 | return { 100 | success: true, 101 | libraryId, 102 | snippets: response.snippets, 103 | pagination: response.pagination, 104 | totalTokens: response.totalTokens, 105 | }; 106 | } catch (error) { 107 | return { 108 | success: false, 109 | error: error instanceof Error ? error.message : "Failed to fetch documentation", 110 | libraryId, 111 | }; 112 | } 113 | }, 114 | }); 115 | } 116 | -------------------------------------------------------------------------------- /packages/sdk/src/commands/get-docs/index.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test, expect } from "vitest"; 2 | import { GetDocsCommand } from "./index"; 3 | import { newHttpClient } from "../../utils/test-utils"; 4 | import { Context7 } from "../../client"; 5 | import { CodeDocsResponse, TextDocsResponse } from "@commands/types"; 6 | 7 | const httpClient = newHttpClient(); 8 | 9 | describe("GetDocsCommand", () => { 10 | test("should get library code docs as text with pagination and totalTokens", async () => { 11 | const command = new GetDocsCommand("/facebook/react", { 12 | mode: "code", 13 | format: "txt", 14 | limit: 10, 15 | }); 16 | const result = await command.exec(httpClient); 17 | 18 | expect(result).toBeDefined(); 19 | expect(typeof result).toBe("object"); 20 | expect(result).toHaveProperty("content"); 21 | expect(result).toHaveProperty("pagination"); 22 | expect(result).toHaveProperty("totalTokens"); 23 | expect(typeof (result as TextDocsResponse).content).toBe("string"); 24 | expect((result as TextDocsResponse).content.length).toBeGreaterThan(0); 25 | expect((result as TextDocsResponse).pagination).toHaveProperty("page"); 26 | expect((result as TextDocsResponse).pagination).toHaveProperty("limit"); 27 | expect((result as TextDocsResponse).pagination).toHaveProperty("totalPages"); 28 | expect((result as TextDocsResponse).pagination).toHaveProperty("hasNext"); 29 | expect((result as TextDocsResponse).pagination).toHaveProperty("hasPrev"); 30 | expect(typeof (result as TextDocsResponse).totalTokens).toBe("number"); 31 | }); 32 | 33 | test("should get library info docs as text with pagination and totalTokens", async () => { 34 | const command = new GetDocsCommand("/facebook/react", { 35 | mode: "info", 36 | format: "txt", 37 | limit: 10, 38 | }); 39 | const result = await command.exec(httpClient); 40 | 41 | expect(result).toBeDefined(); 42 | expect(typeof result).toBe("object"); 43 | expect(result).toHaveProperty("content"); 44 | expect(result).toHaveProperty("pagination"); 45 | expect(result).toHaveProperty("totalTokens"); 46 | expect(typeof (result as TextDocsResponse).content).toBe("string"); 47 | expect((result as TextDocsResponse).content.length).toBeGreaterThan(0); 48 | expect(typeof (result as TextDocsResponse).totalTokens).toBe("number"); 49 | }); 50 | 51 | test("should get library code docs as JSON", async () => { 52 | const command = new GetDocsCommand("/facebook/react", { 53 | mode: "code", 54 | format: "json", 55 | limit: 5, 56 | }); 57 | const result = await command.exec(httpClient); 58 | 59 | expect(result).toBeDefined(); 60 | expect(typeof result).toBe("object"); 61 | expect(result).toHaveProperty("snippets"); 62 | expect(Array.isArray((result as CodeDocsResponse).snippets)).toBe(true); 63 | expect(result).toHaveProperty("pagination"); 64 | expect(result).toHaveProperty("metadata"); 65 | }); 66 | 67 | test("should get library code docs using client with pagination and totalTokens", async () => { 68 | const client = new Context7({ 69 | apiKey: process.env.CONTEXT7_API_KEY || process.env.API_KEY!, 70 | }); 71 | 72 | const result = await client.getDocs("/facebook/react", { 73 | mode: "code", 74 | format: "txt", 75 | limit: 10, 76 | }); 77 | 78 | expect(result).toBeDefined(); 79 | expect(result).toHaveProperty("content"); 80 | expect(result).toHaveProperty("pagination"); 81 | expect(result).toHaveProperty("totalTokens"); 82 | expect(result.content.length).toBeGreaterThan(0); 83 | expect(typeof result.totalTokens).toBe("number"); 84 | }); 85 | 86 | test("should get library info docs using client with pagination and totalTokens", async () => { 87 | const client = new Context7({ 88 | apiKey: process.env.CONTEXT7_API_KEY || process.env.API_KEY!, 89 | }); 90 | 91 | const result = await client.getDocs("/facebook/react", { 92 | mode: "info", 93 | format: "txt", 94 | limit: 10, 95 | }); 96 | 97 | expect(result).toBeDefined(); 98 | expect(result).toHaveProperty("content"); 99 | expect(result).toHaveProperty("pagination"); 100 | expect(result).toHaveProperty("totalTokens"); 101 | expect(result.content.length).toBeGreaterThan(0); 102 | expect(typeof result.totalTokens).toBe("number"); 103 | }); 104 | }); 105 | -------------------------------------------------------------------------------- /packages/mcp/schema/context7.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://context7.com/schema/context7.json", 4 | "title": "Context7 Configuration Schema", 5 | "description": "Configuration file for Context7 project parsing and documentation generation", 6 | "type": "object", 7 | "properties": { 8 | "projectTitle": { 9 | "type": "string", 10 | "description": "The display name for your project in Context7. This overrides the default repository name.", 11 | "minLength": 1, 12 | "maxLength": 100, 13 | "examples": ["Upstash Ratelimit", "Next.js", "React Query"] 14 | }, 15 | "description": { 16 | "type": "string", 17 | "description": "A brief description of what your library does. This helps coding agents understand the purpose of your project.", 18 | "minLength": 10, 19 | "maxLength": 200, 20 | "examples": [ 21 | "Ratelimiting library based on Upstash Redis", 22 | "The React Framework for Production", 23 | "Powerful data synchronization for React" 24 | ] 25 | }, 26 | "folders": { 27 | "type": "array", 28 | "description": "Specific folder paths to include when parsing documentation. If empty, Context7 will scan the entire repository. Supports regex patterns and requires full paths.", 29 | "items": { 30 | "type": "string", 31 | "minLength": 1 32 | }, 33 | "uniqueItems": true, 34 | "default": [], 35 | "examples": [ 36 | ["docs", "guides", "examples"], 37 | ["documentation/**"], 38 | ["api-reference", "tutorials/*"] 39 | ] 40 | }, 41 | "excludeFolders": { 42 | "type": "array", 43 | "description": "Folder paths to exclude from documentation parsing. Supports regex patterns and requires full paths.", 44 | "items": { 45 | "type": "string", 46 | "minLength": 1 47 | }, 48 | "uniqueItems": true, 49 | "default": [], 50 | "examples": [ 51 | ["src", "build", "node_modules"], 52 | ["**/test/**", "**/tests/**"], 53 | ["legacy/*", "archive"] 54 | ] 55 | }, 56 | "excludeFiles": { 57 | "type": "array", 58 | "description": "Specific file names to exclude from documentation parsing. Only include the filename (not the path). Regex patterns are not supported.", 59 | "items": { 60 | "type": "string", 61 | "minLength": 1, 62 | "pattern": "^[^/\\\\]+$" 63 | }, 64 | "uniqueItems": true, 65 | "default": [], 66 | "examples": [ 67 | ["CHANGELOG.md", "LICENSE"], 68 | ["README-dev.md", "CONTRIBUTING.md"], 69 | ["package.json", "tsconfig.json"] 70 | ] 71 | }, 72 | "rules": { 73 | "type": "array", 74 | "description": "Best practices or important guidelines that coding agents should follow when using your library. These appear as recommendations in the documentation context.", 75 | "items": { 76 | "type": "string", 77 | "minLength": 5, 78 | "maxLength": 200 79 | }, 80 | "default": [], 81 | "examples": [ 82 | ["Always use TypeScript for better type safety"], 83 | ["Use Upstash Redis as a database", "Use single region set up"], 84 | ["Import components from the main package", "Follow the naming conventions"] 85 | ] 86 | }, 87 | "previousVersions": { 88 | "type": "array", 89 | "description": "Information about previous versions of your library that should also be available in Context7.", 90 | "items": { 91 | "type": "object", 92 | "properties": { 93 | "tag": { 94 | "type": "string", 95 | "description": "The Git tag or version identifier", 96 | "pattern": "^v?\\d+\\.\\d+\\.\\d+", 97 | "examples": ["v1.2.1", "2.0.0", "v3.1.0-beta.1"] 98 | }, 99 | "title": { 100 | "type": "string", 101 | "description": "Human-readable version name", 102 | "minLength": 1, 103 | "maxLength": 50, 104 | "examples": ["version 1.2.1", "Legacy Version", "Beta Release"] 105 | } 106 | }, 107 | "required": ["tag", "title"], 108 | "additionalProperties": false 109 | }, 110 | "default": [] 111 | } 112 | }, 113 | "additionalProperties": false, 114 | "examples": [ 115 | { 116 | "projectTitle": "Upstash Ratelimit", 117 | "description": "Ratelimiting library based on Upstash Redis", 118 | "folders": [], 119 | "excludeFolders": ["src"], 120 | "excludeFiles": [], 121 | "rules": ["Use Upstash Redis as a database", "Use single region set up"], 122 | "previousVersions": [ 123 | { 124 | "tag": "v1.2.1", 125 | "title": "version 1.2.1" 126 | } 127 | ] 128 | } 129 | ] 130 | } 131 | -------------------------------------------------------------------------------- /docs/sdks/ts/commands/search-library.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Search Library" 3 | description: "Search available libraries" 4 | --- 5 | 6 | # Search Library 7 | 8 | Search across available libraries. Returns finalized public libraries and accessible private repositories based on authentication. 9 | 10 | ## Arguments 11 | 12 | 13 | The search query to find libraries 14 | 15 | 16 | ## Response 17 | 18 | 19 | 20 | 21 | Array of library search results 22 | 23 | 24 | Unique identifier for the library (e.g., "/facebook/react") 25 | 26 | 27 | Display name of the library 28 | 29 | 30 | Brief description of the library 31 | 32 | 33 | Default branch name 34 | 35 | 36 | ISO 8601 timestamp of last update 37 | 38 | 43 | Current processing state of the library 44 | 45 | 46 | Total number of tokens in documentation 47 | 48 | 49 | Total number of code snippets 50 | 51 | 52 | Number of GitHub stars 53 | 54 | 55 | Trust score of the library 56 | 57 | 58 | Benchmark score 59 | 60 | 61 | Available versions 62 | 63 | 64 | 65 | 66 | 67 | 68 | Authentication level used for the request 69 | 70 | 71 | 72 | 73 | 74 | 75 | ## Examples 76 | 77 | 78 | ```typescript Basic Search 79 | import { Context7 } from "@upstash/context7-sdk"; 80 | 81 | const client = new Context7(); 82 | 83 | const response = await client.searchLibrary("react"); 84 | 85 | console.log(`Found ${response.results.length} libraries`); 86 | response.results.forEach(library => { 87 | console.log(`${library.title}: ${library.description}`); 88 | }); 89 | 90 | ```` 91 | 92 | ```typescript Error Handling 93 | import { Context7, Context7Error } from "@upstash/context7-sdk"; 94 | 95 | const client = new Context7(); 96 | 97 | try { 98 | const response = await client.searchLibrary("express"); 99 | 100 | if (response.results.length === 0) { 101 | console.log("No libraries found"); 102 | } else { 103 | console.log(`Found ${response.results.length} libraries`); 104 | } 105 | } catch (error) { 106 | if (error instanceof Context7Error) { 107 | console.error("API Error:", error.message); 108 | } else { 109 | throw error; 110 | } 111 | } 112 | ``` 113 | 114 | 115 | 116 | ## Use Cases 117 | 118 | ### Finding Popular Libraries 119 | 120 | ```typescript 121 | const response = await client.searchLibrary("react"); 122 | 123 | // Sort by stars 124 | const popular = response.results 125 | .filter((lib) => lib.stars !== undefined) 126 | .sort((a, b) => (b.stars || 0) - (a.stars || 0)); 127 | 128 | console.log("Most popular:", popular[0].title); 129 | ``` 130 | 131 | ### Checking Documentation Availability 132 | 133 | ```typescript 134 | const response = await client.searchLibrary("axios"); 135 | 136 | response.results.forEach((lib) => { 137 | console.log(`${lib.title}:`); 138 | console.log(` - State: ${lib.state}`); 139 | console.log(` - Snippets: ${lib.totalSnippets}`); 140 | console.log(` - Tokens: ${lib.totalTokens}`); 141 | }); 142 | ``` 143 | 144 | ### Getting Library Versions 145 | 146 | ```typescript 147 | const response = await client.searchLibrary("lodash"); 148 | 149 | const library = response.results[0]; 150 | if (library.versions) { 151 | console.log(`Available versions: ${library.versions.join(", ")}`); 152 | } 153 | ``` 154 | -------------------------------------------------------------------------------- /docs/api-guide.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: API Guide 3 | description: Authentication, rate limits, best practices, and integration guides for the Context7 API 4 | --- 5 | 6 | ## Authentication 7 | 8 | All API requests require authentication using an API key. Include your API key in the `Authorization` header: 9 | 10 | ```bash 11 | Authorization: Bearer CONTEXT7_API_KEY 12 | ``` 13 | 14 | Get your API key at [context7.com/dashboard](https://context7.com/dashboard). Learn more about [creating and managing API keys](/dashboard/api-keys). 15 | 16 | 17 | Store your API key in an environment variable or secret manager. Rotate it if compromised. 18 | 19 | 20 | ## Rate Limits 21 | 22 | - **Without API key**: Low rate limits and no custom configuration 23 | - **With API key**: Higher limits based on your plan 24 | - View current usage and reset windows in the [dashboard](https://context7.com/dashboard). 25 | 26 | When you exceed rate limits, the API returns a `429` status code: 27 | 28 | ```json 29 | { 30 | "error": "Too many requests", 31 | "status": 429 32 | } 33 | ``` 34 | 35 | ## Best Practices 36 | 37 | ### Specify Topics 38 | 39 | Use the `topic` parameter to get more relevant results and reduce unnecessary content: 40 | 41 | ```bash 42 | # Focus on routing-specific documentation 43 | curl "https://context7.com/api/v2/docs/code/vercel/next.js?topic=routing" \ 44 | -H "Authorization: Bearer CONTEXT7_API_KEY" 45 | ``` 46 | 47 | ### Cache Responses 48 | 49 | Store documentation locally to reduce API calls and improve performance. Documentation updates are relatively infrequent, so caching for several hours or days is usually appropriate. 50 | 51 | ### Handle Rate Limits 52 | 53 | Implement exponential backoff for rate limit errors: 54 | 55 | ```python 56 | import time 57 | import requests 58 | 59 | def fetch_with_retry(url, headers, max_retries=3): 60 | for attempt in range(max_retries): 61 | response = requests.get(url, headers=headers) 62 | 63 | if response.status_code == 429: 64 | # Wait before retrying with exponential backoff 65 | time.sleep(2 ** attempt) 66 | continue 67 | 68 | return response 69 | 70 | raise Exception("Max retries exceeded") 71 | ``` 72 | 73 | ### Use Specific Versions 74 | 75 | Specify exact versions for consistent results across deployments: 76 | 77 | ```bash 78 | # Pin to a specific version 79 | curl "https://context7.com/api/v2/docs/code/vercel/next.js/v15.1.8" \ 80 | -H "Authorization: Bearer CONTEXT7_API_KEY" 81 | ``` 82 | 83 | ### Use Pagination for More Results 84 | 85 | When you need more documentation snippets, use the `page` parameter to fetch additional pages. The API supports up to 10 pages (100 snippets total) per topic: 86 | 87 | ```bash 88 | # Fetch first page 89 | curl "https://context7.com/api/v2/docs/code/vercel/next.js?topic=routing&page=1" \ 90 | -H "Authorization: Bearer CONTEXT7_API_KEY" 91 | 92 | # Fetch next page if needed 93 | curl "https://context7.com/api/v2/docs/code/vercel/next.js?topic=routing&page=2" \ 94 | -H "Authorization: Bearer CONTEXT7_API_KEY" 95 | ``` 96 | 97 | The response includes pagination metadata to help you navigate: 98 | 99 | ```json 100 | { 101 | "snippets": [...], 102 | "pagination": { 103 | "page": 1, 104 | "limit": 10, 105 | "totalPages": 5, 106 | "hasNext": true, 107 | "hasPrev": false 108 | } 109 | } 110 | ``` 111 | 112 | **Tips:** 113 | 114 | - Use specific topics to reduce the total number of pages needed 115 | - Check `hasNext` before fetching additional pages 116 | - Combine with version pinning for consistent pagination 117 | 118 | ## Error Handling 119 | 120 | The Context7 API uses standard HTTP status codes: 121 | 122 | | Code | Description | Action | 123 | | ---- | --------------------------------------------- | ------------------------------------------------------------- | 124 | | 200 | Success | Process the response normally | 125 | | 401 | Unauthorized - Invalid or missing API key | Check your API key and authentication header | 126 | | 404 | Not Found - Library or endpoint doesn't exist | Verify the library ID or endpoint URL | 127 | | 429 | Too Many Requests - Rate limit exceeded | Implement exponential backoff and retry | 128 | | 500 | Internal Server Error | Retry with exponential backoff, contact support if persistent | 129 | 130 | ### Error Response Format 131 | 132 | All errors return a JSON object with these fields: 133 | 134 | ```json 135 | { 136 | "error": "Error message describing what went wrong", 137 | "status": 429 138 | } 139 | ``` 140 | 141 | ## SDK and Libraries 142 | 143 | ### MCP Server (Recommended) 144 | 145 | The Context7 Model Context Protocol (MCP) server provides seamless integration with Claude and other AI tools: 146 | 147 | ```bash 148 | npm install @upstash/context7-mcp 149 | ``` 150 | 151 | **Features:** 152 | 153 | - Automatic API key management 154 | - Built-in caching 155 | - Type-safe library resolution 156 | - Optimized for AI workflows 157 | 158 | See the [Installation guide](/installation) for detailed setup instructions. 159 | 160 | ### Direct API Integration 161 | 162 | For custom integrations or non-MCP use cases, use the REST endpoints directly. The API is language-agnostic and works with any HTTP client. 163 | 164 | **Example (cURL):** 165 | 166 | ```bash 167 | curl "https://context7.com/api/v2/docs/code/vercel/next.js?topic=routing" \ 168 | -H "Authorization: Bearer CONTEXT7_API_KEY" 169 | ``` 170 | 171 | **Example (Python):** 172 | 173 | ```python 174 | import requests 175 | 176 | headers = { 177 | "Authorization": "Bearer CONTEXT7_API_KEY" 178 | } 179 | 180 | response = requests.get( 181 | "https://context7.com/api/v2/docs/code/vercel/next.js", 182 | headers=headers, 183 | params={"topic": "routing"} 184 | ) 185 | 186 | docs = response.json() 187 | ``` 188 | 189 | **Example (JavaScript/Node.js):** 190 | 191 | ```javascript 192 | const response = await fetch("https://context7.com/api/v2/docs/code/vercel/next.js?topic=routing", { 193 | headers: { 194 | Authorization: "Bearer CONTEXT7_API_KEY", 195 | }, 196 | }); 197 | const docs = await response.json(); 198 | ``` 199 | -------------------------------------------------------------------------------- /packages/sdk/src/http/index.ts: -------------------------------------------------------------------------------- 1 | import { Context7Error } from "@error"; 2 | 3 | type CacheSetting = 4 | | "default" 5 | | "force-cache" 6 | | "no-cache" 7 | | "no-store" 8 | | "only-if-cached" 9 | | "reload" 10 | | false; 11 | 12 | export type Context7Request = { 13 | path?: string[]; 14 | /** 15 | * Request body will be serialized to json 16 | */ 17 | body?: unknown; 18 | /** 19 | * HTTP method to use 20 | * @default "POST" 21 | */ 22 | method?: "GET" | "POST"; 23 | /** 24 | * Query parameters for GET requests 25 | */ 26 | query?: Record; 27 | }; 28 | export type TxtResponseHeaders = { 29 | page: number; 30 | limit: number; 31 | totalPages: number; 32 | hasNext: boolean; 33 | hasPrev: boolean; 34 | totalTokens: number; 35 | }; 36 | 37 | export type Context7Response = { 38 | result?: TResult; 39 | headers?: TxtResponseHeaders; 40 | }; 41 | 42 | export type Requester = { 43 | request: (req: Context7Request) => Promise>; 44 | }; 45 | 46 | export type RetryConfig = 47 | | false 48 | | { 49 | /** 50 | * The number of retries to attempt before giving up. 51 | * 52 | * @default 5 53 | */ 54 | retries?: number; 55 | /** 56 | * A backoff function receives the current retry cound and returns a number in milliseconds to wait before retrying. 57 | * 58 | * @default 59 | * ```ts 60 | * Math.exp(retryCount) * 50 61 | * ``` 62 | */ 63 | backoff?: (retryCount: number) => number; 64 | }; 65 | 66 | export type RequesterConfig = { 67 | /** 68 | * Configure the retry behaviour in case of network errors 69 | */ 70 | retry?: RetryConfig; 71 | 72 | /** 73 | * Configure the cache behaviour 74 | * @default "no-store" 75 | */ 76 | cache?: CacheSetting; 77 | }; 78 | 79 | export type HttpClientConfig = { 80 | headers?: Record; 81 | baseUrl: string; 82 | retry?: RetryConfig; 83 | signal?: () => AbortSignal; 84 | } & RequesterConfig; 85 | 86 | export class HttpClient implements Requester { 87 | public baseUrl: string; 88 | public headers: Record; 89 | public readonly options: { 90 | signal?: HttpClientConfig["signal"]; 91 | cache?: CacheSetting; 92 | }; 93 | 94 | public readonly retry: { 95 | attempts: number; 96 | backoff: (retryCount: number) => number; 97 | }; 98 | 99 | public constructor(config: HttpClientConfig) { 100 | this.options = { 101 | cache: config.cache, 102 | signal: config.signal, 103 | }; 104 | 105 | this.baseUrl = config.baseUrl.replace(/\/$/, ""); 106 | 107 | this.headers = { 108 | "Content-Type": "application/json", 109 | ...config.headers, 110 | }; 111 | 112 | this.retry = 113 | typeof config?.retry === "boolean" && config?.retry === false 114 | ? { 115 | attempts: 1, 116 | backoff: () => 0, 117 | } 118 | : { 119 | attempts: config?.retry?.retries ?? 5, 120 | backoff: config?.retry?.backoff ?? ((retryCount) => Math.exp(retryCount) * 50), 121 | }; 122 | } 123 | 124 | public async request(req: Context7Request): Promise> { 125 | const method = req.method || "POST"; 126 | 127 | let url = [this.baseUrl, ...(req.path ?? [])].join("/"); 128 | if (method === "GET" && req.query) { 129 | const queryParams = new URLSearchParams(); 130 | Object.entries(req.query).forEach(([key, value]) => { 131 | if (value !== undefined) { 132 | queryParams.append(key, String(value)); 133 | } 134 | }); 135 | const queryString = queryParams.toString(); 136 | if (queryString) { 137 | url += `?${queryString}`; 138 | } 139 | } 140 | 141 | const requestOptions = { 142 | cache: this.options.cache, 143 | method, 144 | headers: this.headers, 145 | body: req.body ? JSON.stringify(req.body) : undefined, 146 | keepalive: true, 147 | signal: this.options.signal?.(), 148 | }; 149 | 150 | let res: Response | null = null; 151 | let error: Error | null = null; 152 | 153 | for (let i = 0; i <= this.retry.attempts; i++) { 154 | try { 155 | res = await fetch(url, requestOptions as RequestInit); 156 | break; 157 | } catch (error_) { 158 | if (requestOptions.signal?.aborted) { 159 | throw error_; 160 | } 161 | error = error_ as Error; 162 | if (i < this.retry.attempts) { 163 | await new Promise((r) => setTimeout(r, this.retry.backoff(i))); 164 | } 165 | } 166 | } 167 | if (!res) { 168 | throw error ?? new Error("Exhausted all retries"); 169 | } 170 | 171 | if (!res.ok) { 172 | const errorBody = (await res.json()) as { error?: string; message?: string }; 173 | throw new Context7Error(errorBody.error || errorBody.message || res.statusText); 174 | } 175 | 176 | const contentType = res.headers.get("content-type"); 177 | 178 | if (contentType?.includes("application/json")) { 179 | const body = await res.json(); 180 | return { result: body as TResult }; 181 | } else { 182 | const text = await res.text(); 183 | const headers = this.extractTxtResponseHeaders(res.headers); 184 | return { result: text as TResult, headers }; 185 | } 186 | } 187 | 188 | private extractTxtResponseHeaders(headers: Headers): TxtResponseHeaders | undefined { 189 | const page = headers.get("x-context7-page"); 190 | const limit = headers.get("x-context7-limit"); 191 | const totalPages = headers.get("x-context7-total-pages"); 192 | const hasNext = headers.get("x-context7-has-next"); 193 | const hasPrev = headers.get("x-context7-has-prev"); 194 | const totalTokens = headers.get("x-context7-total-tokens"); 195 | 196 | if (!page || !limit || !totalPages || !hasNext || !hasPrev || !totalTokens) { 197 | return undefined; 198 | } 199 | 200 | return { 201 | page: parseInt(page, 10), 202 | limit: parseInt(limit, 10), 203 | totalPages: parseInt(totalPages, 10), 204 | hasNext: hasNext === "true", 205 | hasPrev: hasPrev === "true", 206 | totalTokens: parseInt(totalTokens, 10), 207 | }; 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /packages/mcp/src/lib/api.ts: -------------------------------------------------------------------------------- 1 | import { SearchResponse } from "./types.js"; 2 | import { generateHeaders } from "./encryption.js"; 3 | import { ProxyAgent, setGlobalDispatcher } from "undici"; 4 | import { DocumentationMode, DOCUMENTATION_MODES } from "./types.js"; 5 | 6 | const CONTEXT7_API_BASE_URL = "https://context7.com/api"; 7 | const DEFAULT_TYPE = "txt"; 8 | 9 | /** 10 | * Parses a Context7-compatible library ID into its components 11 | * @param libraryId The library ID (e.g., "/vercel/next.js" or "/vercel/next.js/v14.3.0") 12 | * @returns Object with username, library, and optional tag 13 | */ 14 | function parseLibraryId(libraryId: string): { 15 | username: string; 16 | library: string; 17 | tag?: string; 18 | } { 19 | // Remove leading slash if present 20 | const cleaned = libraryId.startsWith("/") ? libraryId.slice(1) : libraryId; 21 | const parts = cleaned.split("/"); 22 | 23 | if (parts.length < 2) { 24 | throw new Error( 25 | `Invalid library ID format: ${libraryId}. Expected format: /username/library or /username/library/tag` 26 | ); 27 | } 28 | 29 | return { 30 | username: parts[0], 31 | library: parts[1], 32 | tag: parts[2], // undefined if not present 33 | }; 34 | } 35 | 36 | /** 37 | * Generates appropriate error messages based on HTTP status codes 38 | * @param errorCode The HTTP error status code 39 | * @param apiKey Optional API key (used for rate limit message) 40 | * @returns Error message string 41 | */ 42 | function createErrorMessage(errorCode: number, apiKey?: string): string { 43 | switch (errorCode) { 44 | case 429: 45 | return apiKey 46 | ? "Rate limited due to too many requests. Please try again later." 47 | : "Rate limited due to too many requests. You can create a free API key at https://context7.com/dashboard for higher rate limits."; 48 | case 404: 49 | return "The library you are trying to access does not exist. Please try with a different library ID."; 50 | case 401: 51 | if (!apiKey) { 52 | return "Unauthorized. Please provide an API key."; 53 | } 54 | return `Unauthorized. Please check your API key. API keys should start with 'ctx7sk'`; 55 | default: 56 | return `Failed to fetch documentation. Please try again later. Error code: ${errorCode}`; 57 | } 58 | } 59 | 60 | // Pick up proxy configuration in a variety of common env var names. 61 | const PROXY_URL: string | null = 62 | process.env.HTTPS_PROXY ?? 63 | process.env.https_proxy ?? 64 | process.env.HTTP_PROXY ?? 65 | process.env.http_proxy ?? 66 | null; 67 | 68 | if (PROXY_URL && !PROXY_URL.startsWith("$") && /^(http|https):\/\//i.test(PROXY_URL)) { 69 | try { 70 | // Configure a global proxy agent once at startup. Subsequent fetch calls will 71 | // automatically use this dispatcher. 72 | // Using `any` cast because ProxyAgent implements the Dispatcher interface but 73 | // TS may not infer it correctly in some versions. 74 | setGlobalDispatcher(new ProxyAgent(PROXY_URL)); 75 | } catch (error) { 76 | // Don't crash the app if proxy initialisation fails – just log a warning. 77 | console.error( 78 | `[Context7] Failed to configure proxy agent for provided proxy URL: ${PROXY_URL}:`, 79 | error 80 | ); 81 | } 82 | } 83 | 84 | /** 85 | * Searches for libraries matching the given query 86 | * @param query The search query 87 | * @param clientIp Optional client IP address to include in headers 88 | * @param apiKey Optional API key for authentication 89 | * @returns Search results or null if the request fails 90 | */ 91 | export async function searchLibraries( 92 | query: string, 93 | clientIp?: string, 94 | apiKey?: string 95 | ): Promise { 96 | try { 97 | const url = new URL(`${CONTEXT7_API_BASE_URL}/v2/search`); 98 | url.searchParams.set("query", query); 99 | 100 | const headers = generateHeaders(clientIp, apiKey); 101 | 102 | const response = await fetch(url, { headers }); 103 | if (!response.ok) { 104 | const errorCode = response.status; 105 | const errorMessage = createErrorMessage(errorCode, apiKey); 106 | console.error(errorMessage); 107 | return { 108 | results: [], 109 | error: errorMessage, 110 | } as SearchResponse; 111 | } 112 | const searchData = await response.json(); 113 | return searchData as SearchResponse; 114 | } catch (error) { 115 | const errorMessage = `Error searching libraries: ${error}`; 116 | console.error(errorMessage); 117 | return { results: [], error: errorMessage } as SearchResponse; 118 | } 119 | } 120 | 121 | /** 122 | * Fetches documentation context for a specific library 123 | * @param libraryId The library ID to fetch documentation for 124 | * @param docMode Documentation mode (CODE for API references and code examples, INFO for conceptual guides) 125 | * @param options Optional request parameters (page, limit, topic) 126 | * @param clientIp Optional client IP address to include in headers 127 | * @param apiKey Optional API key for authentication 128 | * @returns The documentation text or null if the request fails 129 | */ 130 | export async function fetchLibraryDocumentation( 131 | libraryId: string, 132 | docMode: DocumentationMode, 133 | options: { 134 | page?: number; 135 | limit?: number; 136 | topic?: string; 137 | } = {}, 138 | clientIp?: string, 139 | apiKey?: string 140 | ): Promise { 141 | try { 142 | const { username, library, tag } = parseLibraryId(libraryId); 143 | 144 | // Build URL path 145 | let urlPath = `${CONTEXT7_API_BASE_URL}/v2/docs/${docMode}/${username}/${library}`; 146 | if (tag) { 147 | urlPath += `/${tag}`; 148 | } 149 | 150 | const url = new URL(urlPath); 151 | url.searchParams.set("type", DEFAULT_TYPE); 152 | if (options.topic) url.searchParams.set("topic", options.topic); 153 | if (options.page) url.searchParams.set("page", options.page.toString()); 154 | if (options.limit) url.searchParams.set("limit", options.limit.toString()); 155 | 156 | const headers = generateHeaders(clientIp, apiKey, { "X-Context7-Source": "mcp-server" }); 157 | 158 | const response = await fetch(url, { headers }); 159 | if (!response.ok) { 160 | const errorCode = response.status; 161 | const errorMessage = createErrorMessage(errorCode, apiKey); 162 | console.error(errorMessage); 163 | return errorMessage; 164 | } 165 | const text = await response.text(); 166 | if (!text || text === "No content available" || text === "No context data available") { 167 | const suggestion = 168 | docMode === DOCUMENTATION_MODES.CODE 169 | ? " Try mode='info' for guides and tutorials." 170 | : " Try mode='code' for API references and code examples."; 171 | return `No ${docMode} documentation available for this library.${suggestion}`; 172 | } 173 | return text; 174 | } catch (error) { 175 | const errorMessage = `Error fetching library documentation. Please try again later. ${error}`; 176 | console.error(errorMessage); 177 | return errorMessage; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /docs/plans-pricing.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Plans & Pricing 3 | --- 4 | 5 | Choose a plan that fits your workflow today, and scale as your needs grow. 6 | 7 | To change your plan, visit [context7.com/plans](https://context7.com/plans). 8 | 9 | ## Compare Plans 10 | 11 | | Feature | Free | Pro | Enterprise | 12 | | --------------------------- | ----------- | ---------------------- | ------------- | 13 | | **Price** | $0 | $7 per seat/month | Custom | 14 | | **Public Repositories** | ✓ | ✓ | ✓ | 15 | | **Private Repositories** | ✗ | ✓ | ✓ | 16 | | **Team Collaboration** | ✗ | ✓ (up to 20 members) | ✓ (unlimited) | 17 | | **API Rate Limit** | 60 req/hour | 60 req/hour per member | Custom | 18 | | **Parse Token Cost** | N/A | $15 per 1M tokens | Custom | 19 | | **Access Control** | Basic | Full | Advanced | 20 | | **SOC-2 Compliance** | ✗ | ✗ | ✓ | 21 | | **SSO (SAML, OAuth, OIDC)** | ✗ | ✗ | ✓ | 22 | | **Support** | Community | Email | Dedicated | 23 | | **Usage Analytics** | Basic | ✓ | Advanced | 24 | | **Custom Rate Limits** | ✗ | ✗ | ✓ | 25 | | **Priority Features** | ✗ | ✗ | ✓ | 26 | | **Custom SLA** | ✗ | ✗ | ✓ | 27 | 28 | ## Understanding Costs 29 | 30 | ### Free Plan 31 | 32 | The Free plan is always **$0**. Perfect for individual developers using public libraries. 33 | 34 | ### Pro Plan 35 | 36 | Pro plan costs consist of two components: 37 | 38 | **1. Team Seats: $7 per member per month** 39 | 40 | Each team member (Owner, Admin, or Developer) counts as one seat. Learn more about team roles in the [Team Management](/dashboard/team#roles) guide. 41 | 42 | **Example**: 43 | 44 | - 1 member (you): $7/month 45 | - 4 members: $28/month 46 | 47 | **2. Parse Tokens: $15 per 1M tokens** 48 | 49 | Parse tokens are charged when adding or refreshing private repositories: 50 | 51 | - **Adding a new private repo**: Charged for all parsed content 52 | - **Refreshing a repo**: Only charged for new or changed content (cached pages are free) 53 | - **Querying documentation**: Free (covered by seat cost) 54 | 55 | **Example**: 56 | 57 | - Add a 500K token private repo: $7.50 one-time 58 | - Refresh with 100K tokens of changes: $1.50 59 | 60 | See [Private Repositories](/dashboard/private-repositories) for setup instructions and [Usage Statistics](/dashboard/usage) to monitor your token usage. 61 | 62 | **Total Monthly Cost = (Seats × $7) + Parse Token Charges** 63 | 64 | **Example**: 65 | 66 | - Team: 4 members = $28/month 67 | - Parsing: 800K tokens this month = $12 68 | - **Total: $40** 69 | 70 | ### Enterprise Plan 71 | 72 | Custom pricing based on your needs. Contact us at [context7@upstash.com](mailto:context7@upstash.com) for details. 73 | 74 | ## Frequently Asked Questions 75 | 76 | ### General Questions 77 | 78 | 79 | 80 | The Free plan includes access to public repositories, basic access control, and API usage with rate limits. It's perfect for individual developers who don't need private repositories or team collaboration. 81 | 82 | 83 | 84 | The Pro plan costs $7 per seat per month. Each team member counts as a seat, and you're billed 85 | based on the number of members in your team. You also pay for parse tokens used when adding or 86 | refreshing private repositories. 87 | 88 | 89 | 90 | In addition to \$7 per seat per month, you are charged \$15 per 1M tokens for parsing private 91 | repositories. This charge applies when you add a new private repository or refresh an existing 92 | one. The cached pages (while refreshing private repositories) are free. 93 | 94 | 95 | 96 | No, private repository access is only available on Pro and Enterprise plans. You'll need to upgrade to work with private repositories and collaborate with your team. 97 | 98 | 99 | 100 | ### Plan Management 101 | 102 | 103 | 104 | To downgrade, you must first remove all team members and private repositories from your account. Once done, you can switch to the Free plan from the Plans page. 105 | 106 | 107 | 108 | Yes, you can downgrade to the Free plan at any time. A prorated charge will apply based on the 109 | number of days used in your current billing period. 110 | 111 | 112 | 113 | Enterprise plans include additional features like SOC-2 compliance, SSO (Single Sign-On), 114 | dedicated support, and custom rate limits. Contact us to discuss your specific enterprise needs. 115 | 116 | 117 | 118 | Enterprise pricing is customized based on your specific needs and usage requirements. Please contact us at [context7@upstash.com](mailto:context7@upstash.com) to discuss pricing and features. 119 | 120 | 121 | 122 | ### Security & Privacy 123 | 124 | 125 | 126 | The MCP client sends only generic topics to our servers, not your actual queries. Your prompts and code remain private on your local machine. 127 | 128 | 129 | 130 | We follow several processes to ensure safety: 131 | 132 | - Run an LLM-based model to detect injection attempts before storing code 133 | - Assign a source reputation to repository authors 134 | - Allow users to filter trusted libraries by organization and repository 135 | - Regular security audits and monitoring 136 | 137 | 138 | 139 | 140 | We are part of Upstash Inc., based in Silicon Valley since 2020. Review our certifications and practices on our [Trust page](https://trust.upstash.com). We follow SOC-2 compliance standards and industry best practices. 141 | 142 | 143 | 144 | ### API Usage 145 | 146 | 147 | 148 | No, we have different rate limits for each plan. The Free plan has lower rate limits, while the 149 | Pro plan offers higher limits per team member. If you need custom rate limits for high-volume 150 | usage, please contact us at [context7@upstash.com](mailto:context7@upstash.com) to discuss 151 | Enterprise plan options. 152 | 153 | 154 | -------------------------------------------------------------------------------- /docs/security.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Security 3 | --- 4 | 5 | Context7 takes security and privacy seriously. This page outlines our security practices, data handling, and compliance measures. 6 | 7 | ## Highlights 8 | 9 | - Queries stay on your device; Context7 only receives derived topics for retrieval 10 | - Documentation is indexed inside SOC 2 compliant infrastructure operated by Upstash 11 | - API keys are encrypted, rate limited, and easy to rotate from your dashboard 12 | - Enterprise customers can enable SSO (SAML, OAuth, OIDC) and receive dedicated audit trails 13 | 14 | ## Privacy-First Architecture 15 | 16 | ### Query Privacy 17 | 18 | **Your queries never leave your machine.** 19 | 20 | When you use Context7 through the MCP client: 21 | 22 | 1. Your query is analyzed locally to extract topics and relevant keywords 23 | 2. Only these extracted topics are sent to the Context7 server 24 | 3. Your original query and code remain on your local machine 25 | 4. The server has no access to your actual prompts or conversations 26 | 27 | 28 | The MCP client processes your queries locally and only transmits topic information needed to 29 | retrieve relevant documentation. Your full prompts, code, and context remain private. 30 | 31 | 32 | ### Data Storage 33 | 34 | **Context7 does not store your source files.** 35 | 36 | - We only index and store **documentation** and **code examples** from public repositories 37 | - Your private code, projects, and source files are never uploaded or stored 38 | - All indexed content is stored in a secure vector database optimized for retrieval 39 | 40 | **What we store:** 41 | 42 | - Public library documentation 43 | - Public code examples from documentation 44 | - Metadata about indexed libraries 45 | 46 | **What we don't store:** 47 | 48 | - Your source code 49 | - Your queries or prompts 50 | - Your private repositories (unless explicitly authorized) 51 | - Your conversations with AI assistants 52 | 53 | ## Infrastructure Security 54 | 55 | ### SOC 2 Compliance 56 | 57 | Context7 runs on **SOC 2 compliant infrastructure** provided by Upstash. 58 | 59 | - Type II SOC 2 certified infrastructure 60 | - Regular security audits and assessments 61 | - Continuous monitoring and compliance checks 62 | - Industry-standard security controls 63 | 64 | ### Managed by Upstash 65 | 66 | Context7's infrastructure is managed by the experienced Upstash team: 67 | 68 | - 24/7 infrastructure monitoring 69 | - Automated security patching 70 | - DDoS protection and mitigation 71 | - Redundant backups and disaster recovery 72 | - Enterprise-grade reliability and uptime 73 | 74 | ### Upstash Security Practices 75 | 76 | All security practices and certificates of Upstash apply to Context7 projects: 77 | 78 | - **Data Encryption**: Encryption at rest and in transit (TLS 1.2+) 79 | - **Network Security**: VPC isolation, firewall rules, and network segmentation 80 | - **Access Control**: Role-based access control (RBAC) and least privilege principles 81 | - **Audit Logging**: Comprehensive logging of all system activities 82 | - **Incident Response**: Documented incident response procedures 83 | - **Vulnerability Management**: Regular security scanning and penetration testing 84 | 85 | Learn more about Upstash security: [upstash.com/trust](https://upstash.com/trust) 86 | 87 | ## Authentication and Access Control 88 | 89 | ### API Key Security 90 | 91 | - API keys use cryptographic random generation 92 | - Keys are hashed and encrypted in our database 93 | - Keys can be rotated at any time from your dashboard 94 | - Rate limiting prevents abuse and unauthorized access 95 | 96 | ### Enterprise SSO 97 | 98 | **Single Sign-On (SSO) is available for Enterprise plans.** 99 | 100 | Supported SSO providers: 101 | 102 | - SAML 2.0 103 | - OAuth 2.0 104 | - OpenID Connect (OIDC) 105 | 106 | Enterprise features include: 107 | 108 | - Centralized user management 109 | - Team access controls 110 | - Audit logs for compliance 111 | - Custom authentication policies 112 | 113 | Contact our sales team at [context7.com](https://context7.com) for Enterprise plan details. 114 | 115 | ## Data Protection 116 | 117 | ### Privacy by Design 118 | 119 | - **Data Minimization**: We only collect and store what's necessary 120 | - **Purpose Limitation**: Data is used only for documentation retrieval 121 | - **Storage Limitation**: Automated cleanup of outdated data 122 | - **Transparency**: Clear documentation of what we collect and why 123 | 124 | ### GDPR Compliance 125 | 126 | For European users, Context7 provides: 127 | 128 | - The right to access your data 129 | - The right to delete your data 130 | - Data portability options 131 | - Clear consent mechanisms 132 | - Privacy-first data processing 133 | 134 | ## Rate Limiting and Abuse Prevention 135 | 136 | - IP-based rate limiting for anonymous requests 137 | - API key-based rate limiting with tiered limits 138 | - Automatic detection and blocking of abusive patterns 139 | - Protection against DDoS and scraping attacks 140 | 141 | ## Secure Development Practices 142 | 143 | - Regular security code reviews 144 | - Automated dependency scanning 145 | - Secure CI/CD pipelines 146 | - Principle of least privilege for all systems 147 | - Security testing in development lifecycle 148 | 149 | ## Reporting Security Issues 150 | 151 | If you discover a security vulnerability: 152 | 153 | 1. **Do not** publicly disclose the issue 154 | 2. Report via [GitHub Security](https://github.com/upstash/context7/security) 155 | 3. Include detailed steps to reproduce the issue 156 | 4. Allow reasonable time for us to address the issue 157 | 158 | We take all security reports seriously and will respond promptly. 159 | 160 | ## Transparency and Compliance 161 | 162 | ### Open Source 163 | 164 | The Context7 MCP server is open source: 165 | 166 | - Code is publicly available on GitHub 167 | - Community can audit and contribute 168 | - Transparent implementation and practices 169 | 170 | Repository: [github.com/upstash/context7](https://github.com/upstash/context7) 171 | 172 | ### Compliance Certifications 173 | 174 | Context7 benefits from Upstash's compliance certifications: 175 | 176 | - SOC 2 Type II 177 | - GDPR compliant 178 | - ISO 27001 (in progress) 179 | - CCPA compliant 180 | 181 | ## Best Practices for Users 182 | 183 | ### Secure Your API Keys 184 | 185 | - Never commit API keys to version control 186 | - Use environment variables for key storage 187 | - Rotate keys regularly 188 | - Use different keys for different environments 189 | - Revoke unused or compromised keys immediately 190 | 191 | ### Private Repositories 192 | 193 | For private repository access: 194 | 195 | - Only grant minimum required permissions 196 | - Use dedicated API keys for private repos 197 | - Regularly audit access permissions 198 | - Consider using GitHub Apps with fine-grained permissions 199 | 200 | ### Network Security 201 | 202 | - Use HTTPS for all API communications (enforced) 203 | - Configure proxy settings securely if behind a firewall 204 | - Monitor API usage for unusual patterns 205 | - Implement request timeouts and retries 206 | 207 | ## Data Retention 208 | 209 | - **Library Documentation**: Retained while the library is active and public 210 | - **API Logs**: Retained for 30 days for debugging and analytics 211 | - **User Data**: Retained according to your account status 212 | - **Deleted Data**: Permanently removed within 30 days of deletion request 213 | 214 | ## Questions and Support 215 | 216 | For security-related questions: 217 | 218 | - Review our documentation at [docs.context7.com](https://docs.context7.com) 219 | - Contact us through [GitHub Issues](https://github.com/upstash/context7/issues) 220 | - Join our [Discord Community](https://upstash.com/discord) 221 | - Enterprise customers: Contact your dedicated support team 222 | 223 | For privacy policy details, visit: [context7.com/privacy](https://context7.com/privacy) 224 | 225 | --- 226 | 227 | **Last Updated**: January 2025 228 | 229 | We continuously improve our security practices. Check this page regularly for updates. 230 | -------------------------------------------------------------------------------- /docs/adding-libraries.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Library Owners 3 | --- 4 | 5 | Context7 allows you to add your favorite libraries and frameworks so developers always receive current, trustworthy documentation inside their coding environment. 6 | 7 | ## Quick Submission 8 | 9 | The fastest way to add a library is through our web interface: 10 | 11 | **[Submit a Library ->](https://context7.com/add-library?tab=github)** 12 | 13 | 1. Paste the GitHub repository URL. 14 | 2. (Optional) Adjust folders and exclusions. 15 | 3. Submit and let Context7 parse and index the documentation. 16 | 17 | 18 | For private repositories, see the [Private Repositories](/dashboard/private-repositories) guide. 19 | Requires a Pro or Enterprise plan. 20 | 21 | 22 | ## Advanced Configuration with `context7.json` 23 | 24 | For more control over how Context7 parses and presents your library, you can add a `context7.json` file to the root of your repository. This file works similarly to `robots.txt` and tells Context7 how to handle your project. 25 | 26 | ### Configuration Fields 27 | 28 | Here's an example `context7.json` file with all available options: 29 | 30 | ```json 31 | { 32 | "$schema": "https://context7.com/schema/context7.json", 33 | "projectTitle": "Upstash Ratelimit", 34 | "description": "Ratelimiting library based on Upstash Redis", 35 | "folders": [], 36 | "excludeFolders": ["src"], 37 | "excludeFiles": [], 38 | "rules": ["Use Upstash Redis as a database", "Use single region set up"], 39 | "previousVersions": [ 40 | { 41 | "tag": "v1.2.1" 42 | } 43 | ] 44 | } 45 | ``` 46 | 47 | 48 | **Pro Tip**: Including the `$schema` field enables autocomplete, validation, and helpful tooltips 49 | in modern code editors like VS Code, making it easier to create and maintain your configuration. 50 | 51 | 52 | ## Field Descriptions 53 | 54 | - **`projectTitle`** (string): Suggested display name for your project in Context7. Only used when the LLM cannot generate a name with high confidence. 55 | 56 | - **`description`** (string): Suggested description for your project in Context7. Only used when the LLM cannot generate a description with high confidence. 57 | 58 | - **`branch`** (string): The name of the git branch to parse. If not provided, the default branch will be used. 59 | 60 | - **`folders`** (array): Specific folder paths to include when parsing. If empty, Context7 scans the entire repository. Root-level markdown files are always included. 61 | 62 | - **`excludeFolders`** (array): Patterns to exclude from documentation parsing. Supports simple names, paths, and glob patterns (see Exclusion Patterns below). 63 | 64 | - **`excludeFiles`** (array): Specific file names to exclude. Use only the filename, not the full path. Examples: `CHANGELOG.md`, license files, or non-documentation content. 65 | 66 | - **`rules`** (array): Best practices or important guidelines that coding agents should follow when using your library. These appear as recommendations in the documentation context provided to coding agents. 67 | 68 | - **`previousVersions`** (array): Information about previous versions of your library that should also be available in Context7. 69 | - **`tag`**: The Git tag or version identifier 70 | 71 | - **`branchVersions`** (array): Information about previous versions (branch-based) of your library that should also 72 | be available in Context7. 73 | - **`branch`**: The Git branch 74 | 75 | ### Exclusion Patterns 76 | 77 | The `excludeFolders` parameter supports various pattern types for flexible exclusion: 78 | 79 | - **Simple folder names**: `"node_modules"` - Excludes any folder named "node_modules" anywhere in the tree 80 | - **Root-specific patterns**: `"./xyz"` - Excludes the folder only at repository root (e.g., excludes `/xyz` but not `/dist/xyz`) 81 | - **Path patterns**: `"app-sdk/v2.3"` - Excludes specific paths and everything under them 82 | - **Glob patterns**: `"*.test"`, `"temp*"` - Excludes folders matching the pattern 83 | - **Globstar patterns**: `"**/dist"`, `"docs/**/internal"` - Advanced path matching 84 | - **Complex patterns**: `"src/**/*.test.js"` - Exclude test files in the src directory 85 | 86 | Examples: 87 | 88 | - `"node_modules"` - Excludes all node_modules folders anywhere 89 | - `"./build"` - Excludes the build folder only at root (not `src/build`) 90 | - `"app-sdk/v2.3"` - Excludes the app-sdk/v2.3 path and all its contents 91 | - `"*.test"` - Excludes folders ending with .test 92 | - `"docs/**/internal"` - Excludes any "internal" folder under docs 93 | - `"**/temp"` - Excludes any folder named "temp" anywhere 94 | 95 | ### Default Exclusions 96 | 97 | If you don't specify `excludeFiles` or `excludeFolders` in your `context7.json` file, Context7 uses these default patterns: 98 | 99 | #### Default Excluded Files 100 | 101 | ``` 102 | CHANGELOG.md, changelog.md, CHANGELOG.mdx, changelog.mdx 103 | LICENSE.md, license.md 104 | CODE_OF_CONDUCT.md, code_of_conduct.md 105 | ``` 106 | 107 | #### Default Excluded Folders 108 | 109 | ``` 110 | *archive*, *archived*, old, docs/old, *deprecated*, *legacy* 111 | *previous*, *outdated*, *superseded* 112 | i18n/zh*, i18n/es*, i18n/fr*, i18n/de*, i18n/ja*, i18n/ko* 113 | i18n/ru*, i18n/pt*, i18n/it*, i18n/ar*, i18n/hi*, i18n/tr* 114 | i18n/nl*, i18n/pl*, i18n/sv*, i18n/vi*, i18n/th* 115 | zh-cn, zh-tw, zh-hk, zh-mo, zh-sg 116 | ``` 117 | 118 | These defaults help coding agents avoid irrelevant, outdated, and non-technical content. 119 | 120 | ## Claiming Your Library 121 | 122 | If you're the library owner, you can claim your library on Context7 to unlock a web-based admin panel for managing configuration. This allows you to: 123 | 124 | - Edit settings through a user interface instead of committing file changes 125 | - Invite team members to collaborate on configuration 126 | - Add and manage multiple versions of your library documentation 127 | - Get higher rate limits for refresh operations 128 | 129 | **[Learn more about claiming libraries →](/dashboard/claiming-libraries)** 130 | 131 | ## Who Can Manage Configuration? 132 | 133 | - **Library authors**: Claim ownership via `context7.json` and manage settings through the admin panel, or add configuration directly to your repository 134 | - **Contributors**: Submit pull requests to add or update the configuration 135 | - **Community members**: Propose improvements to the way popular libraries are parsed 136 | 137 | ## Best Practices 138 | 139 | 1. **Keep descriptions concise**: One sentence explaining your library's purpose. Example: "Serverless Redis SDK for edge and browser environments." 140 | 2. **Exclude irrelevant folders**: Use `excludeFolders` to skip source code, tests, or build artifacts. Example: `["src", "test", "dist", "node_modules"]` 141 | 3. **Add helpful rules**: Include common gotchas or best practices. Example: "Always call `.close()` on Redis connections" or "Use environment variables for API keys, never hardcode them" 142 | 4. **Maintain version history**: Keep important previous versions accessible. Users on v1.x still need v1.x documentation, not just the latest v2.x 143 | 144 | ## Adding a Version 145 | 146 | To add a new version to your existing library: 147 | 148 | 1. **Add version to the `context7.json` file**: Update the `previousVersions` array with your new version: 149 | 150 | ```json 151 | "previousVersions": [ 152 | { 153 | "tag": "v2.0.0", 154 | "title": "version 2.0.0" 155 | } 156 | ] 157 | ``` 158 | 159 | The `tag` value must exactly match an existing Git tag in your GitHub repository. 160 | 161 | 2. **Refresh your library**: Go to your library page on Context7 and trigger a refresh to index the new version. 162 | 3. **Confirm availability**: Search for the new version or run `resolve-library-id` from an MCP client to confirm it appears in results. 163 | 164 | ## Monitor Parsing and Quality 165 | 166 | Keep documentation helpful for agents: 167 | 168 | - Review the rendered documentation after each release 169 | - Trim noisy sections (e.g., large changelogs) with `excludeFiles` or `excludeFolders` 170 | - Update `rules` when best practices change, so AI assistants surface current guidance 171 | 172 | ## Need Help? 173 | 174 | If you encounter issues or need assistance adding your project, please [open an issue](https://github.com/upstash/context7/issues/new/choose) or reach out to our community. 175 | -------------------------------------------------------------------------------- /i18n/README.ar.md: -------------------------------------------------------------------------------- 1 | # Context7 MCP - توثيق أكواد محدث لأي أمر برمجي 2 | 3 | [![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) [Install in VS Code (npx)](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%7B%22name%22%3A%22context7%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40upstash%2Fcontext7-mcp%40latest%22%5D%7D) 4 | 5 | ## ❌ بدون Context7 6 | 7 | تعتمد النماذج اللغوية الكبيرة على معلومات قديمة أو عامة حول المكتبات التي تستخدمها. مما يؤدي إلى: 8 | 9 | - ❌ أمثلة أكواد قديمة مبنية على بيانات تدريب مضى عليها وقت طويل 10 | - ❌ واجهات برمجة تطبيقات وهمية غير موجودة 11 | - ❌ إجابات عامة لنسخ قديمة من الحزم 12 | 13 | ## ✅ مع Context7 14 | 15 | يستخرج Context7 MCP التوثيق والأمثلة البرمجية المحدثة مباشرة من المصدر — ويضعها في طلبك للنموذج. 16 | 17 | أضف `use context7` إلى طلبك في Cursor: 18 | 19 | ```txt 20 | أنشئ مشروع Next.js بسيط باستخدام app router. use context7 21 | ``` 22 | 23 | ```txt 24 | أنشئ سكربت لحذف الصفوف التي تكون فيها المدينة فارغة "" باستخدام بيانات اعتماد PostgreSQL. use context7 25 | ``` 26 | 27 | يقوم Context7 بجلب الأمثلة المحدثة والتوثيق المناسب مباشرة إلى السياق. 28 | 29 | - 1️⃣ اكتب طلبك بشكل طبيعي 30 | - 2️⃣ أخبر النموذج بـ `use context7` 31 | - 3️⃣ احصل على أكواد تعمل مباشرة 32 | 33 | لا حاجة للتنقل بين التبويبات، لا واجهات برمجة تطبيقات وهمية، لا أكواد قديمة. 34 | 35 | ## 🛠️ البدء 36 | 37 | ### المتطلبات 38 | 39 | - Node.js إصدار 18.0.0 أو أعلى 40 | - Cursor، Windsurf، Claude Desktop أو أي عميل MCP آخر 41 | 42 | ### التثبيت عبر Smithery 43 | 44 | لتثبيت Context7 MCP Server تلقائيًا لـ Claude Desktop: 45 | 46 | ```bash 47 | npx -y @smithery/cli install @upstash/context7-mcp --client claude 48 | ``` 49 | 50 | ### التثبيت في Cursor 51 | 52 | اذهب إلى: `Settings` -> `Cursor Settings` -> `MCP` -> `Add new global MCP server` 53 | 54 | أو أضف هذا إلى ملف `~/.cursor/mcp.json`: 55 | 56 | ```json 57 | { 58 | "mcpServers": { 59 | "context7": { 60 | "command": "npx", 61 | "args": ["-y", "@upstash/context7-mcp@latest"] 62 | } 63 | } 64 | } 65 | ``` 66 | 67 | ### التثبيت باستخدام Bun 68 | 69 | ```json 70 | { 71 | "mcpServers": { 72 | "context7": { 73 | "command": "bunx", 74 | "args": ["-y", "@upstash/context7-mcp@latest"] 75 | } 76 | } 77 | } 78 | ``` 79 | 80 | ### التثبيت باستخدام Deno 81 | 82 | ```json 83 | { 84 | "mcpServers": { 85 | "context7": { 86 | "command": "deno", 87 | "args": ["run", "--allow-env", "--allow-net", "npm:@upstash/context7-mcp"] 88 | } 89 | } 90 | } 91 | ``` 92 | 93 | ### التثبيت في Windsurf 94 | 95 | ```json 96 | { 97 | "mcpServers": { 98 | "context7": { 99 | "command": "npx", 100 | "args": ["-y", "@upstash/context7-mcp@latest"] 101 | } 102 | } 103 | } 104 | ``` 105 | 106 | ### التثبيت في VS Code 107 | 108 | ```json 109 | { 110 | "servers": { 111 | "Context7": { 112 | "type": "stdio", 113 | "command": "npx", 114 | "args": ["-y", "@upstash/context7-mcp@latest"] 115 | } 116 | } 117 | } 118 | ``` 119 | 120 | ### التثبيت في Zed 121 | 122 | ```json 123 | { 124 | "context_servers": { 125 | "Context7": { 126 | "source": "custom", 127 | "command": "npx", 128 | "args": ["-y", "@upstash/context7-mcp", "--api-key", "YOUR_API_KEY"] 129 | } 130 | } 131 | } 132 | ``` 133 | 134 | ### التثبيت في Claude Code 135 | 136 | ```sh 137 | claude mcp add context7 -- npx -y @upstash/context7-mcp@latest 138 | ``` 139 | 140 | ### التثبيت في Claude Desktop 141 | 142 | ```json 143 | { 144 | "mcpServers": { 145 | "Context7": { 146 | "command": "npx", 147 | "args": ["-y", "@upstash/context7-mcp@latest"] 148 | } 149 | } 150 | } 151 | ``` 152 | 153 | ### التثبيت في BoltAI 154 | 155 | ```json 156 | { 157 | "mcpServers": { 158 | "context7": { 159 | "command": "npx", 160 | "args": ["-y", "@upstash/context7-mcp@latest"] 161 | } 162 | } 163 | } 164 | ``` 165 | 166 | ### التثبيت في Copilot Coding Agent 167 | 168 | أضف التكوين التالي إلى قسم `mcp` في ملف إعدادات Copilot Coding Agent الخاص بك Repository->Settings->Copilot->Coding agent->MCP configuration: 169 | 170 | ```json 171 | { 172 | "mcpServers": { 173 | "context7": { 174 | "type": "http", 175 | "url": "https://mcp.context7.com/mcp", 176 | "tools": ["get-library-docs", "resolve-library-id"] 177 | } 178 | } 179 | } 180 | ``` 181 | 182 | لمزيد من المعلومات، راجع [التوثيق الرسمي على GitHub](https://docs.github.com/en/enterprise-cloud@latest/copilot/how-tos/agents/copilot-coding-agent/extending-copilot-coding-agent-with-mcp). 183 | 184 | ### باستخدام Docker 185 | 186 | **Dockerfile:** 187 | 188 | ```Dockerfile 189 | FROM node:18-alpine 190 | WORKDIR /app 191 | RUN npm install -g @upstash/context7-mcp@latest 192 | CMD ["context7-mcp"] 193 | ``` 194 | 195 | **بناء الصورة:** 196 | 197 | ```bash 198 | docker build -t context7-mcp . 199 | ``` 200 | 201 | **التهيئة داخل العميل:** 202 | 203 | ```json 204 | { 205 | "mcpServers": { 206 | "Context7": { 207 | "command": "docker", 208 | "args": ["run", "-i", "--rm", "context7-mcp"], 209 | "transportType": "stdio" 210 | } 211 | } 212 | } 213 | ``` 214 | 215 | ### التثبيت في Windows 216 | 217 | ```json 218 | { 219 | "mcpServers": { 220 | "github.com/upstash/context7-mcp": { 221 | "command": "cmd", 222 | "args": ["/c", "npx", "-y", "@upstash/context7-mcp@latest"], 223 | "disabled": false, 224 | "autoApprove": [] 225 | } 226 | } 227 | } 228 | ``` 229 | 230 | ### الأدوات المتوفرة 231 | 232 | - `resolve-library-id`: يحول اسم مكتبة عام إلى معرف متوافق مع Context7. 233 | - `get-library-docs`: يستخرج التوثيق حسب المعرف. 234 | - `context7CompatibleLibraryID`: مطلوب 235 | - `topic`: موضوع معين مثل "routing" 236 | - `page` (اختياري، افتراضي 1): رقم الصفحة للترقيم (1-10). إذا كان السياق غير كافٍ، جرب page=2، page=3، إلخ مع نفس الموضوع. 237 | 238 | ## التطوير 239 | 240 | ```bash 241 | bun i 242 | bun run build 243 | ``` 244 | 245 | **التهيئة المحلية:** 246 | 247 | ```json 248 | { 249 | "mcpServers": { 250 | "context7": { 251 | "command": "npx", 252 | "args": ["tsx", "/path/to/folder/context7-mcp/src/index.ts"] 253 | } 254 | } 255 | } 256 | ``` 257 | 258 | **الاختبار باستخدام MCP Inspector:** 259 | 260 | ```bash 261 | npx -y @modelcontextprotocol/inspector npx @upstash/context7-mcp@latest 262 | ``` 263 | 264 | ## استكشاف الأخطاء 265 | 266 | ### ERR_MODULE_NOT_FOUND 267 | 268 | استخدم `bunx` بدلاً من `npx`. 269 | 270 | ```json 271 | { 272 | "mcpServers": { 273 | "context7": { 274 | "command": "bunx", 275 | "args": ["-y", "@upstash/context7-mcp@latest"] 276 | } 277 | } 278 | } 279 | ``` 280 | 281 | ### مشاكل في ESM 282 | 283 | جرّب إضافة: 284 | 285 | ```json 286 | { 287 | "command": "npx", 288 | "args": ["-y", "--node-options=--experimental-vm-modules", "@upstash/context7-mcp@1.0.6"] 289 | } 290 | ``` 291 | 292 | ### أخطاء عميل MCP 293 | 294 | 1. أزل `@latest` 295 | 2. جرّب `bunx` 296 | 3. جرّب `deno` 297 | 4. تأكد أنك تستخدم Node v18 أو أحدث 298 | 299 | ## إخلاء مسؤولية 300 | 301 | المشاريع المدرجة في Context7 مساهم بها من المجتمع، ولا يمكن ضمان دقتها أو أمانها بشكل كامل. الرجاء الإبلاغ عن أي محتوى مريب باستخدام زر "الإبلاغ". 302 | 303 | ## Context7 في الإعلام 304 | 305 | - [Better Stack: "أداة مجانية تجعل Cursor أذكى 10x"](https://youtu.be/52FC3qObp9E) 306 | - [Cole Medin: "أفضل MCP Server لمساعدين الذكاء الاصطناعي البرمجيين"](https://www.youtube.com/watch?v=G7gK8H6u7Rs) 307 | - [Context7 + SequentialThinking: هل هذا AGI؟](https://www.youtube.com/watch?v=-ggvzyLpK6o) 308 | - [تحديث جديد من Context7 MCP](https://www.youtube.com/watch?v=CTZm6fBYisc) 309 | - [إعداد Context7 في VS Code](https://www.youtube.com/watch?v=-ls0D-rtET4) 310 | - [Context7: MCP جديد سيغير البرمجة](https://www.youtube.com/watch?v=PS-2Azb-C3M) 311 | - [Cline & RooCode + Context7: قوة مضاعفة](https://www.youtube.com/watch?v=qZfENAPMnyo) 312 | - [أفضل 5 MCP Servers لتجربة برمجة ساحرة](https://www.youtube.com/watch?v=LqTQi8qexJM) 313 | 314 | ## سجل النجوم 315 | 316 | [![Star History Chart](https://api.star-history.com/svg?repos=upstash/context7&type=Date)](https://www.star-history.com/#upstash/context7&Date) 317 | 318 | ## الترخيص 319 | 320 | MIT 321 | -------------------------------------------------------------------------------- /docs/usage.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: How-To Guides 3 | --- 4 | 5 | Practical techniques for using Context7 effectively. 6 | 7 | ## Quick Wins 8 | 9 | - [Auto-invoke Context7](#auto-invoke-context7) so you never forget to pull fresh docs 10 | - [Target the exact library ID](#use-specific-library-ids) to skip search steps 11 | - [Tune networking and proxies](#configure-https-proxy) for locked-down environments 12 | - [Bring in private repositories](#work-with-private-repositories) for internal docs 13 | 14 | ## Auto-Invoke Context7 15 | 16 | Stop adding `use context7` to every prompt by setting up an automatic rule. 17 | 18 | ### Add a Rule to Your MCP Client 19 | 20 | 21 | 22 | 1. Open `Cursor Settings` → `Rules` 23 | 2. Add this rule: 24 | 25 | ```txt 26 | Always use context7 when I need code generation, setup steps, or library documentation. 27 | Automatically use Context7 MCP tools without me having to ask. 28 | ``` 29 | 30 | 31 | 32 | 33 | Create or edit `.windsurfrules` in your project root: 34 | 35 | ```txt 36 | Use context7 for all code generation and API documentation questions. 37 | ``` 38 | 39 | 40 | 41 | 42 | Create or edit `CLAUDE.md` in your project root: 43 | 44 | ```txt 45 | Automatically use context7 for code generation and library documentation. 46 | ``` 47 | 48 | 49 | 50 | 51 | 52 | Customize the rule for your workflow. Examples: "Auto-invoke only for Next.js questions" or "Use 53 | context7 when the prompt mentions 'API' or 'documentation'." 54 | 55 | 56 | ## Use Specific Library IDs 57 | 58 | Skip the search step and get documentation instantly by specifying exact library IDs. 59 | 60 | ### How to Find Library IDs 61 | 62 | 1. Visit [context7.com](https://context7.com) 63 | 2. Search for your library 64 | 3. The ID is shown in the format `/owner/repository` 65 | 66 | ### Use in Your Prompts 67 | 68 | ```txt 69 | Implement JWT auth with Supabase. use library /supabase/supabase 70 | ``` 71 | 72 | ```txt 73 | Build a rate limiter. use library /upstash/ratelimit 74 | ``` 75 | 76 | ```txt 77 | Set up Next.js middleware. use library /vercel/next.js/v15.1.0 78 | ``` 79 | 80 | You can even specify versions: `/owner/repo/v1.0.0` 81 | 82 | ### Benefits 83 | 84 | - **Faster**: No library resolution needed 85 | - **Precise**: Get docs for the exact library and version 86 | - **Reliable**: No ambiguity about which library to use 87 | 88 | ## Configure HTTPS Proxy 89 | 90 | If you're behind a corporate proxy, configure Context7 to route through it. 91 | 92 | ### Set Environment Variables 93 | 94 | 95 | 96 | ```bash 97 | export https_proxy=http://proxy.example.com:8080 98 | export HTTPS_PROXY=http://proxy.example.com:8080 99 | ``` 100 | 101 | With authentication: 102 | ```bash 103 | export https_proxy=http://username:password@proxy.example.com:8080 104 | ``` 105 | 106 | 107 | 108 | 109 | ```cmd 110 | set https_proxy=http://proxy.example.com:8080 111 | set HTTPS_PROXY=http://proxy.example.com:8080 112 | ``` 113 | 114 | With authentication: 115 | ```cmd 116 | set https_proxy=http://username:password@proxy.example.com:8080 117 | ``` 118 | 119 | 120 | 121 | 122 | ```powershell 123 | $env:https_proxy = "http://proxy.example.com:8080" 124 | $env:HTTPS_PROXY = "http://proxy.example.com:8080" 125 | ``` 126 | 127 | 128 | 129 | ### Or Configure in MCP Settings 130 | 131 | Add proxy directly to your MCP configuration: 132 | 133 | ```json 134 | { 135 | "mcpServers": { 136 | "context7": { 137 | "command": "npx", 138 | "args": ["-y", "@upstash/context7-mcp", "--api-key", "YOUR_API_KEY"], 139 | "env": { 140 | "https_proxy": "http://proxy.example.com:8080", 141 | "HTTPS_PROXY": "http://proxy.example.com:8080" 142 | } 143 | } 144 | } 145 | } 146 | ``` 147 | 148 | Both lowercase and uppercase environment variables are supported. 149 | 150 | 151 | After updating proxy settings, run `curl https://mcp.context7.com/mcp/ping` to confirm outbound 152 | connectivity before restarting your IDE. 153 | 154 | 155 | ## Work with Private Repositories 156 | 157 | Add your private GitHub, GitLab, or Bitbucket repositories to make internal documentation available through Context7. Requires a Pro or Enterprise plan. 158 | 159 | For complete instructions on adding, refreshing, and managing private repositories, see the [Private Repositories](/dashboard/private-repositories) guide. 160 | 161 | **Cost**: $15 per 1M tokens when parsing. See [Plans & Pricing](/plans-pricing) for details. 162 | 163 | ## Set Up Team Collaboration 164 | 165 | Share Context7 access with your team. Create a team, invite members with different roles (Owner, Admin, Developer), and manage permissions from your dashboard. 166 | 167 | For complete instructions on creating teams, inviting members, and managing roles, see the [Team Management](/dashboard/team) guide. 168 | 169 | **Cost**: $7 per team member per month on Pro plan. See [Plans & Pricing](/plans-pricing) for details. 170 | 171 | ## Refresh Library Documentation 172 | 173 | Keep your documentation up to date. 174 | 175 | ### Web Interface 176 | 177 | 1. Go to [context7.com/refresh-library](https://context7.com/refresh-library) 178 | 2. Enter library ID (e.g., `/vercel/next.js`) 179 | 3. Submit 180 | 181 | ### API 182 | 183 | ```bash 184 | POST https://context7.com/api/v1/refresh 185 | Content-Type: application/json 186 | Authorization: Bearer YOUR_API_KEY 187 | 188 | { 189 | "docsRepoUrl": "https://github.com/vercel/next.js" 190 | } 191 | ``` 192 | 193 | ### When to Refresh 194 | 195 | - After major version releases 196 | - When documentation is updated 197 | - When you notice outdated information 198 | 199 | For private repos, you only pay for new/changed content during refresh. 200 | 201 | ## Monitor Usage 202 | 203 | Track your API usage, parse tokens, and costs from the dashboard. View metrics for search requests, query tokens, parse tokens, and total monthly costs with detailed breakdowns. 204 | 205 | For complete details on usage statistics and cost calculations, see the [Usage Statistics](/dashboard/usage) guide. 206 | 207 | ## Best Practices 208 | 209 | ### Security 210 | 211 | - Never commit API keys to version control. Use `.env` files and add them to `.gitignore`. 212 | - Use environment variables for keys, like: `export CONTEXT7_API_KEY=your_key_here`. 213 | - Rotate keys regularly -- every 90 days or immediately if compromised. 214 | - Grant only the permissions a team member needs. Use the "Developer" role for non-admins. 215 | 216 | See [Security](/security) for comprehensive security guidelines. 217 | 218 | ### Performance 219 | 220 | - Use specific library IDs such as `/vercel/next.js` instead of general phrases like "next.js docs" when possible. 221 | - Focus results using topic filtering. Try adding specific topics like "authentication" or "routing". 222 | - Use pagination when you need more context — the API supports up to 10 pages per topic. Check the `hasNext` field in responses to know when more pages are available. 223 | - Cache frequently used documentation locally for 6-24 hours to reduce API calls. 224 | 225 | ### Library Management 226 | 227 | - Keep the `context7.json` file in your repositories up to date. Update it when adding new docs or changing structure. 228 | - Exclude unnecessary folders, such as tests and build artifacts: `excludeFolders: ["test", "dist", "node_modules"]`. 229 | - Add helpful rules for AI agents, such as "Always validate user input" or "Use TypeScript strict mode". 230 | - Maintain version tags for important releases. For example, keep v1.x docs available even after releasing v2.x. 231 | 232 | See [Library Owners](/adding-libraries) for configuration details. 233 | 234 | ## Need Help? 235 | 236 | - **Troubleshooting**: [Common issues and solutions](/troubleshooting) 237 | - **API Reference**: [Complete API documentation](/api) 238 | - **MCP Details**: [Technical MCP server info](/mcp) 239 | - **Community**: [Join our Discord](https://upstash.com/discord) 240 | -------------------------------------------------------------------------------- /packages/tools-ai-sdk/src/index.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, test, expect } from "vitest"; 2 | import { generateText, stepCountIs, tool } from "ai"; 3 | import { createAmazonBedrock } from "@ai-sdk/amazon-bedrock"; 4 | import { z } from "zod"; 5 | import { 6 | resolveLibrary, 7 | getLibraryDocs, 8 | Context7Agent, 9 | SYSTEM_PROMPT, 10 | AGENT_PROMPT, 11 | RESOLVE_LIBRARY_DESCRIPTION, 12 | } from "./index"; 13 | 14 | const bedrock = createAmazonBedrock({ 15 | region: process.env.AWS_REGION, 16 | apiKey: process.env.AWS_BEARER_TOKEN_BEDROCK, 17 | }); 18 | 19 | describe("@upstash/context7-tools-ai-sdk", () => { 20 | describe("Tool structure", () => { 21 | test("resolveLibrary() should return a tool object with correct structure", () => { 22 | const tool = resolveLibrary(); 23 | 24 | expect(tool).toBeDefined(); 25 | expect(tool).toHaveProperty("execute"); 26 | expect(tool).toHaveProperty("inputSchema"); 27 | expect(tool).toHaveProperty("description"); 28 | expect(tool.description).toContain("library"); 29 | }); 30 | 31 | test("getLibraryDocs() should return a tool object with correct structure", () => { 32 | const tool = getLibraryDocs(); 33 | 34 | expect(tool).toBeDefined(); 35 | expect(tool).toHaveProperty("execute"); 36 | expect(tool).toHaveProperty("inputSchema"); 37 | expect(tool).toHaveProperty("description"); 38 | expect(tool.description).toContain("documentation"); 39 | }); 40 | 41 | test("tools should accept custom config", () => { 42 | const resolveTool = resolveLibrary({ 43 | apiKey: "ctx7sk-test-key", 44 | }); 45 | 46 | const docsTool = getLibraryDocs({ 47 | apiKey: "ctx7sk-test-key", 48 | defaultMaxResults: 5, 49 | }); 50 | 51 | expect(resolveTool).toHaveProperty("execute"); 52 | expect(docsTool).toHaveProperty("execute"); 53 | }); 54 | }); 55 | 56 | describe("Tool usage with generateText", () => { 57 | test("resolveLibrary tool should be called when searching for a library", async () => { 58 | const result = await generateText({ 59 | model: bedrock("anthropic.claude-3-haiku-20240307-v1:0"), 60 | tools: { 61 | resolveLibrary: resolveLibrary(), 62 | }, 63 | toolChoice: { type: "tool", toolName: "resolveLibrary" }, 64 | stopWhen: stepCountIs(2), 65 | prompt: "Search for 'react' library", 66 | }); 67 | 68 | expect(result.toolCalls.length).toBeGreaterThan(0); 69 | expect(result.toolCalls[0].toolName).toBe("resolveLibrary"); 70 | expect(result.toolResults.length).toBeGreaterThan(0); 71 | const toolResult = result.toolResults[0] as unknown as { output: { success: boolean } }; 72 | expect(toolResult.output.success).toBe(true); 73 | }, 30000); 74 | 75 | test("getLibraryDocs tool should fetch documentation", async () => { 76 | const result = await generateText({ 77 | model: bedrock("anthropic.claude-3-haiku-20240307-v1:0"), 78 | tools: { 79 | getLibraryDocs: getLibraryDocs(), 80 | }, 81 | toolChoice: { type: "tool", toolName: "getLibraryDocs" }, 82 | stopWhen: stepCountIs(2), 83 | prompt: "Fetch documentation for library ID '/facebook/react' with topic 'hooks'", 84 | }); 85 | 86 | expect(result.toolCalls.length).toBeGreaterThan(0); 87 | expect(result.toolCalls[0].toolName).toBe("getLibraryDocs"); 88 | expect(result.toolResults.length).toBeGreaterThan(0); 89 | const toolResult = result.toolResults[0] as unknown as { output: { success: boolean } }; 90 | expect(toolResult.output.success).toBe(true); 91 | }, 30000); 92 | 93 | test("both tools can work together in a multi-step flow", async () => { 94 | const result = await generateText({ 95 | model: bedrock("anthropic.claude-3-haiku-20240307-v1:0"), 96 | tools: { 97 | resolveLibrary: resolveLibrary(), 98 | getLibraryDocs: getLibraryDocs(), 99 | }, 100 | stopWhen: stepCountIs(5), 101 | prompt: 102 | "First use resolveLibrary to find the Next.js library, then use getLibraryDocs to get documentation about routing", 103 | }); 104 | 105 | const allToolCalls = result.steps.flatMap((step) => step.toolCalls); 106 | const toolNames = allToolCalls.map((call) => call.toolName); 107 | expect(toolNames).toContain("resolveLibrary"); 108 | expect(toolNames).toContain("getLibraryDocs"); 109 | }, 60000); 110 | }); 111 | 112 | describe("Context7Agent class", () => { 113 | test("should create an agent instance with model", () => { 114 | const agent = new Context7Agent({ 115 | model: bedrock("anthropic.claude-3-haiku-20240307-v1:0"), 116 | }); 117 | 118 | expect(agent).toBeDefined(); 119 | expect(agent).toHaveProperty("generate"); 120 | expect(agent).toHaveProperty("stream"); 121 | }); 122 | 123 | test("should accept custom stopWhen condition", () => { 124 | const agent = new Context7Agent({ 125 | model: bedrock("anthropic.claude-3-haiku-20240307-v1:0"), 126 | stopWhen: stepCountIs(3), 127 | }); 128 | 129 | expect(agent).toBeDefined(); 130 | }); 131 | 132 | test("should accept custom system prompt", () => { 133 | const agent = new Context7Agent({ 134 | model: bedrock("anthropic.claude-3-haiku-20240307-v1:0"), 135 | system: "Custom system prompt for testing", 136 | }); 137 | 138 | expect(agent).toBeDefined(); 139 | }); 140 | 141 | test("should accept Context7 config options", () => { 142 | const agent = new Context7Agent({ 143 | model: bedrock("anthropic.claude-3-haiku-20240307-v1:0"), 144 | apiKey: "ctx7sk-test-key", 145 | defaultMaxResults: 5, 146 | }); 147 | 148 | expect(agent).toBeDefined(); 149 | }); 150 | 151 | test("should accept additional tools alongside Context7 tools", () => { 152 | const customTool = tool({ 153 | description: "A custom test tool", 154 | inputSchema: z.object({ 155 | input: z.string().describe("Test input"), 156 | }), 157 | execute: async ({ input }) => ({ result: `processed: ${input}` }), 158 | }); 159 | 160 | const agent = new Context7Agent({ 161 | model: bedrock("anthropic.claude-3-haiku-20240307-v1:0"), 162 | tools: { 163 | customTool, 164 | }, 165 | }); 166 | 167 | expect(agent).toBeDefined(); 168 | }); 169 | 170 | test("should generate response using agent workflow", async () => { 171 | const agent = new Context7Agent({ 172 | model: bedrock("anthropic.claude-3-haiku-20240307-v1:0"), 173 | stopWhen: stepCountIs(5), 174 | }); 175 | 176 | const result = await agent.generate({ 177 | prompt: "Find the React library and get documentation about hooks", 178 | }); 179 | 180 | expect(result).toBeDefined(); 181 | expect(result.steps.length).toBeGreaterThan(0); 182 | 183 | const allToolCalls = result.steps.flatMap((step) => step.toolCalls); 184 | const toolNames = allToolCalls.map((call) => call.toolName); 185 | expect(toolNames).toContain("resolveLibrary"); 186 | }, 60000); 187 | 188 | test("should include Context7 tools in generate result", async () => { 189 | const agent = new Context7Agent({ 190 | model: bedrock("anthropic.claude-3-haiku-20240307-v1:0"), 191 | stopWhen: stepCountIs(5), 192 | }); 193 | 194 | const result = await agent.generate({ 195 | prompt: 196 | "Use resolveLibrary to search for Next.js, then use getLibraryDocs to get routing documentation", 197 | }); 198 | 199 | expect(result).toBeDefined(); 200 | 201 | const allToolCalls = result.steps.flatMap((step) => step.toolCalls); 202 | const toolNames = allToolCalls.map((call) => call.toolName); 203 | 204 | expect(toolNames).toContain("resolveLibrary"); 205 | expect(toolNames).toContain("getLibraryDocs"); 206 | }, 60000); 207 | }); 208 | 209 | describe("Prompt exports", () => { 210 | test("should export SYSTEM_PROMPT", () => { 211 | expect(SYSTEM_PROMPT).toBeDefined(); 212 | expect(typeof SYSTEM_PROMPT).toBe("string"); 213 | expect(SYSTEM_PROMPT.length).toBeGreaterThan(0); 214 | }); 215 | 216 | test("should export AGENT_PROMPT", () => { 217 | expect(AGENT_PROMPT).toBeDefined(); 218 | expect(typeof AGENT_PROMPT).toBe("string"); 219 | expect(AGENT_PROMPT).toContain("Context7"); 220 | }); 221 | 222 | test("should export RESOLVE_LIBRARY_DESCRIPTION", () => { 223 | expect(RESOLVE_LIBRARY_DESCRIPTION).toBeDefined(); 224 | expect(typeof RESOLVE_LIBRARY_DESCRIPTION).toBe("string"); 225 | expect(RESOLVE_LIBRARY_DESCRIPTION).toContain("library"); 226 | }); 227 | }); 228 | }); 229 | --------------------------------------------------------------------------------