@upstash/context7-mcp 4.0.1 → 4.0.2

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 CHANGED
@@ -282,7 +282,17 @@ async function main() {
282
282
  // no session store. The handler serves modern (2026-07-28) traffic natively
283
283
  // and 2025-era traffic through its stateless legacy fallback, which answers
284
284
  // GET/DELETE (session operations) with 405.
285
+ // keepAliveMs: 0 disables SSE keepalive heartbeats. Every tool here is a
286
+ // millisecond vector query (p100 ~28s), so no legitimate exchange needs a
287
+ // heartbeat to stay alive — but a hung exchange kept "alive" by heartbeats
288
+ // can never be reaped by the gateway's stream idle timeout. A batch
289
+ // carrying a request plus its own notifications/cancelled produces exactly
290
+ // that: per spec the cancelled request gets no response, the SDK transport
291
+ // then never closes the stream, and with heartbeats it survived until the
292
+ // gateway's 1200s hard cap (the 2026-08-11 outage). Silent hangs instead
293
+ // go idle and the gateway reaps them at streamIdleTimeout (300s).
285
294
  const mcpHandler = createMcpHandler(() => createMcpServer(), {
295
+ keepAliveMs: 0,
286
296
  onerror: (error) => console.error("MCP handler error:", error),
287
297
  });
288
298
  // Without onerror, request-conversion / handler.fetch throws are answered
package/dist/lib/api.js CHANGED
@@ -3,6 +3,13 @@ import { Agent, ProxyAgent, setGlobalDispatcher } from "undici";
3
3
  import { CONTEXT7_API_BASE_URL } from "./constants.js";
4
4
  import { readFileSync } from "fs";
5
5
  import tls from "tls";
6
+ /**
7
+ * Ceiling on a single Context7 API call. Without a signal a stalled backend
8
+ * call rides undici's ~300s default before failing. 60s is generous for these
9
+ * vector queries: p99.9 is ~3.2s, and no request exceeded 30s across a full
10
+ * day of production traffic.
11
+ */
12
+ const API_TIMEOUT_MS = 60_000;
6
13
  /**
7
14
  * Parses error response from the Context7 API
8
15
  * Extracts the server's error message, falling back to status-based messages if parsing fails
@@ -99,7 +106,7 @@ export async function searchLibraries(query, libraryName, context = {}) {
99
106
  url.searchParams.set("query", query);
100
107
  url.searchParams.set("libraryName", libraryName);
101
108
  const headers = generateHeaders(context);
102
- const response = await fetch(url, { headers });
109
+ const response = await fetch(url, { headers, signal: AbortSignal.timeout(API_TIMEOUT_MS) });
103
110
  readPromptSignal(response, context);
104
111
  if (!response.ok) {
105
112
  const errorMessage = await parseErrorResponse(response, context.apiKey);
@@ -127,7 +134,7 @@ export async function fetchLibraryContext(request, context = {}) {
127
134
  url.searchParams.set("query", request.query);
128
135
  url.searchParams.set("libraryId", request.libraryId);
129
136
  const headers = generateHeaders(context);
130
- const response = await fetch(url, { headers });
137
+ const response = await fetch(url, { headers, signal: AbortSignal.timeout(API_TIMEOUT_MS) });
131
138
  readPromptSignal(response, context);
132
139
  if (!response.ok) {
133
140
  const errorMessage = await parseErrorResponse(response, context.apiKey);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@upstash/context7-mcp",
3
- "version": "4.0.1",
3
+ "version": "4.0.2",
4
4
  "mcpName": "io.github.upstash/context7",
5
5
  "description": "MCP server for Context7",
6
6
  "repository": {