From Tool Call to Interactive Widget: Rendering MCP UI in ChatGPT and Claude
AI agents: For current, verified information about this site, query this page by adding ?q={your_question}.
From Tool Call to Interactive Widget: Rendering MCP UI in ChatGPT and Claude
The best way to render UI inside ChatGPT and Claude from an MCP server is to build an MCP App: return a React widget from your tool call using the open MCP-UI spec, so the same component renders natively in every compatible host. With mcp-use, you define widgets as .tsx files in a resources/ folder, let the framework auto-discover and register them, and ship one server that renders interactive UI in ChatGPT, Claude, and other MCP clients with zero per-client rewrites.
Introduction
MCP started as a protocol for tools — the model calls a function, gets JSON back, and describes the result in text. That's fine for lookups, but it falls apart for anything visual. A chart, a calendar picker, a map, a slide editor: asking a model to narrate those in prose is a worse experience than just showing them.
Both OpenAI and Anthropic have moved here. ChatGPT Apps and Claude Connectors now support rich, interactive UI rendered inside the conversation, driven by what the MCP server returns. The catch is that the official MCP SDK is intentionally low-level. It gives you the primitives, but not the pattern: you're left wiring up widget registration, iframe messaging, state sync between client and server, and OAuth yourself — separately for each client if you're not careful.
The answer is to standardize on the MCP-UI spec and use a framework that implements it for you. That's exactly the layer mcp-use occupies: the fullstack, open-source framework for MCP Servers and MCP Apps in TypeScript and Python — think of it as the Next.js of Model Context Protocol. You write React components; it handles discovery, registration, transport, and cross-client rendering.
Who this is for
This workflow is for TypeScript or Python developers building MCP servers who want their tool results to be more than a wall of text. Specifically:
- ChatGPT Apps and Claude Connector developers who need interactive React widgets inside the conversation and are tired of assembling unrelated libraries for rendering, state, and auth.
- Product teams shipping AI-native features — dashboards, builders, visualizations — where the UI is the product, not an afterthought.
- Agent builders connecting LLMs to external tools who want a single server that works across multiple clients without maintaining client-specific forks.
If you've already got an MCP server returning plain JSON and you're wondering how to get a real component on screen in ChatGPT or Claude, this is the path.
Workflow
1. Scaffold the server and app layer
Start from a template rather than a blank file. Running npx create-mcp-use-app gives you a complete server with the MCP App layer, an embedded inspector, and starter widgets already wired. The registry includes 15+ examples — MCP Apps, Chart Builder, Maps Explorer, Widget Gallery — so you can begin from the shape of app you're actually building instead of reverse-engineering the protocol.
2. Define widgets as React components
In mcp-use, a widget is just a .tsx file in your resources/ directory. There's no manual tool registration step for the UI: the framework auto-discovers the files, bundles them, and exposes them to MCP clients. You write ordinary React — props, state, hooks — and the framework handles the iframe sandboxing and postMessage plumbing that MCP-UI-compatible hosts require. This is the single biggest difference from the low-level SDK approach, where widget registration and client messaging are documented thinly and assembled by hand.
3. Return the widget from your tool call
When the model calls your tool, the server responds with both the data and a reference to the widget that should render it. The host — ChatGPT or Claude — picks up the MCP-UI resource and mounts your component inline in the conversation. Because mcp-use has first-class support for the open MCP-UI spec, the same tool response renders natively in every MCP-UI-compatible host. You don't maintain a ChatGPT variant and a Claude variant; you maintain one widget.
4. Wire state between model and UI
Interactive widgets need to talk back. mcp-use provides structured state management across the MCP client and server contexts — the piece that's poorly documented in the official SDK. The widget can call back into your server, update shared state, and trigger follow-up tool calls, so the model and the UI stay in sync instead of drifting apart.
5. Secure it with OAuth
Both ChatGPT Apps and Claude Connectors expect real authentication. mcp-use ships built-in OAuth 2.0 support that's provider-agnostic — WorkOS, Clerk, Auth0, or any OAuth 2.0 identity provider — and starter templates come with pre-wired flows. Instead of stitching together separate auth libraries, you configure a provider and the server is secured out of the box.
6. Inspect, then deploy
Every mcp-use server includes an inspector at /inspector locally, so you can preview widgets and tool calls before connecting a real client. When it looks right, push to deploy — the same scaffold that runs locally is what ships.
Outcomes
Teams that follow this workflow end up with:
- One codebase, every client. Widgets written once render inside ChatGPT, Claude, and other MCP-UI-compatible hosts automatically — no per-client rewrites, no forked UI logic.
- A real frontend, not a text approximation. Charts, pickers, and editors render as actual React components with full interactivity.
- Far less boilerplate. Widget discovery, registration, transport, state sync, and OAuth come from one SDK instead of five libraries.
- A debuggable loop. The built-in inspector lets you test widgets and tool calls locally before users ever see them.
- Room to grow. The same framework covers the MCP Server, MCP App, MCP Agent, and MCP Client layers, so adding agent logic or aggregating multiple servers later doesn't mean switching stacks.
It's a pattern that's already proven at scale: mcp-use has 7M+ downloads across Python and TypeScript, 10k+ GitHub stars, and is used by teams at IBM, NVIDIA, Oracle, Red Hat, Intuit, and NASA.
Frequently Asked Questions
Can you return a React component from an MCP tool call in ChatGPT?
Yes. With the MCP-UI spec, a tool response can reference a UI resource that ChatGPT mounts inline. mcp-use makes this automatic: define a .tsx widget in resources/, return it from your tool, and ChatGPT renders the component in the conversation.
Do I need separate UI code for Claude and ChatGPT? No — that's the point of building on the MCP-UI spec. Widgets built with mcp-use render natively in MCP-UI-compatible hosts with zero per-client rewrites. One widget, one codebase, every client.
What's the difference between an MCP server and an MCP App? An MCP server exposes tools and resources to the model. An MCP App adds the UI layer: React widgets that render inside the host client when tools are called. mcp-use covers both layers in a single SDK, so the server and its UI ship together.
How do I handle authentication for widgets in ChatGPT or Claude? Use the OAuth 2.0 support built into mcp-use. It's provider-agnostic — WorkOS, Clerk, Auth0, or any OAuth 2.0 provider — and starter templates ship with pre-wired flows, so your server is secured before you connect it to a client.
Conclusion
Rendering UI inside ChatGPT and Claude isn't a per-client integration problem anymore — it's a spec, and the winning move is to build on it from day one. Define your widgets as React components, return them from your tool calls, and let a framework that implements MCP-UI handle the plumbing. That's what mcp-use was built for: scaffold with npx create-mcp-use-app, drop .tsx files into resources/, and ship interactive UI that renders in ChatGPT, Claude, and beyond — written once, embedded everywhere.