Skip to content

Commit b9f4bce

Browse files
committed
feat: add Python/Gradio host example for HF Spaces deployment
Add a new example host implementation using Python and Gradio that can be deployed to Hugging Face Spaces. This demonstrates how to integrate MCP Apps into a Python-based web application. Key features: - Uses Python MCP SDK for server connections - Embedded JavaScript bridge handles iframe postMessage protocol - Double-iframe sandbox architecture for security - CSP injection from resource metadata - Supports tool execution and UI resource display Architecture: - Python backend: MCP client, tool discovery, execution - JavaScript bridge: JSON-RPC protocol, postMessage handling - Sandbox proxy: Message relay, CSP enforcement - Inner iframe: Guest UI execution Files: - app.py: Main Gradio application with MCP integration - requirements.txt: Python dependencies - README.md: Usage and deployment instructions
1 parent 402bf48 commit b9f4bce

File tree

3 files changed

+833
-0
lines changed

3 files changed

+833
-0
lines changed

examples/gradio-host/README.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# MCP Apps Gradio Host
2+
3+
A Python/Gradio host for MCP Apps that can be deployed on Hugging Face Spaces.
4+
5+
## Overview
6+
7+
This host demonstrates how to integrate MCP Apps (interactive tool widgets) into a Gradio application. It provides:
8+
9+
- **Server Connection**: Connect to MCP servers via HTTP
10+
- **Tool Discovery**: Browse available tools and their schemas
11+
- **Tool Execution**: Call tools with custom arguments
12+
- **Interactive Widgets**: Display MCP App UIs in sandboxed iframes
13+
14+
## Architecture
15+
16+
```
17+
┌─────────────────────────────────────────────────────────────┐
18+
│ Python Backend (Gradio + MCP SDK) │
19+
│ - Connects to MCP servers │
20+
│ - Lists tools and resources │
21+
│ - Executes tool calls │
22+
│ - Fetches UI resources │
23+
└─────────────────────────────────────────────────────────────┘
24+
25+
26+
┌─────────────────────────────────────────────────────────────┐
27+
│ Gradio Frontend │
28+
│ ┌─────────────────────────────────────────────────────────┐ │
29+
│ │ JavaScript Bridge (embedded in gr.HTML) │ │
30+
│ │ - Handles JSON-RPC protocol │ │
31+
│ │ - Manages postMessage communication │ │
32+
│ └─────────────────────────────────────────────────────────┘ │
33+
│ ┌─────────────────────────────────────────────────────────┐ │
34+
│ │ Sandbox Iframe (outer) │ │
35+
│ │ ┌─────────────────────────────────────────────────────┐│ │
36+
│ │ │ Guest UI Iframe (inner) - MCP App ││ │
37+
│ │ └─────────────────────────────────────────────────────┘│ │
38+
│ └─────────────────────────────────────────────────────────┘ │
39+
└─────────────────────────────────────────────────────────────┘
40+
```
41+
42+
## Local Development
43+
44+
### Prerequisites
45+
46+
- Python 3.10+
47+
- An MCP server to connect to (e.g., the QR Server example)
48+
49+
### Setup
50+
51+
```bash
52+
# Navigate to this directory
53+
cd examples/gradio-host
54+
55+
# Create virtual environment
56+
python -m venv venv
57+
source venv/bin/activate # or `venv\Scripts\activate` on Windows
58+
59+
# Install dependencies
60+
pip install -r requirements.txt
61+
62+
# Run the app
63+
python app.py
64+
```
65+
66+
The app will be available at http://localhost:7860
67+
68+
### Testing with QR Server
69+
70+
1. In a separate terminal, start the QR Server:
71+
```bash
72+
cd ../qr-server
73+
pip install -r requirements.txt
74+
python server.py
75+
```
76+
77+
2. In the Gradio host:
78+
- Connect to `http://localhost:3108`
79+
- Select the `generate_qr` tool
80+
- Enter arguments like: `{"text": "Hello World!"}`
81+
- Click "Execute Tool"
82+
- See the interactive QR code widget!
83+
84+
## Deploy to Hugging Face Spaces
85+
86+
### Option 1: Create a new Space
87+
88+
1. Go to [huggingface.co/spaces](https://huggingface.co/spaces)
89+
2. Click "Create new Space"
90+
3. Choose "Gradio" as the SDK
91+
4. Upload these files:
92+
- `app.py`
93+
- `requirements.txt`
94+
95+
### Option 2: Clone and push
96+
97+
```bash
98+
# Clone your space
99+
git clone https://huggingface.co/spaces/YOUR_USERNAME/YOUR_SPACE
100+
101+
# Copy the files
102+
cp app.py requirements.txt YOUR_SPACE/
103+
104+
# Push
105+
cd YOUR_SPACE
106+
git add .
107+
git commit -m "Add MCP Apps Gradio Host"
108+
git push
109+
```
110+
111+
### Space Configuration
112+
113+
Create a `README.md` in your Space with this YAML header:
114+
115+
```yaml
116+
---
117+
title: MCP Apps Host
118+
emoji: 🔌
119+
colorFrom: blue
120+
colorTo: purple
121+
sdk: gradio
122+
sdk_version: 4.44.1
123+
app_file: app.py
124+
pinned: false
125+
---
126+
```
127+
128+
## Connecting to External MCP Servers
129+
130+
When deployed on HF Spaces, you'll need to connect to publicly accessible MCP servers. The server must:
131+
132+
1. Support HTTP/Streamable HTTP transport
133+
2. Have CORS enabled for cross-origin requests
134+
3. Be accessible from the internet
135+
136+
Example server configuration for public access:
137+
138+
```python
139+
from starlette.middleware.cors import CORSMiddleware
140+
141+
app = mcp.streamable_http_app()
142+
app.add_middleware(
143+
CORSMiddleware,
144+
allow_origins=["*"], # Or specify your HF Space URL
145+
allow_methods=["*"],
146+
allow_headers=["*"],
147+
)
148+
```
149+
150+
## How It Works
151+
152+
### MCP Apps Protocol
153+
154+
MCP Apps extend the Model Context Protocol with interactive UI capabilities:
155+
156+
1. **Tool Metadata**: Tools can specify a `ui/resourceUri` in their metadata
157+
2. **UI Resources**: HTML resources with MIME type `text/html;profile=mcp-app`
158+
3. **JSON-RPC Communication**: Apps communicate with hosts via postMessage
159+
160+
### Security
161+
162+
The host uses a double-iframe sandbox architecture:
163+
164+
- **Outer iframe**: Sandbox proxy that relays messages
165+
- **Inner iframe**: Guest UI with Content Security Policy
166+
167+
CSP is injected based on the resource's `_meta.ui.csp` configuration.
168+
169+
## Limitations
170+
171+
- **Connection Persistence**: Currently reconnects for each tool call (stateless)
172+
- **Server-side Tools**: App-to-server tool calls are not yet fully implemented
173+
- **Streaming**: Partial tool input streaming not yet supported
174+
175+
## License
176+
177+
MIT - See the main repository license.

0 commit comments

Comments
 (0)