diff --git a/docs/content/docs/1.getting-started/7.ai/1.mcp.md b/docs/content/docs/1.getting-started/7.ai/1.mcp.md index de063f23c8..23d9f6c222 100644 --- a/docs/content/docs/1.getting-started/7.ai/1.mcp.md +++ b/docs/content/docs/1.getting-started/7.ai/1.mcp.md @@ -54,6 +54,14 @@ The Nuxt UI MCP server provides the following tools organized by category: - **`get_migration_guide`**: Retrieves version-specific migration guides and upgrade instructions +### Assistant Tools + +- **`ask_nuxt_ui_agent`**: Ask the Nuxt UI assistant for a concise direct answer (returns only the final content, no intermediate steps). + +::note{icon="i-lucide-info"} +Disabled when using the Agent from the Nuxt UI website. +:: + ## Available Prompts The Nuxt UI MCP server provides guided prompts for common workflows: diff --git a/docs/server/api/search.ts b/docs/server/api/search.ts index f7860f4211..ab4607c792 100644 --- a/docs/server/api/search.ts +++ b/docs/server/api/search.ts @@ -1,10 +1,10 @@ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js' -import { streamText, convertToModelMessages, stepCountIs } from 'ai' +import { streamText, convertToModelMessages, stepCountIs, generateText } from 'ai' import { experimental_createMCPClient } from '@ai-sdk/mcp' import { gateway } from '@ai-sdk/gateway' export default defineEventHandler(async (event) => { - const { messages } = await readBody(event) + const { messages, stream = true } = await readBody(event) const httpTransport = new StreamableHTTPClientTransport( new URL(import.meta.dev ? 'http://localhost:3000/mcp' : 'https://ui.nuxt.com/mcp') @@ -14,9 +14,12 @@ export default defineEventHandler(async (event) => { }) const tools = await httpClient.tools() - return streamText({ + // Remove the ask_nuxt_ui_agent tool to avoid infinite loops + delete tools['ask_nuxt_ui_agent'] + + const options = { model: gateway('anthropic/claude-sonnet-4.5'), - maxOutputTokens: 10000, + maxOutputTokens: 10_000, system: `You are a helpful assistant for Nuxt UI, a UI library for Nuxt and Vue. Use your knowledge base tools to search for relevant information before answering questions. Guidelines: @@ -40,7 +43,23 @@ Guidelines: - Format responses in a conversational way, not as documentation sections. `, messages: convertToModelMessages(messages), - stopWhen: stepCountIs(6), + stopWhen: stepCountIs(6) + } + + // If not streaming, it's called from the MCP route as a tool. + if (stream === false) { + const { text } = await generateText({ + ...options, + tools + }) + + await httpClient.close() + + return text + } + + return streamText({ + ...options, tools, onFinish: async () => { await httpClient.close() diff --git a/docs/server/routes/mcp.ts b/docs/server/routes/mcp.ts index dfc509195f..e6ddd1e972 100644 --- a/docs/server/routes/mcp.ts +++ b/docs/server/routes/mcp.ts @@ -5,6 +5,7 @@ import { z } from 'zod/v3' import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js' import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js' +import type { UIMessage } from 'ai' function createServer() { const server = new McpServer({ @@ -413,6 +414,36 @@ function createServer() { } ) + server.registerTool( + 'ask_nuxt_ui_agent', + { + title: 'Ask Nuxt UI Agent', + description: 'Asks the Nuxt UI agent a question', + inputSchema: { + // @ts-expect-error - need to wait for support for zod 4, this works correctly just a type mismatch from zod 3 to zod 4 (https://github.com/modelcontextprotocol/typescript-sdk/pull/869) + query: z.string().describe('The question to ask the agent') + } + }, + async (params: { query: string }) => { + const result = await $fetch('/api/search', { + method: 'POST', + timeout: 60_000, + body: { + stream: false, + messages: [{ + role: 'user', + parts: [{ type: 'text', text: params.query }] + }] satisfies Array> } + }) + + console.log(result) + + return { + content: [{ type: 'text' as const, text: result }] + } + } + ) + return server }