diff --git a/packages/@n8n/mcp-apps/README.md b/packages/@n8n/mcp-apps/README.md index c7744168461..b382ae34778 100644 --- a/packages/@n8n/mcp-apps/README.md +++ b/packages/@n8n/mcp-apps/README.md @@ -18,9 +18,11 @@ helpers used by `packages/cli` to register them as MCP resources and tools. the host context the MCP client provides at runtime. Today the package ships a single app, `workflow-preview`, which is rendered -after the `create_workflow_from_code` MCP tool returns and gives the user a -button to open the freshly created workflow in n8n. New apps can be added -alongside it (see [Adding a new app](#adding-a-new-app)). +after the `create_workflow_from_code` MCP tool returns. It loads the sanitized +workflow graph through the existing `get_workflow_details` MCP tool, renders the +existing n8n demo canvas in an iframe, and keeps a button to open the freshly +created workflow in n8n. New apps can be added alongside it (see +[Adding a new app](#adding-a-new-app)). ## Package layout @@ -33,7 +35,15 @@ src/ main.ts # mounts App with i18n index.html # entry HTML (built into dist/apps/.html) tokens.scss # design tokens / global styles - url.ts # defense-in-depth URL validation + types.ts # workflow preview data types + type-guards.ts # workflow preview data guards + composables/ + use-workflow-preview.ts # workflow preview state and host tool handling + utils/ + url.ts # defense-in-depth URL validation + components/ # reusable MCP app Vue components + workflow-preview/ # workflow-preview-specific reusable components + composables/ # reusable MCP host/runtime composables i18n/ # vue-i18n setup + host locale resolution locales/ # flat-key locale files (en.json, …) server/ # consumed by packages/cli @@ -42,6 +52,7 @@ src/ register-mcp-app-tool.ts resource-loader.ts # lazy reads built HTML from dist/apps index.ts # public entry: @n8n/mcp-apps/server + utils/ # framework-agnostic client helpers ``` `apps-manifest.ts` is the canonical registry of MCP apps. Both the Vite @@ -63,14 +74,25 @@ Each app: through `onhostcontextchanged` and reflects it on the document. - Reads the originating tool's `structuredContent` via `ontoolresult` to populate its own state. +- Calls `app.callServerTool(...)` when it needs fresh n8n data from the MCP + server. The workflow preview uses this to call `get_workflow_details` with + the created workflow ID. - Calls `app.openLink({ url })` to ask the host to navigate — never opens links itself. URL handling is locked down by `isAllowedWorkflowUrl` in -`src/apps/workflow-preview/url.ts`: only `http(s)://` URLs with a non-empty +`src/apps/workflow-preview/utils/url.ts`: only `http(s)://` URLs with a non-empty host are accepted, both when reading the tool result and right before calling `openLink`. This is defense in depth on top of the host's own validation. +The workflow preview iframe uses a server-provided `previewUrl` when available. +Otherwise it uses the existing n8n preview service because instance routes are +commonly blocked or unreachable from MCP hosts. The resource metadata declares +broad `frameDomains` for `http` and `https` so hosts that enforce MCP Apps CSP +can load instance-specific or configured preview URLs. The framed n8n server's +own frame policy still applies, so the app falls back to the open-workflow +button when the preview cannot load. + ## Internationalization Locale files live under `src/locales/` and use flat, namespaced keys diff --git a/packages/@n8n/mcp-apps/src/apps/workflow-preview/App.vue b/packages/@n8n/mcp-apps/src/apps/workflow-preview/App.vue index bbb84bfb6fa..ebcea2df7fd 100644 --- a/packages/@n8n/mcp-apps/src/apps/workflow-preview/App.vue +++ b/packages/@n8n/mcp-apps/src/apps/workflow-preview/App.vue @@ -1,140 +1,90 @@ diff --git a/packages/@n8n/mcp-apps/src/components/mcp-fallback-card.vue b/packages/@n8n/mcp-apps/src/components/mcp-fallback-card.vue new file mode 100644 index 00000000000..c1d9491d059 --- /dev/null +++ b/packages/@n8n/mcp-apps/src/components/mcp-fallback-card.vue @@ -0,0 +1,60 @@ + + + + + diff --git a/packages/@n8n/mcp-apps/src/components/open-in-n8n-button.vue b/packages/@n8n/mcp-apps/src/components/open-in-n8n-button.vue new file mode 100644 index 00000000000..d8656727efd --- /dev/null +++ b/packages/@n8n/mcp-apps/src/components/open-in-n8n-button.vue @@ -0,0 +1,31 @@ + + + diff --git a/packages/@n8n/mcp-apps/src/components/workflow-preview/workflow-preview-card.vue b/packages/@n8n/mcp-apps/src/components/workflow-preview/workflow-preview-card.vue new file mode 100644 index 00000000000..752ae659a20 --- /dev/null +++ b/packages/@n8n/mcp-apps/src/components/workflow-preview/workflow-preview-card.vue @@ -0,0 +1,221 @@ + + +