xj% dZddlmZddlmZmZddlmZmZm Z ddl m Z m Z ddl mZddlmZddlmZmZmZdd lmZdd lmZmZd Z d Z ed Z e dedefZGdde ZGdde ZGddeZ ddZ!ddZ"ddZ#y)aRMCP Apps extension (`io.modelcontextprotocol/ui`). MCP Apps lets a tool carry a reference to an interactive UI: the tool's `_meta.ui.resourceUri` points at a `ui://` resource (an HTML document served with the `text/html;profile=mcp-app` MIME type) that the host renders in a sandboxed iframe. See https://modelcontextprotocol.io/specification/draft/extensions/apps and the ext-apps spec for the wire format, and SEP-2133 for the extension framework. This is a self-contained, additive `Extension`: it contributes tools and resources and advertises the capability, but does not intercept any core method. A server opts in by passing an `Apps` instance to `MCPServer(extensions=[...])`. apps = Apps() @apps.tool(resource_uri="ui://clock/app.html", description="Current time") def get_time(ctx: Context) -> str: return datetime.now(timezone.utc).isoformat() apps.add_html_resource("ui://clock/app.html", CLOCK_HTML) mcp = MCPServer("clock", extensions=[apps]) Per SEP-2133, an extension MUST degrade gracefully: a UI-enabled tool should still return meaningful text for clients that did not negotiate Apps. Use `client_supports_apps(ctx)` to branch on the client's advertised support. (The SDK keeps Apps in-core under `mcp.server.apps` rather than a separate package; the TypeScript and C# SDKs ship it as a standalone package.) ) annotations)CallableSequence)AnyLiteralTypeVar) BaseModel ConfigDict)to_camel)ServerRequestContext) ExtensionResourceBinding ToolBinding)Context)Resource TextResourcezio.modelcontextprotocol/uiztext/html;profile=mcp-app)modelapp _CallableT.)boundc^eZdZUdZeedZdZded<dZ ded<dZ ded<dZ ded <y) ResourcePermissionszHIframe permissions a `ui://` resource requests (`_meta.ui.permissions`).Talias_generatorpopulate_by_nameNdict[str, Any] | Nonecamera microphone geolocationclipboard_write) __name__ __module__ __qualname____doc__r r model_configr__annotations__rrr c/mnt/ssd/data/Dropbox/adrian/sandbox/mcp-query/venv/lib/python3.12/site-packages/mcp/server/apps.pyrr7s=RhNL$(F !((,J%,)-K&--1O*1r(rc^eZdZUdZeedZdZded<dZ ded<dZ ded<dZ ded <y) ResourceCspzHContent-Security-Policy domains for a `ui://` resource (`_meta.ui.csp`).TrNzlist[str] | Noneconnect_domainsresource_domains frame_domainsbase_uri_domains) r!r"r#r$r r r%r,r&r-r.r/r'r(r)r+r+Bs?RhNL(,O%,)-&-&*M#*)-&-r(r+ceZdZdZeZd dZddd d dZdddddddd d dZddZ dd Z dd Z y)AppszThe MCP Apps extension: bind tools to `ui://` UI resources. Register UI-bound tools with `@apps.tool(resource_uri=...)` and their HTML with `add_html_resource(...)`, then pass the instance to `MCPServer(extensions=[apps])`. c g|_g|_yN)_tools _resourcesselfs r)__init__z Apps.__init__Ws57 13r(N) visibilitymetac trdvr tddi|t|d<dfd }|S)aDecorator registering a tool bound to a `ui://` resource. Stamps `_meta.ui.resourceUri` (and `_meta.ui.visibility` when given) on the tool. `tool_kwargs` are forwarded to `MCPServer.add_tool` (name, title, description, annotations, ...); pass `meta=` to merge extra `_meta` keys alongside the `ui` entry. Args: resource_uri: The `ui://` URI of the UI resource this tool renders. visibility: Where the tool is surfaced (`["model", "app"]`). meta: Additional `_meta` keys to merge with the `ui` entry. Raises: ValueError: If `resource_uri` does not use the `ui://` scheme, or `meta` carries a `"ui"` key (the decorator owns `_meta["ui"]`). uizWApps.tool() owns _meta['ui']; pass resource_uri=/visibility= instead of a 'ui' meta key resourceUrir9crt|ixsidi}jj|f|S)Nr<)fnr:kwargs)rr4append)r?bindingr: resource_urir7 tool_kwargsr<s r) decoratorzApps.tool..decoratorzs?!R.H$*".HtR.HQ\]G KK  6 7Ir()r?rreturnr)_require_ui_scheme ValueErrorlist)r7rCr9r:rDrEr<s`` `` @r)toolz Apps.tool[sS0 <( DDLvw w+\:  !#J/B|    r()nametitle descriptioncsp permissionsdomainprefers_borderc i} ||jdd| d<||jdd| d<||| d<| | | d<|jt||xs|||t| rd| ind| y) aRegister a `ui://` HTML resource served as `text/html;profile=mcp-app`. `csp`, `permissions`, `domain`, and `prefers_border` populate the resource's `_meta.ui` per the ext-apps spec. Args: uri: The `ui://` URI; a tool references it via `resource_uri`. html: The HTML document the host renders. Raises: ValueError: If `uri` does not use the `ui://` scheme. NT)by_alias exclude_nonerNrOrP prefersBorderr<)urirKrLrM mime_typer:text) model_dump add_resourcer APP_MIME_TYPE) r7rVhtmlrKrLrMrNrOrPrQr<s r)add_html_resourcezApps.add_html_resources2  ?4HBuI  " + 6 6SW 6 XB}   !BxL  %"0B   [S''#%dBZ4  r(c*t|jd|jvr|jdti}n2|j tk7rt dtd|j |jjt|y)u9Register a pre-built `ui://` resource. The escape hatch for resources `add_html_resource` cannot express (e.g. a `FileResource` serving HTML from disk). A resource without an explicit `mime_type` is served as `text/html;profile=mcp-app` — hosts will not render a `ui://` resource under any other MIME type, so an explicit mismatch is rejected. Raises: ValueError: If the resource URI does not use the `ui://` scheme, or its explicit `mime_type` is not `text/html;profile=mcp-app`. rW)updatez!MCP Apps resources are served as z, got )resourceN) rGrVmodel_fields_set model_copyr[rWrHr5rAr)r7r`s r)rZzApps.add_resources~ 8<<( h77 7**; 2N*OH   = 0@@QQWX`XjXjWmno o ABr(c,|jDchc]}|jj}}|jD]/\}}||vs t d|j j d|d|jDcgc]\}}| c}}Scc}wcc}}w)uVThe bound tools. Raises: ValueError: If a tool's `resource_uri` has no matching resource registered on this instance — a tool advertising a `_meta.ui.resourceUri` that 404s on `resources/read` is a misconfiguration, caught when the server consumes the extension. z Apps tool z binds resource_uri zW, but no such resource is registered; add it with add_html_resource() or add_resource())r5r`rVr4rHr?r!)r7rB registeredrJrV_s r)toolsz Apps.toolss;?//Jwg&&**J J ID#*$  !1!1 44HPWW  %)KK0q00K1s B ; Bc|jSr3)r5r6s r) resourceszApps.resourcess r()rFNone) rCstrr9zSequence[Visibility] | Noner:rrDrrFz"Callable[[_CallableT], _CallableT])rVrjr\rjrK str | NonerLrkrMrkrNzResourceCsp | NonerOzResourcePermissions | NonerPrkrQz bool | NonerFri)r`rrFri)rFzSequence[ToolBinding])rFzSequence[ResourceBinding]) r!r"r#r$ EXTENSION_ID identifierr8rJr]rZrfrhr'r(r)r1r1MsJ437&* $$0 $ $ $  $ ,$V  "&"&26!&*, , ,  ,  ,  ,  , 0, , $,  , \C(1$r(r1ct|}|r |jnd}|r|jtnd}|y|jd}t |t t zxrt|vS)aWhether the connected client negotiated MCP Apps support. Returns `True` only when the client advertised the extension AND listed the `text/html;profile=mcp-app` MIME type in its settings, so a UI-enabled tool can fall back to text-only output otherwise. NF mimeTypes)_client_capabilities extensionsgetrl isinstancerItupler[)ctx capabilitiesrqsettings mime_typess r)client_supports_appsrysa(,L,8((dJ/9z~~l+tHk*J j$, / OMZ4OOr(cft|tr |jS|jjSr3)rsrclient_capabilitiessession)rus r)rprps(#w&&& ;; * **r(cB|jdstd|y)Nzui://z-MCP Apps URIs must use the ui:// scheme, got ) startswithrH)rVs r)rGrGs& >>' "HPQQ #r(N)ru-Context[Any] | ServerRequestContext[Any, Any]rFbool)rurrFr)rVrjrFri)$r$ __future__rcollections.abcrrtypingrrrpydanticr r pydantic.alias_generatorsr mcp.server.contextr mcp.server.extensionr rrmcp.server.mcpserver.contextrmcp.server.mcpserver.resourcesrrrlr[ Visibilityrrr+r1ryrprGr'r(r)rs:#.((*.3HH0A+ E+ + ^ $ @ \#s(); < 2)2.).I9IX P + Rr(