Skip to content

Commit 0fc92ba

Browse files
committed
Add MCP Apps blog post with video demo and architecture diagram
1 parent e48bc68 commit 0fc92ba

File tree

7 files changed

+292
-0
lines changed

7 files changed

+292
-0
lines changed

.vitepress/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export default defineConfig({
7171
text: 'Blog',
7272
items: [
7373
{ text: 'All Posts', link: '/blog/' },
74+
{ text: 'MCP Apps: Interactive Tools', link: '/blog/mcp-apps-interactive-tools' },
7475
{ text: 'Demo is Live', link: '/blog/demo-launch' },
7576
{ text: 'BYOK & Custom MCP Servers', link: '/blog/whats-new-jan-2026' },
7677
{ text: 'Cutting Context by 60%', link: '/blog/token-optimization-toon-rag' },

blog/index.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ Technical articles about building efficient AI agents with Agentic Forge.
66

77
<div class="blog-list">
88

9+
### [MCP Apps: Interactive Tools for AI Agents](/blog/mcp-apps-interactive-tools)
10+
*February 2026*
11+
12+
Tools can now include interactive UI components. Our first MCP App: a location picker that renders a Leaflet.js map directly in the chat—click to select coordinates, search by name, or use your current location.
13+
14+
---
15+
916
### [Agentic Forge Demo is Live](/blog/demo-launch)
1017
*January 2026*
1118

blog/mcp-apps-interactive-tools.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# MCP Apps: Interactive Tools for AI Agents
2+
3+
*February 2026*
4+
5+
AI tool calling has a limitation: it's one-way. The LLM calls a tool, gets a result, and moves on. But what if the tool needs user input that's hard to describe in words—like picking a location on a map? We've implemented MCP Apps in Agentic Forge to bridge this gap, starting with an interactive location picker for our weather server.
6+
7+
## The Problem: Some Inputs Need a UI
8+
9+
Consider asking an agent: "What's the weather at my favorite hiking spot?"
10+
11+
The agent can call a weather API, but it doesn't know *where* your hiking spot is. It could ask you to describe it, but coordinates from memory are imprecise. What if you could just... point to it on a map?
12+
13+
This is the kind of interaction that text-based tools can't handle well. You need a visual interface.
14+
15+
## What are MCP Apps?
16+
17+
MCP Apps are an extension to the Model Context Protocol that allows tools to include interactive UI components. When a tool returns a response with UI metadata, the host application renders the interface in a sandboxed iframe, letting users interact directly before the conversation continues.
18+
19+
The specification was [introduced by Anthropic in November 2025](https://blog.modelcontextprotocol.io/posts/2025-11-21-mcp-apps/) and reached stable 1.0 in [January 2026](https://blog.modelcontextprotocol.io/posts/2026-01-26-mcp-apps/). It's since been adopted by major platforms including [OpenAI's ChatGPT](https://developers.openai.com/apps-sdk/mcp-apps-in-chatgpt/).
20+
21+
## Our First MCP App: Location Picker
22+
23+
We built a location picker app for the weather MCP server. Here it is in action:
24+
25+
<video controls width="100%" style="border-radius: 8px; margin: 1rem 0;">
26+
<source src="/videos/mcp-app-location-selection.mp4" type="video/mp4">
27+
Your browser does not support the video tag.
28+
</video>
29+
30+
The flow works like this:
31+
32+
1. **User asks** about weather at an unspecified location
33+
2. **Agent calls** the `pick_location` tool
34+
3. **Map UI appears** with search and click-to-select
35+
4. **User picks** their location visually
36+
5. **Agent continues** with the selected coordinates
37+
38+
No need to describe latitude/longitude or spell out addresses—just point and click.
39+
40+
## Architecture
41+
42+
MCP Apps add a UI layer on top of standard tool calling:
43+
44+
![MCP Apps Architecture](/diagrams/mcp-apps-architecture.svg)
45+
46+
The diagram shows the complete flow:
47+
48+
1. The agent calls `pick_location`, which returns a `_meta.ui` field pointing to a UI resource
49+
2. forge-ui fetches the HTML from the MCP server (via Armory) and renders it in a sandboxed iframe
50+
3. The user interacts with the map—clicking to select a location or searching by name
51+
4. When the user clicks "Continue", the app calls `updateModelContext` to pass the selected coordinates back to the conversation
52+
53+
The app runs completely sandboxed—no access to the parent page's DOM or storage. Communication happens through JSON-RPC messages over `postMessage`.
54+
55+
## How It Works
56+
57+
### Server Side
58+
59+
The MCP server defines both the tool and the UI resource. The tool returns a `_meta.ui` field containing the resource URI, required permissions (like geolocation), and whether user interaction is required before continuing.
60+
61+
### App Side
62+
63+
The location picker is a Vue 3 app bundled to a single HTML file using `vite-plugin-singlefile`. It uses the official `@modelcontextprotocol/ext-apps` SDK for communication with the host.
64+
65+
The app can call tools on its parent MCP server—the geocoding search reuses the weather server's existing `geocode` tool rather than implementing its own. When the user selects a location, the app calls `updateModelContext` to send the coordinates back.
66+
67+
### Host Side
68+
69+
forge-ui's `McpAppRenderer` component handles rendering and message routing. It fetches the HTML resource, creates the sandboxed iframe, and sets up the JSON-RPC bridge. When the app calls `updateModelContext`, the host captures the data and makes it available for the LLM's next turn.
70+
71+
## Security Model
72+
73+
MCP Apps run in sandboxed iframes with minimal permissions:
74+
75+
- **Sandboxed execution**`allow-scripts allow-forms` only, no access to parent DOM
76+
- **Origin validation** — Communication only via `postMessage` with source verification
77+
- **Permission requests** — Apps can request additional permissions (like `geolocation`) which the host may grant
78+
- **Proxied tool calls** — All tool calls go through the host, maintaining an audit trail
79+
80+
This means a malicious MCP App can't steal cookies, access local storage, or manipulate the chat interface.
81+
82+
## Building Your Own MCP Apps
83+
84+
The location picker serves as a reference implementation. The key components are:
85+
86+
| File | Purpose |
87+
|------|---------|
88+
| `src/App.vue` | Main component, state management |
89+
| `src/composables/useAppBridge.ts` | JSON-RPC bridge to host |
90+
| `src/components/MapView.vue` | Leaflet.js map rendering |
91+
| `vite.config.ts` | Bundle to single HTML file |
92+
93+
The build produces a self-contained HTML file with inlined JS and CSS. Deployment is simple—just serve the file as a text resource from your MCP server.
94+
95+
## What's Next
96+
97+
The location picker is our first MCP App, but the pattern opens up many possibilities:
98+
99+
- **Weather Explorer** — Interactive dashboard with charts and forecasts
100+
- **Search Refinement** — Visual filters for web search results
101+
- **Data Visualization** — Charts and graphs for analytical tools
102+
- **Form Builders** — Complex input collection that would be tedious in text
103+
104+
We're also working on dark/light theme synchronization so apps match the host's appearance automatically.
105+
106+
## Try It
107+
108+
The location picker is available in the [demo](https://agentic-forge.compulife.com.pk). Ask the agent about weather at a location and see the map appear.
109+
110+
## Source Code
111+
112+
- [mcp-weather](https://github.com/agentic-forge/mcp-weather) — Weather server with location picker app
113+
- [forge-ui](https://github.com/agentic-forge/forge-ui) — Host implementation with McpAppRenderer
114+
- [forge-armory](https://github.com/agentic-forge/forge-armory) — Gateway with ui:// resource routing
115+
116+
## References
117+
118+
- [MCP Apps Announcement](https://blog.modelcontextprotocol.io/posts/2025-11-21-mcp-apps/) — Original introduction
119+
- [MCP Apps 1.0 Specification](https://blog.modelcontextprotocol.io/posts/2026-01-26-mcp-apps/) — Stable release
120+
- [@modelcontextprotocol/ext-apps](https://www.npmjs.com/package/@modelcontextprotocol/ext-apps) — Official SDK
121+
- [OpenAI MCP Apps Integration](https://developers.openai.com/apps-sdk/mcp-apps-in-chatgpt/) — ChatGPT adoption
122+
123+
---
124+
125+
*This is part of a series on building [Agentic Forge](https://agentic-forge.github.io).*

docs/index.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ Tool results are converted from JSON to TOON (Token-Oriented Object Notation) at
3030

3131
Instead of loading all tools into context, Tool RAG uses semantic search to dynamically select only relevant tools. Our benchmarks show 60% context reduction when combined with TOON format.
3232

33+
### Interactive Tool UIs with MCP Apps
34+
35+
Tools can include interactive UI components that render in the chat. Our location picker demonstrates this—users click on a map to select coordinates instead of typing them. Built on the [MCP Apps specification](https://blog.modelcontextprotocol.io/posts/2026-01-26-mcp-apps/) with sandboxed iframes and JSON-RPC messaging.
36+
3337
## Data Flow
3438

3539
<div class="diagram-container">

index.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ Seamless translation between OpenAI, Anthropic, Gemini formats and MCP protocol.
8383
### 🔧 Smart Routing
8484
Rule-based routing to select models and tools based on task characteristics.
8585

86+
### 🖼️ MCP Apps
87+
Interactive UI components embedded in tool responses. Maps, forms, and visualizations render directly in the chat.
88+
8689
### 🔍 Observability
8790
Hooks and middleware for logging, metrics, cost tracking, and custom logic injection.
8891

Lines changed: 152 additions & 0 deletions
Loading
7.18 MB
Binary file not shown.

0 commit comments

Comments
 (0)