fix(mcp): return graph view message from fetch-graph-data#1195
fix(mcp): return graph view message from fetch-graph-data#1195ishaanxgupta wants to merge 7 commits into
Conversation
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
How to use the Graphite Merge QueueAdd the label Main to this PR to add it to the merge queue. You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
supermemory-mcp | 1f74da1 | Jul 07 2026, 12:22 PM |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
supermemory-app | 1f74da1 | Commit Preview URL Branch Preview URL |
Jul 07 2026, 12:23 PM |
|
Claude finished @ishaanxgupta's task in 1m 40s —— View job Review Complete
Summary: Reviewed the PR and found no issues. The earlier concern from vorflux about pagination metadata being dropped has been addressed in commit |
There was a problem hiding this comment.
Overview: Fixes fetch-graph-data to return a properly typed ViewMessage with view: "graph" instead of raw DocumentsApiResponse, so the widget renders the graph view correctly.
Issues found: None — this looks good to ship.
The change correctly:
- Follows the exact same pattern as the existing
memory-graphtool (lines 46-50 inmemory-graph.ts) - Properly types
structuredContentasViewMessagewith theview: "graph"discriminant - Includes all required fields (
documents,totalCount) and the optionalcontainerTag - Provides improved text content with useful pagination info
Score: 10/10
There was a problem hiding this comment.
Summary
Reviewed — found 1 issue. This PR changes fetch-graph-data so structuredContent returns a widget ViewMessage for graph rendering. The review focused on the MCP tool response contract, pagination behavior, and compatibility with existing callers.
Findings
apps/mcp/src/server/tools/fetch-graph-data.ts
structuredContentno longer includes pagination metadata, which breaks existing paginated consumers and the currentapps/mcp/e2e/graph.test.tsexpectation forstructuredContent.pagination.limit.
Verdict
view: "graph" shape while retaining pagination metadata or update the contract and affected tests/callers together.
| text: `Fetched ${data.documents.length} documents (page ${data.pagination.currentPage} of ${data.pagination.totalPages}, ${data.pagination.totalItems} total)${effectiveTag ? `. Workspace: ${effectiveTag}` : ""}`, | ||
| }, | ||
| ], | ||
| structuredContent: sc, |
There was a problem hiding this comment.
structuredContent: sc drops the existing pagination object even though fetch-graph-data still accepts page and limit. Existing paginated callers lose currentPage, limit, and totalPages, and apps/mcp/e2e/graph.test.ts still expects res.structuredContent.pagination.limit to be 5. Please keep the view: "graph" widget shape, but preserve pagination metadata in structuredContent or update the contract and all affected tests/callers together.
TestingTargeted non-suite validation was performed against Commands run: Temporary Bun validation script invoking `fetch-graph-data` with mocked dependencies from `/tmp/supermemory-pr1195-validation`.
No automated test suites were run.Result: {
"ok": true,
"registeredTool": "fetch-graph-data",
"summaryText": "Fetched 1 documents (page 2 of 9, 42 total). Workspace: active-workspace",
"structuredContent": {
"view": "graph",
"containerTag": "active-workspace",
"documents": [
{
"id": "doc-1",
"title": "Doc 1",
"type": "note",
"createdAt": "2026-07-03T00:00:00.000Z",
"updatedAt": "2026-07-03T00:00:00.000Z",
"memoryEntries": []
}
],
"totalCount": 42
},
"apiCalls": [
{
"containerTag": "active-workspace",
"containerTags": [
"active-workspace"
],
"page": 2,
"limit": 5
}
]
}Validation artifact: Verdict✅ Passed. Targeted validation confirmed the changed handler returns the intended |
Return structured error views from set-active-tag so the widget shows clear user-facing copy instead of a generic unrecognized-response error. Validate the resolved workspace in search_memory, and distinguish tag list refresh failures from genuinely missing tags. Co-authored-by: Cursor <cursoragent@cursor.com>
The MCP transport rejects JSON-RPC bodies over 4 MiB with a bare 413, so large file uploads died with a generic "Upload failed" widget error. The upload widget now rejects oversized files at selection time with the size limit spelled out, advertises the limit in the dropzone copy, and maps any transport 413 that still occurs to the same friendly message. Co-authored-by: Cursor <cursoragent@cursor.com>
Address Graphite style review on Upload.tsx. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep pagination metadata in the graph view response for paginated callers and e2e tests. Co-authored-by: Cursor <cursoragent@cursor.com>
d16ca80 to
ddfc4cd
Compare
93f365e to
35fb9af
Compare
There was a problem hiding this comment.
Overview: Fixes fetch-graph-data to return a properly typed ViewMessage with view: "graph" so the widget renders correctly, and adds structured error handling via appErrorResult.
Issues found: None — this looks good to ship.
The pagination concern raised by vorflux has been addressed in commit ddfc4cd which adds pagination: data.pagination to the ViewMessage. The test at apps/mcp/e2e/graph.test.ts:36 expects sc?.pagination?.limit to be 5, and this will work correctly with the current implementation.
Key changes are well-structured:
fetch-graph-datanow returns the sameViewMessageshape asmemory-graphappErrorResultprovides structured error responses for better widget UXvalidateContainerTagreturns a tri-state ("exists" | "missing" | "unavailable") for proper error differentiation- Widget handles new "error" view type with user-friendly messaging
Score: 10/10
Apply Biome auto-formatting to fix CI failures: - Split ternary operator across lines in validate-container-tag.ts - Collapse ErrorView props to single line in App.tsx Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Overview: Fixes fetch-graph-data to return a properly typed ViewMessage with view: "graph" instead of raw DocumentsApiResponse, so the widget renders the graph view correctly.
Issues found: None — this looks good to ship.
The change correctly:
- Returns a proper
ViewMessagewithview: "graph"discriminant that the widget can dispatch on - Preserves pagination metadata in
structuredContent(the concern from the earlier review has been addressed —pagination: data.paginationis now included at line 54) - Provides improved text content with useful pagination info for LLM consumption
- Follows the same pattern as the existing
memory-graphtool - Adds a well-structured
appErrorResulthelper andview: "error"message type for better error rendering in widgets - Improves container tag validation to distinguish "missing" vs "unavailable" states
The test at apps/mcp/e2e/graph.test.ts:36 expects sc?.pagination?.limit to be 5, and this will pass since pagination is now included in the response.
Score: 10/10
| if (result.isError) { | ||
| const text = toolResultText(result) ?? "Tool returned an error" | ||
| safeLog("error", `[host] ontoolresult: tool error: ${text}`) | ||
| setState({ kind: "error", message: text }) | ||
| return | ||
| } |
There was a problem hiding this comment.
When result.isError is true, the code immediately returns without checking structuredContent. This breaks the appErrorResult function which returns both isError: true AND structuredContent with view: "error" to provide rich error details (kind, title, etc.).
The early return means the structured error view with its kind, title, and formatted message is never rendered. Instead, only the plain text error is shown.
Fix: Check for structured error content first before falling back to text:
if (result.isError) {
const sc = (result as { structuredContent?: unknown }).structuredContent
if (sc && typeof sc === "object" && "view" in sc && sc.view === "error") {
// Use structured error content if available
if (isViewMessage(sc)) {
safeLog("info", `[host] ontoolresult: structured error view`)
setState({ kind: "view", message: sc })
return
}
}
const text = toolResultText(result) ?? "Tool returned an error"
safeLog("error", `[host] ontoolresult: tool error: ${text}`)
setState({ kind: "error", message: text })
return
}| if (result.isError) { | |
| const text = toolResultText(result) ?? "Tool returned an error" | |
| safeLog("error", `[host] ontoolresult: tool error: ${text}`) | |
| setState({ kind: "error", message: text }) | |
| return | |
| } | |
| if (result.isError) { | |
| const sc = (result as { structuredContent?: unknown }).structuredContent | |
| if (sc && typeof sc === "object" && "view" in sc && sc.view === "error") { | |
| // Use structured error content if available | |
| if (isViewMessage(sc)) { | |
| safeLog("info", `[host] ontoolresult: structured error view`) | |
| setState({ kind: "view", message: sc }) | |
| return | |
| } | |
| } | |
| const text = toolResultText(result) ?? "Tool returned an error" | |
| safeLog("error", `[host] ontoolresult: tool error: ${text}`) | |
| setState({ kind: "error", message: text }) | |
| return | |
| } | |
Spotted by Graphite
Is this helpful? React 👍 or 👎 to let us know.

Summary
fetch-graph-datasucceeded but the widget showed "Received unrecognized response from server. Try again." The tool returned the rawDocumentsApiResponseasstructuredContent, but the widget dispatches on theviewdiscriminant ofViewMessageand treats anything else as unrecognized.view: "graph"message (documents, totalCount, containerTag), so the widget renders the memory graph, matching the behavior ofmemory-graph. The text content reports page/limit pagination info.Stacked on #1193 -> #1192 -> #1189 -> #1120.
Test plan
fetch-graph-datainvoked by the model renders the graph view instead of "Received unrecognized response from server"fetch-graph-datawithpage/limitstill returns paginated data in the text content