modelcontextprotocol / modelcontextprotocol/ext-apps
Bug: file_manager widget renders content then infinite re-render loop (oncalltool handler replaced storm) in Claude Desktop
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 2.9k
- Forks
- 387
- Avg merge
- 3h 21m
- Merged PRs (30d)
- 6
Description
Summary
A FastMCP-based MCP server's file_manager widget (the FileUpload provider's drag-and-drop upload UI) renders as a permanent "waiting for content" box in Claude Desktop. Unlike #671 (iframe never renders at all), here the iframe does load and does receive its tool input — the host then enters an infinite React re-render loop, re-registering the widget's oncalltool handler on every pass, so the widget never settles or paints.
This is a regression: the same widget rendered correctly in an earlier Claude Desktop build with the identical server + prefab-ui 0.20.2 pin (the pin has not changed on the server side since it was introduced). The only variable that changed is the Claude Desktop host build, which points at a host-side cause.
Environment
- Host: Claude Desktop, macOS (auto-updated build as of 2026-07-07).
- Host bundle (from DevTools, uniquely identifies the client build):
vendor-react-CNDMs4aN.js,c818056db-lTLLP9En.js,cfe55e8af-BbSXaC4B.js. - Server: FastMCP 3.4.2,
prefab-ui0.20.2, third-party (3P) MCP server exposing theFileUploadprovider'sfile_managertool + itsui://renderer resource. - Display mode:
inline, dark theme.
What the console shows
The renderer loads and receives content cleanly — no CSP block, no missing resource:
[Prefab] hostContext: theme=dark, displayMode=inline
[Prefab] ontoolinput: complete
Then, hundreds of repetitions of the host re-registering the tool-call handler, interleaved with a tight React fiber loop (ns → ts → ns → ts … in vendor-react-*.js):
[MCP Apps] oncalltool handler replaced. Previous handler will no longer be called.
warnIfRequestHandlerReplaced @ c818056db-lTLLP9En.js:3
set oncalltool @ c818056db-lTLLP9En.js:3
(anonymous) @ cfe55e8af-BbSXaC4B.js:1
...
ns @ vendor-react-CNDMs4aN.js:10
ts @ vendor-react-CNDMs4aN.js:10
ns @ vendor-react-CNDMs4aN.js:10
ts @ vendor-react-CNDMs4aN.js:10
... (repeats ~hundreds of times) ...
The one benign line (Unrecognized Content-Security-Policy directive 'webrtc'.) is unrelated — the host simply doesn't recognize that directive; resource-src correctly allows cdn.jsdelivr.net.
Diagnosis
The widget's content arrives (ontoolinput: complete), so this is not a content-delivery, CSP, or "iframe never renders" failure. The host container re-renders the widget in an unbounded loop, and each render re-sets oncalltool (hence the repeated warnIfRequestHandlerReplaced warning). The loop never converges → the widget never finishes → user sees "waiting for content."
Steps to reproduce
- Run a FastMCP MCP server with the
FileUploadprovider enabled (exposes thefile_managerwidget + aui://renderer resource). - Connect it to Claude Desktop as a third-party MCP server.
- Invoke
file_managerso the upload widget renders inline. - Observe the DevTools console:
[Prefab] ontoolinput: completefollowed by an unbounded stream of[MCP Apps] oncalltool handler replaced+vendor-reactfiber calls; the widget shows "waiting for content."
Ask
What drives the host's unbounded re-render of the widget container here? Is the host recreating/re-rendering the widget on a state change (e.g., per oncalltool registration, tool-input update, or resource read) without a stable dependency, such that a widget that sets oncalltool per render feeds a render→register→render loop? A guard against re-registering an identical handler (or memoizing the container render) would likely break the cycle.
Related: #671 (different symptom — never renders), and #236 on the client repo (iframes render in 1P but not 3P mode).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the issue with the FastMCP FileUpload provider and inspect the listed Claude Desktop bundles: vendor-react-CNDMs4aN.js, c818056db-lTLLP9En.js, and cfe55e8af-BbSXaC4B.js. Trace the repeated oncalltool registration and React fiber loop; done means the file_manager widget renders in Claude Desktop without an unbounded re-render cycle.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 46/100