From 71e127d0c2bb4f6de25445338926cdf9bf24fe3b Mon Sep 17 00:00:00 2001 From: Eric Gustin Date: Thu, 22 Oct 2026 12:53:11 -0700 Subject: [PATCH 1/2] docs: explain MCP Apps authoring and Arcade Deploy --- content/docs/build/arcade-deploy.mdx | 2 + .../tool-basics/build-mcp-server.mdx | 1 + .../create-tools/tool-basics/mcp-apps.mdx | 182 ++++++++++++++++++ .../build/create-tools/tool-basics/meta.json | 3 +- .../docs/references/mcp/python/resources.mdx | 4 + 5 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 content/docs/build/create-tools/tool-basics/mcp-apps.mdx diff --git a/content/docs/build/arcade-deploy.mdx b/content/docs/build/arcade-deploy.mdx index f8546e42b..d33719100 100644 --- a/content/docs/build/arcade-deploy.mdx +++ b/content/docs/build/arcade-deploy.mdx @@ -13,6 +13,8 @@ Running your MCP servers locally is very convenient during development and testi Arcade Deploy hosts *your* MCP server, either on Arcade Cloud or in a self-hosted Arcade installation on your own Kubernetes cluster. It's a feature for serving tools, not a way to deploy the Arcade platform. For a full platform deployment, see the [marketplace guides](/en/operate/deploy) or [self-host with Helm](/en/operate/deploy/helm). To turn on Arcade Deploy in a self-hosted installation, see [Arcade Deploy on your own cluster](/en/operate/deploy/helm-arcade-deploy). +To publish a tool with an HTML UI inside an MCP client, [add an MCP App](/en/build/create-tools/tool-basics/mcp-apps). Arcade Deploy publishes the tool and the tool's UI resource together. + diff --git a/content/docs/build/create-tools/tool-basics/build-mcp-server.mdx b/content/docs/build/create-tools/tool-basics/build-mcp-server.mdx index 9d8c8e807..49b006545 100644 --- a/content/docs/build/create-tools/tool-basics/build-mcp-server.mdx +++ b/content/docs/build/create-tools/tool-basics/build-mcp-server.mdx @@ -339,6 +339,7 @@ That's it! Your MCP server is running and connected to your AI assistant. ### Next steps +- **Add an MCP App**: [show an HTML UI for a tool and call tools from the UI](/en/build/create-tools/tool-basics/mcp-apps) - **Create custom tools that use auth**: [Learn how to create tools with authorization](/en/build/create-tools/tool-basics/create-tool-auth) - **Create custom tools that use secrets**: [Learn how to create tools with secrets](/en/build/create-tools/tool-basics/create-tool-secrets) - **Learn the capabilities of the `Context` object**: [Understanding the Context object](/en/build/create-tools/tool-basics/runtime-data-access) diff --git a/content/docs/build/create-tools/tool-basics/mcp-apps.mdx b/content/docs/build/create-tools/tool-basics/mcp-apps.mdx new file mode 100644 index 000000000..1104a06b9 --- /dev/null +++ b/content/docs/build/create-tools/tool-basics/mcp-apps.mdx @@ -0,0 +1,182 @@ +--- +title: Add an MCP App to a tool +sidebarTitle: Add an MCP App +description: Publish an HTML UI with your MCP server, deploy the server to Arcade, and call tools from the UI. +--- + +For agent developers who build MCP servers, MCP Apps let you show an HTML UI inside an MCP client. A tool can show a chart, a result view, or an editor that calls the same tool again or another tool in the same gateway. This guide shows how to attach a UI to a tool and publish the UI with Arcade Deploy. + +## Prerequisites + +- An [Arcade MCP server](/en/build/create-tools/tool-basics/build-mcp-server). +- `arcade-mcp-server` version 1.32.1 or later and the [Arcade CLI](/en/references/arcade-cli). +- An Arcade account and project for [Arcade Deploy](/en/build/arcade-deploy). +- An MCP client that supports the MCP Apps extension. A client that only supports tool calls does not render the UI. + +## Start with the runnable example + +The [MCP Apps example server](https://github.com/ArcadeAI/arcade-mcp/tree/main/examples/mcp_servers/tools_with_mcp_apps) includes a greeting editor, tools that the editor calls, and a text resource. Run the example from its project directory: + +```bash +git clone https://github.com/ArcadeAI/arcade-mcp.git +cd arcade-mcp/examples/mcp_servers/tools_with_mcp_apps +uv sync --extra dev +uv run python src/tools_with_mcp_apps/server.py +``` + +The server runs over stdio. Connect an MCP Apps client to the server to test the UI locally. Opening `editor.html` in a browser does not test the host connection: the UI needs the MCP client's message bridge. + +The preview and uppercase tools need no third-party authorization. The Google profile tool is an optional, read-only example of authorization from an open App. + +## Attach an HTML resource to a tool + +Declare the UI with `resource` from the public `arcade_mcp_server` package. Keep the HTML file beside the Python module that declares the resource: + +```python title="src/tools_with_mcp_apps/ui.py" +from arcade_mcp_server import resource + + +@resource(file="editor.html", title="Greeting editor") +def editor() -> None: + """Edit a greeting and call tools through the connected MCP client.""" +``` + +The example's UI-linked tool imports the resource declaration and passes the declaration to `@tool(ui=...)`. The following excerpt omits the example's other tools: + +```python title="src/tools_with_mcp_apps/tools.py" +from typing import Annotated + +from arcade_mcp_server import tool + +from tools_with_mcp_apps.ui import editor + + +@tool(ui=editor) +def preview_greeting(name: Annotated[str, "The name to greet"]) -> str: + """Show a greeting editor.""" + return f"Hello, {name}!" +``` + +Load the package's tools in the server entrypoint: + +```python title="src/tools_with_mcp_apps/server.py" +from importlib.metadata import version + +from arcade_mcp_server import MCPApp + +import tools_with_mcp_apps + +app = MCPApp(name="tools_with_mcp_apps", version=version("tools_with_mcp_apps")) +app.add_tools_from_module(tools_with_mcp_apps) + +if __name__ == "__main__": + app.run() +``` + +Include `editor.html` in the Python package you deploy. The example's wheel configuration includes the HTML file in `src/tools_with_mcp_apps/`. + +The framework publishes the resource with the `ui://` scheme and the `text/html;profile=mcp-app` MIME type. The framework also sets the tool's `_meta.ui.resourceUri`. Do not construct that metadata by hand. Use the standalone `@resource` declaration for Arcade Deploy, rather than the native-MCP-only `@app.resource` API. + +The MCP client reads the linked resource and renders the HTML in a sandbox. Tool execution and UI loading are separate requests. Keep end-user data in tool results, not in the published HTML: the same HTML document serves different end-users. + +## Deploy and connect through a gateway + +From the example's directory containing `pyproject.toml`, run: + +```bash +uv run arcade login +uv run arcade deploy -e src/tools_with_mcp_apps/server.py +``` + +Before deploying a changed release, increase `project.version` in `pyproject.toml` and run `uv sync --extra dev`. When you change the HTML, also update the App's `appInfo.version` in `editor.html`. + +After deployment: + +1. [Create an MCP gateway](/en/operate/governance/mcp-gateways/create-via-dashboard) in the same project. +2. Select `ToolsWithMcpApps.PreviewGreeting` and `ToolsWithMcpApps.UppercaseGreeting`. Add `ToolsWithMcpApps.GoogleProfile` if you want to test authorization. +3. Connect your MCP Apps client to the gateway URL from the Dashboard. +4. Ask the client to call `ToolsWithMcpApps_PreviewGreeting` with `name` set to `Ada`. +5. Change the name in the editor and select **Uppercase greeting**. The editor calls the other tool and shows the updated greeting. + +You do not add the HTML as a separate server or select a resource in the Dashboard. The tool already points to the UI resource. The gateway gives the resource a unique address. Use the exact address returned by the gateway, rather than constructing an address from the toolkit name or version. + +For a self-hosted Arcade installation, use an Arcade Engine release and deployment runtime that support managed-server resources. Ask your platform operator to confirm that support. See [Arcade Deploy on your own cluster](/en/operate/deploy/helm-arcade-deploy) for the deployment setup. + +## Call another tool from the App + +App JavaScript sends tool calls through the MCP client's existing gateway connection. Do not put an Arcade API key or OAuth token in the HTML, or call the Arcade Engine API from the iframe to execute tools. + +In the example's `editor.html`, `request` handles the MCP Apps message bridge and `available` maps tool identities to the names returned by discovery. The cross-tool call uses: + +```javascript title="editor.html" +const name = available.get("ToolsWithMcpApps.UppercaseGreeting"); +const result = await request("tools/call", { + name, + arguments: { name: document.getElementById("name").value }, +}); +``` + +Call the exact discovered name. The greeting editor checks availability before enabling the editor and before each action. An App does not gain permission to call a tool because the App references the tool. + +### Check availability before the user starts editing + +An action's tool may be absent from the gateway or unavailable to the connected end-user. Hide the action or keep the action's button inactive before the end-user spends time editing inputs for an action that cannot run. + +The example first tries App-to-host `tools/list`, which is in the [draft MCP Apps specification](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx#standard-mcp-messages). The example reads every page and respects the tool's App visibility. + +If the host returns method-not-found, or tool recommendations replace the complete tool list, the example asks the host to read Arcade's availability resource: + +```text +arcade://gateway/tool-availability/v1?tool=ToolsWithMcpApps.PreviewGreeting&tool=ToolsWithMcpApps.UppercaseGreeting&request= +``` + +This temporary Arcade-specific fallback requires host support for server resource reads. It returns the exact MCP names of the requested tools available to the end-user in the gateway. Keep the native-first check and fallback when adapting the example. Treat a failed check as unknown availability, not as confirmation that a tool is absent. + +Test the missing-tool case with a second gateway that excludes `ToolsWithMcpApps.UppercaseGreeting`. The editor must not show the uppercase button. + +### Handle authorization without losing edits + +Availability does not mean that OAuth consent or required secrets are ready. Let the ordinary tool call check those requirements. Do not execute a tool to probe availability. + +The MCP host may handle URL elicitation during a call. If the host instead forwards an unresolved authorization requirement, the example shows an authorization prompt and keeps the edited inputs. After authorization, the end-user selects **Retry action**. Completing OAuth does not trigger another tool call from the App. + +For an initial tool call that has not executed, show the authorization prompt instead of an empty editor. The host must retry the original call after authorization. An error about a missing secret is not an OAuth authorization prompt. + +## Configure external assets and requests + +The bundled greeting editor uses inline JavaScript and CSS, with no direct network requests. If you add external scripts, styles, images, or fonts, declare the origins in the resource's `meta` argument. Direct API requests also need declared origins. Replace the existing resource declaration with a declaration such as: + +```python title="ui.py" +@resource( + file="editor.html", + meta={ + "ui": { + "csp": { + "resourceDomains": ["https://cdn.example.com"], + "connectDomains": ["https://api.example.com"], + } + } + }, +) +def editor() -> None: + """Show the greeting editor.""" +``` + +Use `resourceDomains` and `connectDomains`, not browser directive names such as `script-src` and `connect-src`. The MCP host reads `_meta.ui.csp` from the resource-read response. Putting the policy only on the tool does not configure the resource. + +For local assets, include each origin's scheme and port, such as `http://localhost:5173`. `localhost` and `127.0.0.1` are different origins. Remove development origins before deployment. The host's message bridge does not need a `connectDomains` entry. + +## Troubleshoot a missing UI + +| Symptom | Check | +| --- | --- | +| The tool returns text, but no UI appears | Use a client with MCP Apps support. Confirm that the tool definition includes `_meta.ui.resourceUri`. | +| The client reports resource-not-found | Read the exact linked URI from the current tool definition. Confirm that the deployed package includes the HTML file and uses the standalone `@resource` declaration. | +| The UI is blank | Check the host's browser console for blocked assets. Check `resourceDomains` and `connectDomains` on the resource. | +| An action is missing or inactive | Check tool availability for the connected end-user and gateway. A failed discovery request is not an authorization check. | + +## Next steps + +- Adapt the [complete example server and HTML](https://github.com/ArcadeAI/arcade-mcp/tree/main/examples/mcp_servers/tools_with_mcp_apps). +- [Add authorization to a tool](/en/build/create-tools/tool-basics/create-tool-auth). +- Read the [official MCP Apps documentation](https://apps.extensions.modelcontextprotocol.io/) for frontend SDK APIs and host requirements. diff --git a/content/docs/build/create-tools/tool-basics/meta.json b/content/docs/build/create-tools/tool-basics/meta.json index c8858a27e..dcef79e7c 100644 --- a/content/docs/build/create-tools/tool-basics/meta.json +++ b/content/docs/build/create-tools/tool-basics/meta.json @@ -9,6 +9,7 @@ "runtime-data-access", "call-tools-mcp", "organize-mcp-tools", - "add-tool-metadata" + "add-tool-metadata", + "mcp-apps" ] } diff --git a/content/docs/references/mcp/python/resources.mdx b/content/docs/references/mcp/python/resources.mdx index 775fa6d25..b3a54d16e 100644 --- a/content/docs/references/mcp/python/resources.mdx +++ b/content/docs/references/mcp/python/resources.mdx @@ -9,6 +9,10 @@ MCP resources expose data to clients through URI-addressable endpoints. `MCPApp` build-time methods to register static resources, file-backed resources, and dynamic resource handlers -- including URI templates with parameters. + +For MCP Apps published with Arcade Deploy, use the standalone `@resource` declaration in [Add an MCP App to a tool](/en/build/create-tools/tool-basics/mcp-apps). The `MCPApp` registration methods below serve resources over a native MCP connection. Those registrations do not publish resources through Arcade Deploy. + + ## Basic usage ```python From d69f8e976b765e1f989b56f34049d0e39306d0ed Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 22 Oct 2026 19:54:51 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=A4=96=20Regenerate=20LLMs.txt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/llms.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/llms.txt b/public/llms.txt index ac9cd1fe6..369c30a9b 100644 --- a/public/llms.txt +++ b/public/llms.txt @@ -1,4 +1,4 @@ - + # Arcade @@ -74,6 +74,7 @@ Arcade docs serve two audiences. Start with the path that matches your goal: ## Documentation - [About Arcade](https://docs.arcade.dev/en/get-started/about-arcade): Arcade is an enterprise-ready runtime platform that enables AI agents to securely take actions by handling authorization, executing tools reliably across business systems, and providing central governance. The documentation explains how Arcade solves three critical challenges: enforcing security through agent authorization and OAuth management, executing actions through 7,500+ agent-optimized tools, and governing agent lifecycles across organizations. It's designed for both agent developers who need to call tools and platform operators who deploy and govern Arcade for their organizations. +- [Add an MCP App to a tool](https://docs.arcade.dev/en/build/create-tools/tool-basics/mcp-apps): This guide teaches MCP server developers how to attach an HTML user interface to their tools and deploy them through Arcade. It covers declaring UI resources with Python decorators, packaging HTML files with your MCP server, and deploying to Arcade so that MCP clients can render interactive interfaces for tool execution. - [Add metadata to your tools](https://docs.arcade.dev/en/build/create-tools/tool-basics/add-tool-metadata): This documentation teaches you how to annotate MCP tools with ToolMetadata so that clients, policy engines, and tool-selection systems can understand what each tool does and how it behaves. You'll learn to classify tools by service domain, describe their behavior with operations and safety flags, and map those flags to MCP annotations that inform client decisions. - [Add user authorization to your MCP tools](https://docs.arcade.dev/en/build/create-tools/tool-basics/create-tool-auth): This documentation page teaches developers how to build MCP tools that require user authorization through OAuth, using Arcade's auth providers like Reddit to securely authenticate users before tool execution. It explains how auth providers work during execution, including the OAuth flow where users authorize actions and tokens are securely injected into the tool's context without exposing them to the LLM or client. The page provides step-by-step instructions for creating an MCP tool with authorization, including importing modules, setting up an MCP server, and defining tools with the `requires_auth` parameter. - [Adding Resource Server Auth to Your MCP Server](https://docs.arcade.dev/en/build/create-tools/secure-your-server/secure-your-mcp-server): This documentation page guides developers on securing HTTP MCP servers using OAuth 2.1 Resource Server authentication, enabling tool-level authorization and secrets for self-hosted deployments. It explains what Resource Server auth is, why it's needed to protect HTTP MCP servers, and provides prerequisites and learning outcomes for implementing token validation and supporting multiple authorization servers. The page offers two configuration approaches for adding OAuth 2.1 compliant front-door authentication to validate Bearer tokens on every request.