Pular para o conteúdo
← Back to Skalablog

Published article

How to build MCP apps with FastMCP

Software Engineering

FastMCP lets you build MCP apps: interactive Python MCP server interfaces, like charts, forms, and even Excalidraw, that render directly inside an AI chat client. It works through an official extension to the Model Context Protocol spec, and FastMCP plus the Prefab component library make it reachable without writing HTML, CSS, or JavaScript. This article explains the flow, the code, and what you can build with it.

What are MCP apps with FastMCP?

MCP apps with FastMCP are interactive interfaces that an MCP server ships to an AI client, which renders them inside the chat as a sandboxed iframe. The approach is an official extension to the Model Context Protocol spec, the open standard that connects models to external tools and data. FastMCP, a Python framework created and maintained by Jeremiah Lowin, CEO of Prefect, added support for it in 2026, along with the companion Prefab component library.

The motivating example from Lowin's September 2026 talk on the Microsoft Developer channel was Excalidraw, the whiteboard application, running live inside a chat window. Nothing proprietary powers that: the server publishes a standard resource, the client loads it, and the app talks back to the same server that produced it.

How a traditional MCP tool call works

A standard MCP tool call moves data between a model and a server, and both ends stay textual. You type a request such as "show me the team directory"; the model issues a tool call to the MCP server; the server picks the matching tool from its registry, invokes it, and returns a result containing free-text content plus a structured JSON object. The model reads that result and summarizes it conversationally.

This works well while the payload is information meant for the model to interpret. It stops working well when the right answer is a sortable table, a form, or a chart, because the model can only describe those in prose.

How MCP apps extend the tool call

MCP apps change exactly one link in that chain: the tool advertises a UI resource. The tool's metadata points to a resource with a special UI prefix, and that resource holds a full HTML, CSS, and JavaScript bundle. When the tool is invoked, the host client fetches the bundle and runs it in an iframe inside the conversation.

From there, the result is forked. The plain-text content still goes to the LLM, exactly as in a regular tool call, so the model keeps its conversational summary. The structured content is delivered straight into the iframe through a binding layer, populating the application with data that only exists at runtime.

The app can also call back into the MCP server and invoke its tools, which means the server acts as a full backend for an interface rendered mid-chat. This callback path is what powers interactive examples like the embedded whiteboard, and it is what makes refresh, drill-down, and navigation possible without leaving the conversation.

Why FastMCP ships Prefab instead of a full frontend framework

FastMCP was a Python-only framework until it introduced its first TypeScript port in 2026, and its audience is mostly Python developers, often building internal enterprise servers for colleagues rather than customer-facing products. Reimplementing the frontend ecosystem in Python was never the goal. Instead, Lowin's team identified the three patterns those users need most: tables for sharing information, forms for collecting it, and charts for visualizing it.

The result is Prefab, an open-source generative component library included with the FastMCP ecosystem. It exposes more than 125 prebuilt components (a figure the project reports), all built on React and shadcn, and driven by a declarative Python DSL. Nested Python context managers describe the layout, roughly mirroring HTML parent-child structure, and Prefab handles styling.

Under the hood, the Python description compiles to a JSON protocol that fully describes the UI. The transcript notes a practical detail worth keeping: sending the Python-side representation over the wire is more token-efficient than sending the compiled JSON, which is verbose. A small renderer inside the iframe reads that JSON and displays the interactive result.

Building your first MCP app in FastMCP

Turning an existing FastMCP tool into an MCP app takes two edits, and the transcript shows the exact code path for a team directory tool.

  1. Start with an ordinary FastMCP tool: put the decorator on a Python function, such as team_directory, that returns a dictionary of rows. The decorator is the core of the FastMCP Python DSL.
  2. Set app=True on the tool decorator. This one-line annotation tells the client the tool carries a UI resource.
  3. Return a Prefab component instead of the raw dictionary, for example a data table with a few named columns.

That is the whole change on the server. When the agent invokes the tool, you get an interactive table you can sort, filter, and page through, rather than a list the model repeats back at you.

Comparing the ways to render a UI from an MCP server

ApproachWhat you writeBest for
Raw MCP app bundleHTML, CSS, JavaScriptHighly branded, fully custom customer-facing UIs
Prefab componentsPython context managers over a JSON protocolInternal dashboards, tables, forms, and charts
Traditional tool callPython function returning JSONData the model should interpret and summarize

The Prefab path exists because, as Lowin puts it, the goal for the Python audience is not generic frontends but dashboards, data visualizations, and other ways of communicating information, where prebuilt components let the information be the star.

What you can build today

Prefab covers four practical patterns that go beyond static tables, according to the examples shown in the talk. Each one runs on the same protocol, so the server stays pure Python.

Tables, charts, and grids

Compose a data table with a pie chart inside a grid component, for example with two columns and a gap of four defined in the same Python call. The result is sortable, filterable, and pageable inside the chat, assembled from prebuilt parts rather than written from scratch.

Client-side reactivity

Prefab supports a safe subset of JavaScript authored inline alongside the Python objects. The demonstrated example, an interactive ring diagram with buttons, ran entirely in the client with no backend calls at all.

Generative UI

Because the UI is just JSON over the wire, an agent can compose Prefab components at runtime and render an interface it designed itself. Lowin framed this as more demo than daily practice today: if you know what you want, writing the composition in code is faster and more predictable.

File uploads

Uploading a file through a plain MCP tool is expensive, because the agent must emit every byte of the file as tool parameters, in Lowin's words the world's most expensive copy-paste. With an MCP app, the agent instead opens a drag-and-drop upload component, the file goes directly to the server, and only then does the agent act on it, spending no tokens on the file contents.

Themes and the Prefab docs as a living example

Lowin also noted community contributions such as Windows 2000 and MySpace themes built by Anders Swanson, a developer at dbt, who open sourced his work; the project now ships both as built-in options, since themes are ordinary CSS and Prefab compiles to a traditional application you can style however you want.

Prefab's own documentation site is reportedly the largest Prefab app so far. All 125 components and every tutorial render through the Prefab renderer itself, each page showing the Python code next to the running example, plus a live playground that streams edits instantly from the Python pane to the rendered result. It is the easiest way to try the library without installing anything.

App-provided tools: the next step for MCP apps

A newer version of the MCP spec adds app-provided tools, and support is being added to Prefab and FastMCP but is not yet released, with limited client support as of September 2026. Today, interactivity inside an MCP app is human-driven: a button in the app can call back to the server, but the agent has no way to interact with the application itself.

With app-provided tools, the application broadcasts a list of tools the agent can call. Lowin's example is tic-tac-toe: today you can mark your X in a rendered board, but the agent cannot play its O through the app except through convoluted mechanisms. Once app-provided tools land, the app exposes moves as tools, letting the agent play against you, including across several apps at once. Treat this as roadmap, not shipped capability.

Frequently asked questions

  • Do I need to know JavaScript to build MCP apps with FastMCP? No. FastMCP lets you define the interface in Python, and Prefab supplies the components and renderer. Client-side reactivity uses a constrained JavaScript subset, but the basic table, form, and chart patterns are pure Python.
  • Is Prefab open source? Yes. Lowin describes Prefab as open source and the project welcomes contributors, with Prefab's documentation itself serving as the largest known example of a Prefab application.
  • How much code does it take to turn a tool into an MCP app? Set app=True on the existing tool decorator and return a Prefab component, such as a data table, instead of a dictionary. Adding a chart next to the table is a matter of importing a grid and a pie chart and composing them in the same call.
  • Which clients support MCP apps? The mechanism is an official extension to the MCP spec, but support depends on the host client loading the UI resource and rendering the iframe. The upcoming app-provided tools feature has especially limited client support as of September 2026.
  • Why use an MCP app for file uploads? A conventional tool call forces the agent to write out every byte of the file as parameters. An upload app lets the file travel directly from your machine to the server, so the agent spends no tokens and gains access only after the upload completes.

Turn your own talks and demos into articles

The core idea in this piece is that good knowledge should not stay locked in one format: a chat deserves a real interface, and a recorded talk deserves a page people can search and cite. Developers like Gustavo dev doido, who publish walkthroughs and demos on YouTube, sit on exactly this kind of stranded material.

If you have explanations, interviews, or lessons inside your own videos, Skala Blog turns a YouTube URL into a transcription and then into a structured, publishable article, so the content works as hard in writing as it does on screen.

Source video