Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/content/docs/1.getting-started/7.ai/1.mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
29 changes: 24 additions & 5 deletions docs/server/api/search.ts
Original file line number Diff line number Diff line change
@@ -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')
Expand All @@ -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:
Expand All @@ -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()
Expand Down
31 changes: 31 additions & 0 deletions docs/server/routes/mcp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down Expand Up @@ -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<string>('/api/search', {
method: 'POST',
timeout: 60_000,
body: {
stream: false,
messages: [{
role: 'user',
parts: [{ type: 'text', text: params.query }]
}] satisfies Array<Omit<UIMessage, 'id'>> }
})

console.log(result)

return {
content: [{ type: 'text' as const, text: result }]
}
}
)

return server
}

Expand Down
Loading