From 333aaddff58fcdef100c6eb88d8528ff55a427ad Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Fri, 3 Apr 2026 10:22:33 -0400 Subject: [PATCH] fix: remove CSP from tool metadata, keep on resource only (#3754) --- src/fastmcp/apps/app.py | 23 ++++--------------- .../local_provider/decorators/tools.py | 9 +------- tests/test_fastmcp_app.py | 6 ++--- 3 files changed, 8 insertions(+), 30 deletions(-) diff --git a/src/fastmcp/apps/app.py b/src/fastmcp/apps/app.py index f4fed7e15..b800ff5a3 100644 --- a/src/fastmcp/apps/app.py +++ b/src/fastmcp/apps/app.py @@ -306,25 +306,10 @@ class FastMCPApp(Provider): _ensure_prefab_renderer, ) - try: - from prefab_ui.renderer import get_renderer_csp - - from fastmcp.apps.config import ResourceCSP - - csp = get_renderer_csp() - app_config = AppConfig( - resource_uri=PREFAB_RENDERER_URI, - visibility=["model"], - csp=ResourceCSP( - resource_domains=csp.get("resource_domains"), - connect_domains=csp.get("connect_domains"), - ), - ) - except ImportError: - app_config = AppConfig( - resource_uri=PREFAB_RENDERER_URI, - visibility=["model"], - ) + app_config = AppConfig( + resource_uri=PREFAB_RENDERER_URI, + visibility=["model"], + ) meta: dict[str, Any] = { "ui": app_config_to_meta_dict(app_config), diff --git a/src/fastmcp/server/providers/local_provider/decorators/tools.py b/src/fastmcp/server/providers/local_provider/decorators/tools.py index e79cc2c65..c3dfd2fdd 100644 --- a/src/fastmcp/server/providers/local_provider/decorators/tools.py +++ b/src/fastmcp/server/providers/local_provider/decorators/tools.py @@ -108,17 +108,10 @@ def _ensure_prefab_renderer(provider: LocalProvider) -> None: def _expand_prefab_ui_meta(tool: Tool) -> None: """Expand meta["ui"] = True into the full AppConfig dict for a prefab tool.""" - from prefab_ui.renderer import get_renderer_csp + from fastmcp.apps.config import AppConfig, app_config_to_meta_dict - from fastmcp.apps.config import AppConfig, ResourceCSP, app_config_to_meta_dict - - csp = get_renderer_csp() app_config = AppConfig( resource_uri=PREFAB_RENDERER_URI, - csp=ResourceCSP( - resource_domains=csp.get("resource_domains"), - connect_domains=csp.get("connect_domains"), - ), ) meta = dict(tool.meta) if tool.meta else {} meta["ui"] = app_config_to_meta_dict(app_config) diff --git a/tests/test_fastmcp_app.py b/tests/test_fastmcp_app.py index 8a49d659f..068f98024 100644 --- a/tests/test_fastmcp_app.py +++ b/tests/test_fastmcp_app.py @@ -246,7 +246,8 @@ class TestAppUI: assert meta is not None assert meta["ui"]["resourceUri"] == "ui://prefab/renderer.html" - async def test_ui_has_csp(self): + async def test_ui_tool_has_no_csp(self): + """CSP belongs on the UI resource, not the tool (per MCP Apps spec).""" app = FastMCPApp("test") @app.ui() @@ -256,8 +257,7 @@ class TestAppUI: tools = await app._list_tools() meta = tools[0].meta assert meta is not None - csp = meta["ui"].get("csp") - assert csp is not None + assert "csp" not in meta["ui"] async def test_ui_with_title_and_description(self): app = FastMCPApp("test")