@upstash/context7-mcp 2.2.2 → 2.2.4
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/index.js +102 -90
- package/dist/lib/api.js +0 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -89,35 +89,26 @@ function getClientIp(req) {
|
|
|
89
89
|
}
|
|
90
90
|
return undefined;
|
|
91
91
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
92
|
+
function createMcpServer() {
|
|
93
|
+
const server = new McpServer({
|
|
94
|
+
name: "Context7",
|
|
95
|
+
version: SERVER_VERSION,
|
|
96
|
+
websiteUrl: "https://context7.com",
|
|
97
|
+
description: "Context7 provides up-to-date documentation and code examples for libraries and frameworks.",
|
|
98
|
+
icons: [
|
|
99
|
+
{
|
|
100
|
+
src: "https://context7.com/context7-icon-green.png",
|
|
101
|
+
mimeType: "image/png",
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
}, {
|
|
105
|
+
instructions: `Use this server to fetch current documentation whenever the user asks about a library, framework, SDK, API, CLI tool, or cloud service -- even well-known ones like React, Next.js, Prisma, Express, Tailwind, Django, or Spring Boot. This includes API syntax, configuration, version migration, library-specific debugging, setup instructions, and CLI tool usage. Use even when you think you know the answer -- your training data may not reflect recent changes. Prefer this over web search for library docs.
|
|
105
106
|
|
|
106
107
|
Do not use for: refactoring, writing scripts from scratch, debugging business logic, code review, or general programming concepts.`,
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (clientVersion) {
|
|
112
|
-
stdioClientInfo = {
|
|
113
|
-
ide: clientVersion.name,
|
|
114
|
-
version: clientVersion.version,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
server.registerTool("resolve-library-id", {
|
|
119
|
-
title: "Resolve Context7 Library ID",
|
|
120
|
-
description: `Resolves a package/product name to a Context7-compatible library ID and returns matching libraries.
|
|
108
|
+
});
|
|
109
|
+
server.registerTool("resolve-library-id", {
|
|
110
|
+
title: "Resolve Context7 Library ID",
|
|
111
|
+
description: `Resolves a package/product name to a Context7-compatible library ID and returns matching libraries.
|
|
121
112
|
|
|
122
113
|
You MUST call this function before 'Query Documentation' tool 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.
|
|
123
114
|
|
|
@@ -150,79 +141,81 @@ Response Format:
|
|
|
150
141
|
For ambiguous queries, request clarification before proceeding with a best-guess match.
|
|
151
142
|
|
|
152
143
|
IMPORTANT: Do not call this tool more than 3 times per question. If you cannot find what you need after 3 calls, use the best result you have.`,
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}, async ({ query, libraryName }) => {
|
|
168
|
-
|
|
169
|
-
|
|
144
|
+
inputSchema: {
|
|
145
|
+
query: z
|
|
146
|
+
.string()
|
|
147
|
+
.describe("The question or task you need help with. This is used to rank library results by relevance to what the user is trying to accomplish. The query is sent to the Context7 API for processing. Do not include any sensitive or confidential information such as API keys, passwords, credentials, personal data, or proprietary code in your query."),
|
|
148
|
+
libraryName: z
|
|
149
|
+
.string()
|
|
150
|
+
.describe("Library name to search for and retrieve a Context7-compatible library ID. Use the official library name with proper punctuation — e.g., 'Next.js' instead of 'nextjs', 'Customer.io' instead of 'customerio', 'Three.js' instead of 'threejs'."),
|
|
151
|
+
},
|
|
152
|
+
annotations: {
|
|
153
|
+
readOnlyHint: true,
|
|
154
|
+
destructiveHint: false,
|
|
155
|
+
openWorldHint: true,
|
|
156
|
+
idempotentHint: true,
|
|
157
|
+
},
|
|
158
|
+
}, async ({ query, libraryName }) => {
|
|
159
|
+
const searchResponse = await searchLibraries(query, libraryName, getClientContext());
|
|
160
|
+
if (!searchResponse.results || searchResponse.results.length === 0) {
|
|
161
|
+
return {
|
|
162
|
+
content: [
|
|
163
|
+
{
|
|
164
|
+
type: "text",
|
|
165
|
+
text: searchResponse.error
|
|
166
|
+
? searchResponse.error
|
|
167
|
+
: "No libraries found matching the provided name.",
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const resultsText = formatSearchResults(searchResponse);
|
|
173
|
+
const responseText = `Available Libraries:
|
|
174
|
+
|
|
175
|
+
${resultsText}`;
|
|
170
176
|
return {
|
|
171
177
|
content: [
|
|
172
178
|
{
|
|
173
179
|
type: "text",
|
|
174
|
-
text:
|
|
175
|
-
? searchResponse.error
|
|
176
|
-
: "No libraries found matching the provided name.",
|
|
180
|
+
text: responseText,
|
|
177
181
|
},
|
|
178
182
|
],
|
|
179
183
|
};
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
${resultsText}`;
|
|
185
|
-
return {
|
|
186
|
-
content: [
|
|
187
|
-
{
|
|
188
|
-
type: "text",
|
|
189
|
-
text: responseText,
|
|
190
|
-
},
|
|
191
|
-
],
|
|
192
|
-
};
|
|
193
|
-
});
|
|
194
|
-
server.registerTool("query-docs", {
|
|
195
|
-
title: "Query Documentation",
|
|
196
|
-
description: `Retrieves and queries up-to-date documentation and code examples from Context7 for any programming library or framework.
|
|
184
|
+
});
|
|
185
|
+
server.registerTool("query-docs", {
|
|
186
|
+
title: "Query Documentation",
|
|
187
|
+
description: `Retrieves and queries up-to-date documentation and code examples from Context7 for any programming library or framework.
|
|
197
188
|
|
|
198
189
|
You must call 'Resolve Context7 Library ID' tool 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.
|
|
199
190
|
|
|
200
191
|
Do not call this tool more than 3 times per question.`,
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}, async ({ query, libraryId }) => {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
});
|
|
192
|
+
inputSchema: {
|
|
193
|
+
libraryId: z
|
|
194
|
+
.string()
|
|
195
|
+
.describe("Exact Context7-compatible library ID (e.g., '/mongodb/docs', '/vercel/next.js', '/supabase/supabase', '/vercel/next.js/v14.3.0-canary.87') retrieved from 'resolve-library-id' or directly from user query in the format '/org/project' or '/org/project/version'."),
|
|
196
|
+
query: z
|
|
197
|
+
.string()
|
|
198
|
+
.describe("The question or task you need help with. Be specific and include relevant details. Good: 'How to set up authentication with JWT in Express.js' or 'React useEffect cleanup function examples'. Bad: 'auth' or 'hooks'. The query is sent to the Context7 API for processing. Do not include any sensitive or confidential information such as API keys, passwords, credentials, personal data, or proprietary code in your query."),
|
|
199
|
+
},
|
|
200
|
+
annotations: {
|
|
201
|
+
readOnlyHint: true,
|
|
202
|
+
destructiveHint: false,
|
|
203
|
+
openWorldHint: true,
|
|
204
|
+
idempotentHint: true,
|
|
205
|
+
},
|
|
206
|
+
}, async ({ query, libraryId }) => {
|
|
207
|
+
const response = await fetchLibraryContext({ query, libraryId }, getClientContext());
|
|
208
|
+
return {
|
|
209
|
+
content: [
|
|
210
|
+
{
|
|
211
|
+
type: "text",
|
|
212
|
+
text: response.data,
|
|
213
|
+
},
|
|
214
|
+
],
|
|
215
|
+
};
|
|
216
|
+
});
|
|
217
|
+
return server;
|
|
218
|
+
}
|
|
226
219
|
async function main() {
|
|
227
220
|
const transportType = TRANSPORT_TYPE;
|
|
228
221
|
if (transportType === "http") {
|
|
@@ -309,12 +302,19 @@ async function main() {
|
|
|
309
302
|
clientInfo: extractClientInfoFromUserAgent(req.headers["user-agent"]),
|
|
310
303
|
transport: "http",
|
|
311
304
|
};
|
|
305
|
+
// Use SSE responses for tool calls (enableJsonResponse: false). The SDK then
|
|
306
|
+
// flushes response headers immediately after parsing the request rather than
|
|
307
|
+
// buffering until the tool returns. This is required for long-running tools
|
|
308
|
+
// because some MCP HTTP clients cap the underlying fetch at 60s waiting for
|
|
309
|
+
// headers, even though the per-tool timeout is much higher.
|
|
312
310
|
const transport = new StreamableHTTPServerTransport({
|
|
313
311
|
sessionIdGenerator: undefined,
|
|
314
|
-
enableJsonResponse:
|
|
312
|
+
enableJsonResponse: false,
|
|
315
313
|
});
|
|
314
|
+
const server = createMcpServer();
|
|
316
315
|
res.on("close", () => {
|
|
317
316
|
transport.close();
|
|
317
|
+
server.close();
|
|
318
318
|
});
|
|
319
319
|
await requestContext.run(context, async () => {
|
|
320
320
|
await server.connect(transport);
|
|
@@ -413,6 +413,18 @@ async function main() {
|
|
|
413
413
|
else {
|
|
414
414
|
stdioApiKey = cliOptions.apiKey || process.env.CONTEXT7_API_KEY;
|
|
415
415
|
const transport = new StdioServerTransport();
|
|
416
|
+
const server = createMcpServer();
|
|
417
|
+
// Capture client info from MCP initialize handshake (stdio only — HTTP
|
|
418
|
+
// mode plumbs client info through requestContext per request).
|
|
419
|
+
server.server.oninitialized = () => {
|
|
420
|
+
const clientVersion = server.server.getClientVersion();
|
|
421
|
+
if (clientVersion) {
|
|
422
|
+
stdioClientInfo = {
|
|
423
|
+
ide: clientVersion.name,
|
|
424
|
+
version: clientVersion.version,
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
};
|
|
416
428
|
await server.connect(transport);
|
|
417
429
|
console.error(`Context7 Documentation MCP Server v${SERVER_VERSION} running on stdio`);
|
|
418
430
|
}
|
package/dist/lib/api.js
CHANGED
|
@@ -120,8 +120,6 @@ export async function fetchLibraryContext(request, context = {}) {
|
|
|
120
120
|
const url = new URL(`${CONTEXT7_API_BASE_URL}/v2/context`);
|
|
121
121
|
url.searchParams.set("query", request.query);
|
|
122
122
|
url.searchParams.set("libraryId", request.libraryId);
|
|
123
|
-
if (request.researchMode)
|
|
124
|
-
url.searchParams.set("researchMode", "true");
|
|
125
123
|
const headers = generateHeaders(context);
|
|
126
124
|
const response = await fetch(url, { headers });
|
|
127
125
|
if (!response.ok) {
|