@upstash/context7-mcp 1.0.32 → 1.0.34-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/benchmark/benchmark.js +347 -0
- package/dist/benchmark/compare-benchmark.js +289 -0
- package/dist/benchmark/run-benchmark.js +459 -0
- package/dist/benchmark/simulate.js +319 -0
- package/dist/index.js +33 -130
- package/dist/lib/api.js +19 -80
- package/dist/lib/types.js +1 -7
- package/package.json +10 -2
package/dist/lib/api.js
CHANGED
|
@@ -1,26 +1,6 @@
|
|
|
1
1
|
import { generateHeaders } from "./encryption.js";
|
|
2
2
|
import { ProxyAgent, setGlobalDispatcher } from "undici";
|
|
3
|
-
import { DOCUMENTATION_MODES } from "./types.js";
|
|
4
3
|
const CONTEXT7_API_BASE_URL = "https://context7.com/api";
|
|
5
|
-
const DEFAULT_TYPE = "txt";
|
|
6
|
-
/**
|
|
7
|
-
* Parses a Context7-compatible library ID into its components
|
|
8
|
-
* @param libraryId The library ID (e.g., "/vercel/next.js" or "/vercel/next.js/v14.3.0")
|
|
9
|
-
* @returns Object with username, library, and optional tag
|
|
10
|
-
*/
|
|
11
|
-
function parseLibraryId(libraryId) {
|
|
12
|
-
// Remove leading slash if present
|
|
13
|
-
const cleaned = libraryId.startsWith("/") ? libraryId.slice(1) : libraryId;
|
|
14
|
-
const parts = cleaned.split("/");
|
|
15
|
-
if (parts.length < 2) {
|
|
16
|
-
throw new Error(`Invalid library ID format: ${libraryId}. Expected format: /username/library or /username/library/tag`);
|
|
17
|
-
}
|
|
18
|
-
return {
|
|
19
|
-
username: parts[0],
|
|
20
|
-
library: parts[1],
|
|
21
|
-
tag: parts[2], // undefined if not present
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
4
|
/**
|
|
25
5
|
* Parses error response from the Context7 API
|
|
26
6
|
* Extracts the server's error message, falling back to status-based messages if parsing fails
|
|
@@ -46,7 +26,7 @@ async function parseErrorResponse(response, apiKey) {
|
|
|
46
26
|
: "Rate limited or quota exceeded. Create a free API key at https://context7.com/dashboard for higher limits.";
|
|
47
27
|
}
|
|
48
28
|
if (status === 404) {
|
|
49
|
-
return "
|
|
29
|
+
return "No documentation found. Try a different library name or refine your query.";
|
|
50
30
|
}
|
|
51
31
|
if (status === 401) {
|
|
52
32
|
return "Invalid API key. Please check your API key. API keys should start with 'ctx7sk' prefix.";
|
|
@@ -73,79 +53,38 @@ if (PROXY_URL && !PROXY_URL.startsWith("$") && /^(http|https):\/\//i.test(PROXY_
|
|
|
73
53
|
}
|
|
74
54
|
}
|
|
75
55
|
/**
|
|
76
|
-
*
|
|
77
|
-
* @param
|
|
78
|
-
* @param clientIp Optional client IP address to include in headers
|
|
79
|
-
* @param apiKey Optional API key for authentication
|
|
80
|
-
* @returns Search results or null if the request fails
|
|
81
|
-
*/
|
|
82
|
-
export async function searchLibraries(query, clientIp, apiKey) {
|
|
83
|
-
try {
|
|
84
|
-
const url = new URL(`${CONTEXT7_API_BASE_URL}/v2/search`);
|
|
85
|
-
url.searchParams.set("query", query);
|
|
86
|
-
const headers = generateHeaders(clientIp, apiKey);
|
|
87
|
-
const response = await fetch(url, { headers });
|
|
88
|
-
if (!response.ok) {
|
|
89
|
-
const errorMessage = await parseErrorResponse(response, apiKey);
|
|
90
|
-
console.error(errorMessage);
|
|
91
|
-
return {
|
|
92
|
-
results: [],
|
|
93
|
-
error: errorMessage,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
const searchData = await response.json();
|
|
97
|
-
return searchData;
|
|
98
|
-
}
|
|
99
|
-
catch (error) {
|
|
100
|
-
const errorMessage = `Error searching libraries: ${error}`;
|
|
101
|
-
console.error(errorMessage);
|
|
102
|
-
return { results: [], error: errorMessage };
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Fetches documentation context for a specific library
|
|
107
|
-
* @param libraryId The library ID to fetch documentation for
|
|
108
|
-
* @param docMode Documentation mode (CODE for API references and code examples, INFO for conceptual guides)
|
|
109
|
-
* @param options Optional request parameters (page, limit, topic)
|
|
56
|
+
* Fetches intelligent, reranked context for a natural language query
|
|
57
|
+
* @param request The context request parameters (query, topic, library, mode)
|
|
110
58
|
* @param clientIp Optional client IP address to include in headers
|
|
111
59
|
* @param apiKey Optional API key for authentication
|
|
112
|
-
* @returns
|
|
60
|
+
* @returns Context response with data
|
|
113
61
|
*/
|
|
114
|
-
export async function
|
|
62
|
+
export async function fetchLibraryContext(request, clientIp, apiKey) {
|
|
115
63
|
try {
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (options.topic)
|
|
125
|
-
url.searchParams.set("topic", options.topic);
|
|
126
|
-
if (options.page)
|
|
127
|
-
url.searchParams.set("page", options.page.toString());
|
|
128
|
-
if (options.limit)
|
|
129
|
-
url.searchParams.set("limit", options.limit.toString());
|
|
64
|
+
const url = new URL(`${CONTEXT7_API_BASE_URL}/v2/context`);
|
|
65
|
+
url.searchParams.set("query", request.query);
|
|
66
|
+
if (request.topic)
|
|
67
|
+
url.searchParams.set("topic", request.topic);
|
|
68
|
+
if (request.library)
|
|
69
|
+
url.searchParams.set("library", request.library);
|
|
70
|
+
if (request.mode)
|
|
71
|
+
url.searchParams.set("mode", request.mode);
|
|
130
72
|
const headers = generateHeaders(clientIp, apiKey, { "X-Context7-Source": "mcp-server" });
|
|
131
73
|
const response = await fetch(url, { headers });
|
|
132
74
|
if (!response.ok) {
|
|
133
75
|
const errorMessage = await parseErrorResponse(response, apiKey);
|
|
134
76
|
console.error(errorMessage);
|
|
135
|
-
return errorMessage;
|
|
77
|
+
return { data: errorMessage };
|
|
136
78
|
}
|
|
137
79
|
const text = await response.text();
|
|
138
|
-
if (!text
|
|
139
|
-
|
|
140
|
-
? " Try mode='info' for guides and tutorials."
|
|
141
|
-
: " Try mode='code' for API references and code examples.";
|
|
142
|
-
return `No ${docMode} documentation available for this library.${suggestion}`;
|
|
80
|
+
if (!text) {
|
|
81
|
+
return { data: "No documentation found for this query." };
|
|
143
82
|
}
|
|
144
|
-
return text;
|
|
83
|
+
return { data: text };
|
|
145
84
|
}
|
|
146
85
|
catch (error) {
|
|
147
|
-
const errorMessage = `Error fetching library
|
|
86
|
+
const errorMessage = `Error fetching library context. Please try again later. ${error}`;
|
|
148
87
|
console.error(errorMessage);
|
|
149
|
-
return errorMessage;
|
|
88
|
+
return { data: errorMessage };
|
|
150
89
|
}
|
|
151
90
|
}
|
package/dist/lib/types.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@upstash/context7-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.34-canary.0",
|
|
4
4
|
"mcpName": "io.github.upstash/context7",
|
|
5
5
|
"description": "MCP server for Context7",
|
|
6
6
|
"repository": {
|
|
@@ -41,7 +41,13 @@
|
|
|
41
41
|
"zod": "^3.24.2"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
+
"@ai-sdk/anthropic": "^1.2.12",
|
|
45
|
+
"@ai-sdk/google": "^1.2.7",
|
|
46
|
+
"@ai-sdk/mcp": "^0.2.0",
|
|
47
|
+
"@ai-sdk/openai": "^1.3.22",
|
|
44
48
|
"@types/node": "^22.13.14",
|
|
49
|
+
"ai": "^4.3.16",
|
|
50
|
+
"dotenv": "^16.5.0",
|
|
45
51
|
"typescript": "^5.8.2"
|
|
46
52
|
},
|
|
47
53
|
"scripts": {
|
|
@@ -54,6 +60,8 @@
|
|
|
54
60
|
"format:check": "prettier --check .",
|
|
55
61
|
"dev": "tsc --watch",
|
|
56
62
|
"start": "node dist/index.js --transport http",
|
|
57
|
-
"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"
|
|
63
|
+
"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",
|
|
64
|
+
"run-benchmark": "pnpm run build && node dist/benchmark/run-benchmark.js",
|
|
65
|
+
"compare-benchmark": "pnpm run build && node dist/benchmark/compare-benchmark.js"
|
|
58
66
|
}
|
|
59
67
|
}
|