一键导入
castella-mcp
Enable AI agents to introspect and control Castella UIs via MCP. Create MCP servers, expose UI resources, handle MCP tools, and use semantic IDs.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Enable AI agents to introspect and control Castella UIs via MCP. Create MCP servers, expose UI resources, handle MCP tools, and use semantic IDs.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Build desktop, web, or terminal UIs with Castella. Create widgets, components, layouts, manage reactive state, handle events, and use the theme system.
Package Castella applications for distribution using ux, PyInstaller, or Nuitka. Create executables, macOS app bundles, and cross-compile for other platforms.
Connect to A2A protocol agents from Castella. Communicate with agents, display agent cards, send messages, handle responses, and stream results.
Render A2UI JSON as native Castella widgets. Parse A2UI messages, handle actions, progressive rendering, data binding, and connect to A2UI-enabled agents.
Build chat interfaces and agent management UIs with Castella. Create chat components, display tool calls, manage multiple agents, and build agent hubs.
| name | castella-mcp |
| description | Enable AI agents to introspect and control Castella UIs via MCP. Create MCP servers, expose UI resources, handle MCP tools, and use semantic IDs. |
MCP (Model Context Protocol) enables AI agents to introspect and control Castella UIs programmatically. This provides a standard protocol for AI-UI interaction.
When to use: "enable MCP for Castella", "MCP server", "semantic ID", "MCP resources", "MCP tools", "SSE transport", "CastellaMCPServer", "control UI with MCP"
Create an MCP-enabled Castella app:
from castella import App, Column, Button, Input, Text
from castella.frame import Frame
from castella.mcp import CastellaMCPServer
# Build UI with semantic IDs
ui = Column(
Text("Hello MCP!").semantic_id("greeting"),
Input("").semantic_id("name-input"),
Button("Submit").semantic_id("submit-btn"),
)
app = App(Frame("MCP Demo", 800, 600), ui)
# Create MCP server
mcp = CastellaMCPServer(app, name="my-castella-app")
mcp.run_in_background() # Run MCP in background thread
app.run() # Run UI on main thread
uv sync --extra mcp # MCP dependencies
Assign stable, human-readable identifiers to widgets:
Button("Submit").semantic_id("submit-btn")
Input("").semantic_id("email-input")
CheckBox(state).semantic_id("newsletter-checkbox")
Text("Status").semantic_id("status-text")
Auto-generated IDs (if not specified): button_0, input_1, etc.
submit-form-btn, not btn1user-name-inputemail-input, save-btnlogin-btn, search-inputRead-only data available to AI agents:
| URI | Description |
|---|---|
ui://tree | Complete UI tree structure |
ui://focus | Currently focused element |
ui://elements | All interactive elements |
ui://element/{id} | Specific element details |
a2ui://surfaces | A2UI surfaces (if A2UI enabled) |
{
"type": "tree",
"root": {
"id": "root",
"type": "Column",
"children": [
{"id": "greeting", "type": "Text", "value": "Hello MCP!"},
{"id": "name-input", "type": "Input", "value": "", "interactive": true},
{"id": "submit-btn", "type": "Button", "label": "Submit", "interactive": true}
]
}
}
Actions AI agents can perform:
| Tool | Description | Parameters |
|---|---|---|
click | Click/tap element | element_id |
type_text | Type into input | element_id, text, replace |
focus | Set focus | element_id |
scroll | Scroll container | element_id, direction, amount |
toggle | Toggle checkbox/switch | element_id |
select | Select in picker/tabs | element_id, value |
list_actionable | List interactive elements | - |
send_a2ui | Send A2UI message | message |
# Click a button
click(element_id="submit-btn")
# Type into input (replace existing text)
type_text(element_id="name-input", text="Alice", replace=True)
# Type into input (append)
type_text(element_id="name-input", text=" Smith", replace=False)
# Toggle checkbox
toggle(element_id="newsletter-checkbox")
# Select tab
select(element_id="main-tabs", value="settings")
# Scroll down
scroll(element_id="message-list", direction="down", amount=100)
For MCP clients that communicate via stdin/stdout:
mcp = CastellaMCPServer(app, name="my-app")
mcp.run_in_background() # Uses stdio transport
For HTTP-based MCP clients (Claude Desktop, web clients):
mcp = CastellaMCPServer(app, name="my-app")
mcp.run_sse_in_background(host="localhost", port=8765)
SSE endpoints:
GET /sse - SSE event streamPOST /message - Send MCP messagesGET /health - Health checkControl a Castella app via HTTP:
import json
import urllib.request
def call_tool(name: str, **kwargs) -> dict:
message = {
"type": "call_tool",
"params": {"name": name, "arguments": kwargs}
}
data = json.dumps(message).encode("utf-8")
req = urllib.request.Request(
"http://localhost:8765/message",
data=data,
headers={"Content-Type": "application/json"},
)
with urllib.request.urlopen(req) as response:
return json.loads(response.read())
# Type into input
call_tool("type_text", element_id="name-input", text="Alice", replace=True)
# Click button
call_tool("click", element_id="submit-btn")
# Toggle checkbox
call_tool("toggle", element_id="newsletter-checkbox")
# List all interactive elements
result = call_tool("list_actionable")
print(result)
Combine A2UI rendering with MCP control:
from castella.a2ui import A2UIRenderer, A2UIComponent
from castella.mcp import CastellaMCPServer
renderer = A2UIRenderer(on_action=on_action)
renderer.render_json(a2ui_json)
surface = renderer.get_surface("default")
app = App(Frame("A2UI + MCP", 800, 600), A2UIComponent(surface))
# MCP with A2UI renderer for bidirectional integration
mcp = CastellaMCPServer(app, a2ui_renderer=renderer)
mcp.run_sse_in_background(port=8766)
app.run()
A2UI component IDs automatically become MCP semantic IDs.
When A2UI renderer is provided, the send_a2ui tool becomes available:
send_a2ui(message={
"updateDataModel": {
"surfaceId": "default",
"data": {"/counter": 42}
}
})
from castella.mcp import CastellaMCPServer
mcp = CastellaMCPServer(
app=app, # Castella App instance
name="my-app", # MCP server name
version="1.0.0", # Version string
a2ui_renderer=None, # Optional A2UIRenderer
)
# Blocking methods
mcp.run() # Run stdio (blocks)
mcp.run_sse(host, port) # Run SSE (blocks)
# Background methods
mcp.run_in_background() # Run stdio in thread
mcp.run_sse_in_background(host, port) # Run SSE in thread
# Management
mcp.refresh_registry() # Refresh widget registry
mcp.stop() # Stop server
Information about a UI element:
element = {
"id": "submit-btn",
"type": "Button",
"label": "Submit",
"value": None,
"bounds": {"x": 10, "y": 100, "width": 80, "height": 40},
"interactive": True,
"focused": False,
}
mcp.refresh_registry()references/resources.md - Complete resource URI referencereferences/tools.md - Complete tool referencereferences/types.md - ElementInfo, UITreeNode typesscripts/ - Executable examples (mcp_basic.py, mcp_sse.py)