Skip to content

fix(mcp): flush analytics within the request lifetime and bound API-key auth fetch#1270

Open
abhay-codes07 wants to merge 2 commits into
supermemoryai:mainfrom
abhay-codes07:fix/mcp-analytics-and-auth-reliability
Open

fix(mcp): flush analytics within the request lifetime and bound API-key auth fetch#1270
abhay-codes07 wants to merge 2 commits into
supermemoryai:mainfrom
abhay-codes07:fix/mcp-analytics-and-auth-reliability

Conversation

@abhay-codes07

Copy link
Copy Markdown
Contributor

What

Two request-lifecycle reliability gaps in the MCP worker, one commit each:

1. PostHog events are buffered but never flushed, so they're routinely lost.

posthog-node buffers capture() calls and only sends them when flushAt (20 events) or flushInterval (10s) trips. The tool handlers call the capture helpers fire-and-forget with nothing keeping the Durable Object alive, so whenever the isolate is evicted before a periodic flush — the normal case for a session that emits one memory_added / memory_search / memory_forgot per tool call — the buffered events are silently dropped. The exported shutdown() was never wired to anything either. Analytics undercount real usage.

Fix: each helper now flushes explicitly after capturing, and the three call sites in server.ts keep the returned promise alive past the response with this.ctx.waitUntil(...) — the standard Workers pattern for post-response work. Error handling is unchanged (tracking failures still only log).

2. validateApiKey has no upstream timeout.

validateOAuthToken aborts its session call after 30s (AbortSignal.timeout(30_000)), but the API-key path had no signal at all — a hung /v3/session response stalls every API-key-authenticated MCP request until platform limits kick in. Fix: apply the same timeout; the existing catch already maps TimeoutError to a null auth result (clean 401).

Testing

  • vitest run in apps/mcp — format + auth suites pass; the 3 pre-existing failures in e2e/oauth.test.ts (no-secret tests against the production server) fail identically on a clean main checkout, verified side by side
  • wrangler deploy --dry-run — worker bundles cleanly
  • biome check on the three touched files — clean
  • posthog-node 5.28.0 (the installed version) exposes flush(): Promise<void>, and DurableObjectState.waitUntil is present in the pinned @cloudflare/workers-types

posthog-node buffers capture() calls and only sends them when flushAt
(20 events) or flushInterval (10s) trips. The MCP tool handlers called
capture() fire-and-forget with nothing keeping the Durable Object
alive, so whenever the isolate was evicted before the periodic flush —
the normal case for low-traffic sessions emitting one memory_added /
memory_search / memory_forgot event per tool call — the buffered
events were silently dropped. The exported shutdown() was never wired
to anything either.

Flush explicitly after each capture and keep the returned promise
alive past the response with ctx.waitUntil(), the standard Workers
pattern for post-response work.
…s OAuth

validateOAuthToken aborts its upstream session call after 30 seconds,
but validateApiKey had no signal at all, so a hung /v3/session response
stalled every API-key-authenticated MCP request until platform limits
kicked in instead of failing cleanly. Apply the same AbortSignal
timeout; the existing catch already maps TimeoutError to a null auth
result.
Copilot AI review requested due to automatic review settings July 12, 2026 20:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants