@upstash/context7-mcp 1.0.33 → 1.0.34-canary.1
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 +30 -132
- package/dist/lib/api.js +17 -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,36 @@ 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
|
-
const url = new URL(urlPath);
|
|
123
|
-
url.searchParams.set("type", DEFAULT_TYPE);
|
|
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.library)
|
|
67
|
+
url.searchParams.set("library", request.library);
|
|
68
|
+
if (request.mode)
|
|
69
|
+
url.searchParams.set("mode", request.mode);
|
|
130
70
|
const headers = generateHeaders(clientIp, apiKey, { "X-Context7-Source": "mcp-server" });
|
|
131
71
|
const response = await fetch(url, { headers });
|
|
132
72
|
if (!response.ok) {
|
|
133
73
|
const errorMessage = await parseErrorResponse(response, apiKey);
|
|
134
74
|
console.error(errorMessage);
|
|
135
|
-
return errorMessage;
|
|
75
|
+
return { data: errorMessage };
|
|
136
76
|
}
|
|
137
77
|
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}`;
|
|
78
|
+
if (!text) {
|
|
79
|
+
return { data: "No documentation found for this query." };
|
|
143
80
|
}
|
|
144
|
-
return text;
|
|
81
|
+
return { data: text };
|
|
145
82
|
}
|
|
146
83
|
catch (error) {
|
|
147
|
-
const errorMessage = `Error fetching library
|
|
84
|
+
const errorMessage = `Error fetching library context. Please try again later. ${error}`;
|
|
148
85
|
console.error(errorMessage);
|
|
149
|
-
return errorMessage;
|
|
86
|
+
return { data: errorMessage };
|
|
150
87
|
}
|
|
151
88
|
}
|
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.1",
|
|
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
|
}
|