@upstash/context7-mcp 2.2.2 → 2.2.3

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.
Files changed (2) hide show
  1. package/dist/index.js +51 -12
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -197,7 +197,7 @@ server.registerTool("query-docs", {
197
197
 
198
198
  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
199
 
200
- Do not call this tool more than 3 times per question.`,
200
+ Workflow: call first without researchMode. If that doesn't answer the question, retry with researchMode: true. Do not call each tool more than 3 times per question.`,
201
201
  inputSchema: {
202
202
  libraryId: z
203
203
  .string()
@@ -205,6 +205,10 @@ Do not call this tool more than 3 times per question.`,
205
205
  query: z
206
206
  .string()
207
207
  .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."),
208
+ researchMode: z
209
+ .boolean()
210
+ .optional()
211
+ .describe(`Retry the query with deep research: spins up sandboxed agents that read the actual source repos and runs a live web search, then synthesizes a fresh answer. Set true on retry if you weren't satisfied with the first answer and want a more thorough one. Requires an API key. You can get one free at https://context7.com.`),
208
212
  },
209
213
  annotations: {
210
214
  readOnlyHint: true,
@@ -212,16 +216,46 @@ Do not call this tool more than 3 times per question.`,
212
216
  openWorldHint: true,
213
217
  idempotentHint: true,
214
218
  },
215
- }, async ({ query, libraryId }) => {
216
- const response = await fetchLibraryContext({ query, libraryId }, getClientContext());
217
- return {
218
- content: [
219
- {
220
- type: "text",
221
- text: response.data,
222
- },
223
- ],
224
- };
219
+ }, async ({ query, libraryId, researchMode }, { sendNotification, _meta }) => {
220
+ // Emit periodic progress notifications while the upstream call is in flight.
221
+ // MCP clients that opt into resetTimeoutOnProgress (e.g. opencode) reset their
222
+ // request timer on each notification, which keeps long-running tools (notably
223
+ // researchMode) alive past the SDK's default 60s wall-clock timeout. Clients
224
+ // that don't pass a progressToken simply never see these, so behavior is unchanged.
225
+ const progressToken = _meta?.progressToken;
226
+ let progressInterval;
227
+ if (researchMode && progressToken !== undefined) {
228
+ let progress = 0;
229
+ progressInterval = setInterval(() => {
230
+ progress += 1;
231
+ sendNotification({
232
+ method: "notifications/progress",
233
+ params: {
234
+ progressToken,
235
+ progress,
236
+ message: "Researching documentation...",
237
+ },
238
+ }).catch(() => {
239
+ // Notifications are best-effort; swallow transport errors so the tool
240
+ // call itself isn't aborted by a notification write failure.
241
+ });
242
+ }, 20_000);
243
+ }
244
+ try {
245
+ const response = await fetchLibraryContext({ query, libraryId, researchMode }, getClientContext());
246
+ return {
247
+ content: [
248
+ {
249
+ type: "text",
250
+ text: response.data,
251
+ },
252
+ ],
253
+ };
254
+ }
255
+ finally {
256
+ if (progressInterval)
257
+ clearInterval(progressInterval);
258
+ }
225
259
  });
226
260
  async function main() {
227
261
  const transportType = TRANSPORT_TYPE;
@@ -309,9 +343,14 @@ async function main() {
309
343
  clientInfo: extractClientInfoFromUserAgent(req.headers["user-agent"]),
310
344
  transport: "http",
311
345
  };
346
+ // Use SSE responses for tool calls (enableJsonResponse: false). The SDK then
347
+ // flushes response headers immediately after parsing the request rather than
348
+ // buffering until the tool returns. This is required for long-running tools
349
+ // (e.g. researchMode) because some MCP HTTP clients cap the underlying fetch
350
+ // at 60s waiting for headers, even though the per-tool timeout is much higher.
312
351
  const transport = new StreamableHTTPServerTransport({
313
352
  sessionIdGenerator: undefined,
314
- enableJsonResponse: true,
353
+ enableJsonResponse: false,
315
354
  });
316
355
  res.on("close", () => {
317
356
  transport.close();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@upstash/context7-mcp",
3
- "version": "2.2.2",
3
+ "version": "2.2.3",
4
4
  "mcpName": "io.github.upstash/context7",
5
5
  "description": "MCP server for Context7",
6
6
  "repository": {