Show HN: Stop returning raw JSON from MCP servers, build rich inline UIs

muhammad-shafat1 pts0 comments

MCP Apps Tutorial: Interactive UI in MCP Servers with Python | Towards AISitemapOpen in appSign up<br>Sign in

Medium Logo

Get app<br>Write

Search

Sign up<br>Sign in

Towards AI

We build Enterprise AI. We teach what we learn. Join 100K+ AI practitioners on Towards AI Academy. Free: 6-day Agentic AI Engineering Email Guide: https://email-course.towardsai.net/

MCP Apps: Build Interactive Apps Directly Inside Your AI Agent’s Chat

A walkthrough of the MCP Apps protocol extension, with a working weather card in Python and a real-world application in LangGraph debugging.

Muhammad Abdullah Shafat Mulkana

6 min read·<br>Just now

Listen

Share

Press enter or click to view image in full size

A side-by-side comparison showcasing how MCP Apps transforms raw text tool outputs into rich, interactive user interfaces. Source: Image by the authorI remember the first time I saw a tool call result come back from an MCP server. I had just wired up a simple weather tool to Claude, and watching the model reach out, grab live data, and weave it into a response felt genuinely magical. But then I looked at the raw output sitting in the terminal, a wall of JSON, and thought: this is powerful, but it is also a little bleak. The model could tell me the current temperature and conditions, but it could not show me a forecast card, a map, or a live chart. Everything was still just text.<br>That limitation is more significant than it might seem at first. We live in a world where interfaces matter. A plain number is not the same as a graph that lets you spot a trend. MCP gave AI agents a standardized way to reach out and connect with the world, but that world was still trapped in a text-only interface.<br>MCP Apps change that.<br>The polished version of this already exists. Ask Claude for music through the Spotify MCP App and you get a widget you can actually use, not a numbered list in markdown.

Spotify MCP App rendering a playlist search result as an interactive widget inside Claude. Source: Image by the authorA quick recap on MCP servers<br>If you have been keeping up with the AI space over the last year, you have probably heard the term MCP thrown around quite a bit. But for those who are new to it, here is the short version.<br>MCP, or the Model Context Protocol, is an open standard introduced by Anthropic. The core idea is simple: instead of having to build individual one-off integrations for tools and data sources, MCP provides a common interface. An MCP server exposes a set of tools, and any MCP-compatible host, whether that is Claude, Cursor, or your own custom agent, can discover and call those tools in a uniform way. It is often described as the USB of AI tooling.<br>A typical MCP server might expose tools to read and write files, query a database, search the web, or call an external API. That was a genuine step forward. But text-only output is still a real constraint. The tool runs, the data comes back, and what the human sees is usually whatever the host decides to print.<br>What MCP Apps add<br>MCP Apps is a formal extension to MCP, standardized in early 2026. The core idea is that an MCP server can now declare UI resources along with its tools. When a supporting host like Claude calls a tool, it can render a full interactive HTML widget inline in the conversation, not just print the result as text.<br>Three roles show up in every implementation:<br>Server. Your code. It declares tools, serves data, and registers UI layouts at a ui:// URI.<br>Host. The client you chat with (Claude Desktop, Cursor, Copilot, and others).<br>View. HTML and JavaScript running inside that iframe. It renders the tool result and can ask the host to call tools again when the user interacts.<br>Hosts that do not support the extension ignore the UI metadata and keep returning plain tool output. The full specification lives at apps.extensions.modelcontextprotocol.io.<br>What happens when a tool runs<br>The static breakdown above becomes clearer once you follow a single request through the system. Say the model calls a weather tool:<br>User asks for a forecast<br>→ Host calls show_weather on your Server<br>→ Server returns data + a ui:// link in tool metadata<br>→ Host fetches the HTML resource and mounts it (the View)<br>→ Host pushes the tool result into the iframe<br>User toggles °C / °F or hits Refresh<br>→ View asks the Host to call fetch_weather (not the model)<br>→ Server returns fresh data; the card updates in placeTwo details matter once you see that loop. First, linking a tool to its UI is one metadata field:<br>"_meta": {<br>"ui": {<br>"resourceUri": "ui://weather-mcp-app/forecast-card.html",<br>"visibility": ["model", "app"] }<br>}Second, not every tool belongs in the model’s tool list. A refresh button or a unit toggle should use visibility: ["app"]. The model never sees those tools. That was the insight that made MCP Apps click for me: they are not prettier JSON in the chat. They are a second client, with their own tools, living inside the conversation.<br>Get Muhammad Abdullah Shafat Mulkana’s stories in your inbox

Join...

tool apps tools host server model

Related Articles