一键导入
ra-mcp-apps
MCP Apps guide: FastMCP 3.4+ server, Svelte 5 view, tool visibility, polling, sizing, fullscreen, view persistence. Use for any MCP App/UI work.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
MCP Apps guide: FastMCP 3.4+ server, Svelte 5 view, tool visibility, polling, sizing, fullscreen, view persistence. Use for any MCP App/UI work.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Scaffold a new MCP workspace package under packages/. Covers directory structure, pyproject.toml, tools.py, server.py, tool registration, formatter, __init__.py, tests, root server wiring, and uv sync. Use when: add new MCP package, new workspace, new tool server, scaffold package, add module.
This skill should be used when the user asks to "add an app to my MCP server", "add UI to my MCP server", "add a view to my MCP tool", "enrich MCP tools with UI", "add interactive UI to existing server", "add MCP Apps to my server", or needs to add interactive UI capabilities to an existing MCP server that already has tools. Provides guidance for analyzing existing tools and adding MCP Apps UI resources.
This skill should be used when the user asks to "add MCP App support to my web app", "turn my web app into a hybrid MCP App", "make my web page work as an MCP App too", "wrap my existing UI as an MCP App", "convert iframe embed to MCP App", "turn my SPA into an MCP App", or needs to add MCP App support to an existing web application while keeping it working standalone. Provides guidance for analyzing existing web apps and creating a hybrid web + MCP App with server-side tool and resource registration.
Python design patterns and anti-patterns. Use when designing new components, refactoring, reviewing code for common mistakes, choosing abstractions, or evaluating pull requests for structural issues like tight coupling, leaking internal types, or error handling problems.
Modern Python type safety with type hints, generics, protocols, and strict type checking using ty and ruff. Use when adding type annotations, implementing generic classes, defining structural interfaces, configuring ty/ruff, or writing type-safe Python 3.13+/3.14+ code. Triggers on mentions of type hints, typing, TypeVar, Protocol, overload, TypeIs, Pydantic models, ty check, ruff type rules, or any static type analysis in Python.
Write and evaluate effective Python tests using pytest. Use when writing tests, reviewing test code, debugging test failures, or improving test coverage. Covers test design, fixtures, parameterization, mocking, async testing, and CI integration.
| name | ra-mcp-apps |
| description | MCP Apps guide: FastMCP 3.4+ server, Svelte 5 view, tool visibility, polling, sizing, fullscreen, view persistence. Use for any MCP App/UI work. |
Server (FastMCP) ↔ Host (Claude/ChatGPT) ↔ View (sandboxed iframe). The View and Server never talk directly.
| Field | LLM sees? | View sees? | Use for |
|---|---|---|---|
content | Yes | Yes | Short text summary for model context |
structuredContent | No* | Yes | Rich data for UI rendering |
_meta | No | Yes | viewUUID, timestamps, metadata |
*ChatGPT exposes structuredContent to both.
| Visibility | LLM? | View? | Use case |
|---|---|---|---|
["model", "app"] (default) | Yes | Yes | General tools |
["model"] | Yes | No | LLM-only triggers |
["app"] | No | Yes | Pagination, refresh, polling, dangerous actions |
from fastmcp import FastMCP, Context
from fastmcp.apps import AppConfig, ResourceCSP, UI_EXTENSION_ID
from fastmcp.tools import ToolResult
from mcp import types
mcp = FastMCP("My App")
RESOURCE_URI = "ui://my-app/view.html"
# Tool with UI — creates an iframe
@mcp.tool(app=AppConfig(resource_uri=RESOURCE_URI))
async def show_data(query: str, ctx: Context) -> ToolResult:
has_ui = ctx.client_supports_extension(UI_EXTENSION_ID)
return ToolResult(
content=[types.TextContent(type="text", text="Summary for LLM")],
structured_content={"data": [...], "query": query},
)
# App-only tool — View calls this, LLM never sees it
@mcp.tool(app=AppConfig(resource_uri=RESOURCE_URI, visibility=["app"]))
async def load_page(page: int) -> ToolResult: ...
# Resource — serves the bundled HTML
@mcp.resource(uri=RESOURCE_URI)
def get_ui() -> str:
return Path("dist/mcp-app.html").read_text()
<script lang="ts">
import { onMount } from "svelte";
import { App, applyDocumentTheme, applyHostStyleVariables, applyHostFonts, type McpUiHostContext } from "@modelcontextprotocol/ext-apps";
let app = $state<App | null>(null);
let hostContext = $state<McpUiHostContext | undefined>();
let data = $state.raw<MyData | null>(null);
$effect(() => {
if (hostContext?.theme) applyDocumentTheme(hostContext.theme);
if (hostContext?.styles?.variables) applyHostStyleVariables(hostContext.styles.variables);
if (hostContext?.styles?.css?.fonts) applyHostFonts(hostContext.styles.css.fonts);
});
onMount(async () => {
const instance = new App(
{ name: "My App", version: "1.0.0" },
{ availableDisplayModes: ["inline", "fullscreen"] },
{ autoResize: false }, // Required for flexible-height content — see patterns.md
);
instance.ontoolresult = (result) => { data = result.structuredContent; };
instance.onhostcontextchanged = (ctx) => { hostContext = { ...hostContext, ...ctx }; };
instance.onteardown = async () => { /* cleanup */ return {}; };
await instance.connect();
app = instance;
hostContext = instance.getHostContext();
});
</script>
| Question | Answer |
|---|---|
| What does the LLM need? | content |
| What does the UI need? | structuredContent |
| LLM triggers this? | visibility: ["model"] or default |
| UI-only action? | visibility: ["app"] |
| Data >100KB? | Chunked app-only tool — see patterns.md |
| External APIs? | Declare in ResourceCSP — see csp-cors.md |
| Fullscreen? | availableDisplayModes: ["inline", "fullscreen"] |
| View should persist across LLM tool calls? | Brick Builder pattern — see patterns.md |
| Multi-user server? | Per-view state with MemoryStore — see patterns.md |
resourceUri = new iframe. Never put AppConfig(resource_uri=...) on update tools.autoResize: false required for flexible-height content to prevent infinite resize loops.onteardown — always implement to stop polling and clean up.resource_domains.asyncio.gather for parallel fetches — sequential await calls wait for each other.