← Cycles
app.qpoint.io · c2

MCP Apps

activecreated 2026-03-05· last activity 2026-03-12

Add AI assistant UI to app.qpoint.io with shared Vue components usable as MCP Apps

Why

Qpoint has an MCP server. We want to add an in-app AI assistant and also expose interactive UI widgets to external AI clients (Claude, ChatGPT, VS Code Copilot, Goose) via the MCP Apps extension. Building shared Vue components lets us do both from one codebase.

Objective

Design and implement a shared component architecture where Vue components serve both as in-app chat UI widgets and as MCP App bundles. Ship an initial AI assistant chat interface in app.qpoint.io.

Scope

  • app/components/ — shared presentational components
  • app/server/api/chat.ts — AI SDK chat endpoint (future)
  • mcp-apps/ — MCP App entry points and build config (future)
  • MCP server tool definitions with _meta.ui references (future)

Research Findings

Approaches Evaluated

  1. Vercel AI SDK + Custom Vue UI (recommended for in-app chat)
    • AI SDK has first-class Nuxt support (@ai-sdk/vue, useChat)
    • Nuxt UI has pre-built chat components (ChatMessage, ChatMessages, ChatPrompt)
    • @ai-sdk/mcp bridges MCP tools to the AI SDK
    • Needs a /server/api/chat.ts route to proxy LLM calls
  2. CopilotKit — open-source copilot framework, Vue SDK newer, heavier dependency
  3. MCP Apps (for external AI clients) — official MCP extension, self-contained HTML in sandboxed iframes

MCP Apps Architecture

  • Tools declare UI via _meta.ui.resourceUri pointing to a ui:// resource
  • UI resources are self-contained HTML files (bundled JS/CSS)
  • Rendered in double-iframe sandbox by the host client
  • Communication via JSON-RPC over postMessage
  • @modelcontextprotocol/ext-apps provides the App SDK class
  • Framework-agnostic: official Vue starter template exists
  • Backward compatible: tools still return text for non-supporting clients

Shared Component Strategy

Vue Component (pure, prop-driven)
    |                    |
    v                    v
In-app wrapper       MCP App wrapper
(composables,        (App SDK,
 Pinia, Pulse API)    ontoolresult,
                      callServerTool)
  • Build Vue components as pure presentation — props in, events out
  • In Nuxt app: wrap with composables/stores as normal
  • For MCP Apps: thin Vite build using vite-plugin-singlefile to produce self-contained HTML
  • MCP App wrapper is ~20 lines of glue per component
  • Shared Tailwind config across both builds

Key Constraints

  • MCP Apps must be self-contained HTML (no SSR, no Nuxt runtime)
  • Shared components must avoid Nuxt-specific auto-imports (use explicit imports)
  • Need separate Vite build config for MCP App bundles
  • Double-iframe sandbox: no access to parent DOM, cookies, or storage

Qpoint Brand Style Guide