From e706a13877d6f46192eb8f4d2bd92e2b1cabdb30 Mon Sep 17 00:00:00 2001 From: Dhravya Shah Date: Mon, 29 Jun 2026 12:28:14 -0700 Subject: [PATCH] Merge timeout additions for supermemory-mcp (#1144) Co-authored-by: Cursor Agent Co-authored-by: Polylane Automation --- apps/mcp/src/auth.ts | 1 + apps/mcp/src/client.ts | 18 ++++++++++-------- apps/mcp/src/index.ts | 1 + 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/apps/mcp/src/auth.ts b/apps/mcp/src/auth.ts index 7bd3b946..7bf6bc1b 100644 --- a/apps/mcp/src/auth.ts +++ b/apps/mcp/src/auth.ts @@ -103,6 +103,7 @@ export async function validateOAuthToken( headers: { Authorization: `Bearer ${token}`, }, + signal: AbortSignal.timeout(30_000), }) if (!sessionResponse.ok) { diff --git a/apps/mcp/src/client.ts b/apps/mcp/src/client.ts index 1a405979..2ce8d41a 100644 --- a/apps/mcp/src/client.ts +++ b/apps/mcp/src/client.ts @@ -2,6 +2,7 @@ import Supermemory from "supermemory" const MAX_CHARS = 200000 // ~50k tokens (character-based limit) const DEFAULT_PROJECT_ID = "sm_project_default" +const FETCH_TIMEOUT_MS = 30_000 interface MemoryRichFields { metadata?: Record | null @@ -142,7 +143,7 @@ export class SupermemoryClient { this.client = new Supermemory({ apiKey: bearerToken, baseURL: apiUrl, - timeout: 30_000, + timeout: FETCH_TIMEOUT_MS, }) this.containerTag = containerTag || DEFAULT_PROJECT_ID } @@ -329,15 +330,16 @@ export class SupermemoryClient { } // Get projects list - async getProjects(): Promise { + async getProjects(options?: { signal?: AbortSignal }): Promise { try { + const signal = options?.signal ?? AbortSignal.timeout(FETCH_TIMEOUT_MS) const response = await fetch(`${this.apiUrl}/v3/projects`, { method: "GET", headers: { Authorization: `Bearer ${this.bearerToken}`, "Content-Type": "application/json", }, - signal: AbortSignal.timeout(30_000), + signal, }) if (!response.ok) { @@ -361,8 +363,10 @@ export class SupermemoryClient { containerTags?: string[], page = 1, limit = 10, + options?: { signal?: AbortSignal }, ): Promise { try { + const signal = options?.signal ?? AbortSignal.timeout(FETCH_TIMEOUT_MS) const response = await fetch(`${this.apiUrl}/v3/documents/documents`, { method: "POST", headers: { @@ -376,7 +380,7 @@ export class SupermemoryClient { order: "desc", containerTags, }), - signal: AbortSignal.timeout(30_000), + signal, }) if (!response.ok) { throw Object.assign(new Error("Failed to fetch documents"), { @@ -390,14 +394,12 @@ export class SupermemoryClient { } private handleError(error: unknown): never { - // Handle request timeout / abort + // Handle request timeout (AbortSignal.timeout or explicit abort) if ( error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError") ) { - throw new Error( - "Request timed out after 30 seconds. The service may be slow or unavailable. Please try again.", - ) + throw new Error("Request to Supermemory API timed out") } // Handle network/fetch errors diff --git a/apps/mcp/src/index.ts b/apps/mcp/src/index.ts index 846064e1..45731982 100644 --- a/apps/mcp/src/index.ts +++ b/apps/mcp/src/index.ts @@ -89,6 +89,7 @@ app.get("/.well-known/oauth-authorization-server", async (c) => { // Fetch the authorization server metadata from the main API const response = await fetch( `${apiUrl}/.well-known/oauth-authorization-server`, + { signal: AbortSignal.timeout(30_000) }, ) if (!response.ok) {