Skip to main content
An Artifact lets your Cap render a rich, interactive UI inside the Nuwa Client via an iframe. Use it to visualize results, collect structured input, or orchestrate multi-step workflows. To set the Artifact UI for your Cap, set a public and iframe-compatible URL:
cap
core: {
  artifact: { srcUrl: 'https://your-cap-ui.example.com' }
}

Expose MCP tools from your Artifact UI

You can expose MCP tools from your Artifact UI to allow the AI to call into your UI. The overall building process is the same as building an MCP server, except that this time you’re building an MCP server in the frontend. @nuwa-ai/ui-kit uses a customized MCP transport PostMessageMCPTransport, which allows you to expose MCP tools from your Artifact UI.
hooks/useArtifactMCP.ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { useNuwaMCP } from '@nuwa-ai/ui-kit';
import { z } from 'zod';

export const useArtifactMCP = () => {
  const server = new McpServer({ name: 'my-cap-ui', version: '1.0.0' });

  server.registerTool(
    'update_content',
    {
      title: 'Update UI Content',
      description: 'Replace visible content in the iframe',
      inputSchema: { content: z.string().describe('new content') },
    },
    ({ content }) => {
      // your UI state update here
      return { content: [{ type: 'text', text: 'OK' }] };
    },
  );

  useNuwaMCP(server);
}

What does useNuwaMCP do?

Building MCP in the frontend can be a weird experience as the MCP server is usually not a React component. You have to handle mount and unmount, as well as the possibility of multiple instances of the same MCP server. The useNuwaMCP hook is a React hook that you can use to stablized the MCP instance. It will automatically handle the mount and unmount, as well as using refs to ensure there’s only one active MCP server at a time. It also handles the transport connection to the Nuwa Client.

Call Nuwa Client in MCP Tool execution

You can also call the Nuwa Client functions in the MCP tool execution.
hooks/useArtifactMCP.ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { useNuwaMCP } from '@nuwa-ai/ui-kit';
import { z } from 'zod';

export const useArtifactMCP = (nuwaClient: NuwaClient) => {
  const server = new McpServer({ name: 'my-cap-ui', version: '1.0.0' });

  server.registerTool(
    'generate_ai_content',
    {
      title: 'Generate AI Content',
      description: 'Stream AI-generated content',
      prompt: z.string().describe("Prompt for AI to generate content"),
    },
    async ({ prompt }) => {
      const stream = await nuwaClient.createAIStream({ prompt })
      const { result } = await stream.execute({
        onChunk: (chunk) => {
          // update UI with the chunk
        },
        onError: (error) => {
          // handle error
        },
      });
      return { content: [{ type: 'text', text: result }] };
    },
  );

  useNuwaMCP(server);
}

See Also