Skip to content
Draft
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,4 @@ jobs:
- name: Build module
run: pnpm run build:module
- name: Publish
run: pnpx pkg-pr-new publish --compact --no-template --pnpm './packages/nuxt-mcp-toolkit'
run: pnpx pkg-pr-new publish --compact --no-template --pnpm './packages/nuxt-mcp-toolkit' './packages/nitro-mcp-toolkit'
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ dist

# Nuxt
.nuxt
.nitro
.output
.data
.vercel_build_output
Expand Down
91 changes: 79 additions & 12 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,31 @@ This is a pnpm monorepo managed with Turborepo:
```
nuxt-mcp-toolkit/
├── packages/
│ └── nuxt-mcp-toolkit/ # Main module (published as @nuxtjs/mcp-toolkit)
│ ├── nitro-mcp-toolkit/ # Standalone Nitro module (published as nitro-mcp-toolkit)
│ └── nuxt-mcp-toolkit/ # Nuxt wrapper module (published as @nuxtjs/mcp-toolkit)
├── apps/
│ ├── docs/ # Documentation site (mcp-toolkit.nuxt.dev)
│ └── playground/ # Development playground for testing
```

### Package Architecture

The MCP toolkit is split into two packages:

1. **nitro-mcp-toolkit**: Core MCP functionality as a Nitro module
- Pure server-side MCP implementation
- Works with any Nitro-based project
- Provides `defineMcpTool`, `defineMcpResource`, `defineMcpPrompt`, etc.
- Handles file discovery, virtual modules, and transport providers

2. **@nuxtjs/mcp-toolkit**: Nuxt wrapper with additional features
- Uses nitro-mcp-toolkit internally
- Adds Nuxt-specific features:
- `InstallButton` Vue component
- Nuxt DevTools integration
- Nuxt layers support for definition overrides
- Deep link generation for IDE installation

## Development Environment Setup

### Prerequisites
Expand Down Expand Up @@ -62,21 +81,55 @@ Run from the repository root:

## Project Structure

### Main Module (`packages/nuxt-mcp-toolkit/`)
### Nitro Module (`packages/nitro-mcp-toolkit/`)

The standalone Nitro module with core MCP functionality:

```
packages/nitro-mcp-toolkit/
├── src/
│ ├── module.ts # Nitro module entry point (defineMcpNitroModule)
│ ├── handler.ts # MCP HTTP handler and server creation
│ ├── config.ts # Configuration defaults
│ ├── types.ts # TypeScript type exports
│ ├── definitions/ # MCP definition helpers
│ │ ├── tools.ts # defineMcpTool, registerToolFromDefinition
│ │ ├── resources.ts # defineMcpResource, registerResourceFromDefinition
│ │ ├── prompts.ts # defineMcpPrompt, registerPromptFromDefinition
│ │ ├── handlers.ts # defineMcpHandler
│ │ ├── cache.ts # Caching utilities
│ │ ├── results.ts # textResult, jsonResult, errorResult helpers
│ │ └── utils.ts # Name/title enrichment
│ ├── loaders/ # File discovery (framework-agnostic)
│ │ ├── index.ts # loadAllDefinitions, loadTools, etc.
│ │ └── utils.ts # Pattern creation, template generation
│ └── providers/ # Transport providers
│ ├── types.ts # McpTransportHandler type
│ ├── node.ts # Node.js StreamableHTTP transport
│ └── cloudflare.ts # Cloudflare Workers transport
└── build.config.ts # Unbuild configuration
```

### Nuxt Module (`packages/nuxt-mcp-toolkit/`)

The Nuxt wrapper with additional integrations:

```
packages/nuxt-mcp-toolkit/
├── src/
│ ├── module.ts # Main module entry point
│ ├── module.ts # Nuxt module entry point (wrapper)
│ ├── utils/
│ │ └── ide.ts # IDE detection and deep links
│ └── runtime/
│ ├── components/ # Vue components (InstallButton)
│ └── server/
│ ├── mcp/
│ │ ├── definitions/ # Tool, resource, prompt definitions
│ │ ├── loaders/ # File discovery and loading
│ │ ├── validators/ # Zod validation logic
│ │ ├── definitions/ # Re-exported from core (with layers support)
│ │ ├── devtools/ # Nuxt DevTools integration
│ │ ├── providers/ # Transport providers
│ │ ├── handler.ts # MCP HTTP handler
│ │ └── utils.ts # Utility functions
│ │ ├── deeplink.ts # IDE installation deep links
│ │ └── badge-image.ts # SVG badge generation
│ └── types/ # TypeScript types
└── test/
├── *.test.ts # Test files
Expand Down Expand Up @@ -243,13 +296,27 @@ This module uses `@modelcontextprotocol/sdk` version 1.23.0+. When referencing S

## Key Files

### Nitro Module (`packages/nitro-mcp-toolkit/`)

| File | Description |
|------|-------------|
| `src/module.ts` | Nitro module entry point with `defineMcpNitroModule()` |
| `src/handler.ts` | MCP HTTP handler and server creation |
| `src/definitions/` | Tool, resource, prompt, handler definitions |
| `src/loaders/` | File discovery logic (framework-agnostic) |
| `src/providers/` | Transport providers (Node.js, Cloudflare) |
| `src/config.ts` | Default configuration |

### Nuxt Module (`packages/nuxt-mcp-toolkit/`)

| File | Description |
|------|-------------|
| `packages/nuxt-mcp-toolkit/src/module.ts` | Main module entry point |
| `packages/nuxt-mcp-toolkit/src/runtime/server/mcp/handler.ts` | MCP HTTP handler |
| `packages/nuxt-mcp-toolkit/src/runtime/server/mcp/definitions/` | Definition processors |
| `packages/nuxt-mcp-toolkit/src/runtime/server/mcp/loaders/` | File discovery logic |
| `packages/nuxt-mcp-toolkit/src/runtime/server/types/` | TypeScript type definitions |
| `src/module.ts` | Nuxt module entry point (wrapper) |
| `src/runtime/components/InstallButton.vue` | Vue component for IDE installation |
| `src/runtime/server/mcp/devtools/` | Nuxt DevTools integration |
| `src/runtime/server/mcp/deeplink.ts` | IDE deep link generation |
| `src/runtime/server/mcp/badge-image.ts` | SVG badge generation |
| `src/utils/ide.ts` | IDE detection utilities |

## Troubleshooting

Expand Down
17 changes: 17 additions & 0 deletions apps/nitro-playground/nitro.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { defineMcpNitroModule } from 'nitro-mcp-toolkit'

export default defineNitroConfig({
compatibilityDate: '2026-01-01',

modules: [
defineMcpNitroModule({
route: '/mcp',
name: 'nitro-mcp-playground',
version: '1.0.0',
}),
],

experimental: {
asyncContext: true,
},
})
18 changes: 18 additions & 0 deletions apps/nitro-playground/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "nitro-mcp-toolkit-playground",
"private": true,
"type": "module",
"scripts": {
"dev": "nitro dev",
"build": "nitro build",
"preview": "node .output/server/index.mjs"
},
"dependencies": {
"nitro-mcp-toolkit": "workspace:*"
},
"devDependencies": {
"nitropack": "^2.13.1",
"typescript": "~5.9.3",
"zod": "^4.3.6"
}
}
3 changes: 3 additions & 0 deletions apps/nitro-playground/routes/health.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default defineEventHandler(() => {
return { status: 'ok', timestamp: new Date().toISOString() }
})
10 changes: 10 additions & 0 deletions apps/nitro-playground/routes/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export default defineEventHandler(() => {
return {
name: 'Nitro MCP Toolkit Playground',
description: 'A standalone Nitro server with MCP support',
endpoints: {
mcp: '/mcp',
health: '/health',
},
}
})
32 changes: 32 additions & 0 deletions apps/nitro-playground/server/mcp/prompts/assistant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { defineMcpPrompt } from 'nitro-mcp-toolkit'
import { z } from 'zod'

export default defineMcpPrompt({
description: 'A helpful assistant prompt with customizable persona',
inputSchema: {
persona: z.enum(['friendly', 'professional', 'technical']).default('friendly').describe('The persona to use'),
context: z.string().optional().describe('Additional context for the assistant'),
},
handler: async ({ persona, context }) => {
const personas = {
friendly: 'You are a friendly and helpful assistant. Be warm and encouraging in your responses.',
professional: 'You are a professional assistant. Be concise, clear, and maintain a business-appropriate tone.',
technical: 'You are a technical expert. Provide detailed, accurate information with code examples when relevant.',
}

const systemMessage = personas[persona]
const contextMessage = context ? `\n\nAdditional context: ${context}` : ''

return {
messages: [
{
role: 'user',
content: {
type: 'text',
text: `${systemMessage}${contextMessage}`,
},
},
],
}
},
})
38 changes: 38 additions & 0 deletions apps/nitro-playground/server/mcp/prompts/code-review.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { defineMcpPrompt } from 'nitro-mcp-toolkit'
import { z } from 'zod'

export default defineMcpPrompt({
description: 'Generate a code review prompt',
inputSchema: {
language: z.string().describe('The programming language of the code'),
focus: z.enum(['security', 'performance', 'readability', 'all']).default('all').describe('What to focus on'),
},
handler: async ({ language, focus }) => {
const focusAreas = {
security: 'Focus primarily on security vulnerabilities, input validation, and potential exploits.',
performance: 'Focus primarily on performance optimizations, memory usage, and algorithmic efficiency.',
readability: 'Focus primarily on code readability, naming conventions, and documentation.',
all: 'Review all aspects including security, performance, readability, and best practices.',
}

return {
messages: [
{
role: 'user',
content: {
type: 'text',
text: `You are an expert ${language} code reviewer. ${focusAreas[focus]}

Please review the code that will be provided and give constructive feedback with specific suggestions for improvement.

Format your review with:
1. Overall assessment
2. Specific issues found (if any)
3. Suggestions for improvement
4. Positive aspects of the code`,
},
},
],
}
},
})
20 changes: 20 additions & 0 deletions apps/nitro-playground/server/mcp/resources/environment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { defineMcpResource } from 'nitro-mcp-toolkit'

export default defineMcpResource({
uri: 'nitro://server/environment',
description: 'Current environment information (safe subset)',
handler: async () => {
const safeEnv = {
NODE_ENV: process.env.NODE_ENV || 'development',
TZ: process.env.TZ || Intl.DateTimeFormat().resolvedOptions().timeZone,
}

return {
contents: [{
uri: 'nitro://server/environment',
mimeType: 'application/json',
text: JSON.stringify(safeEnv, null, 2),
}],
}
},
})
22 changes: 22 additions & 0 deletions apps/nitro-playground/server/mcp/resources/server-info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { defineMcpResource } from 'nitro-mcp-toolkit'

export default defineMcpResource({
uri: 'nitro://server/info',
description: 'Information about the Nitro server',
handler: async () => {
return {
contents: [{
uri: 'nitro://server/info',
mimeType: 'application/json',
text: JSON.stringify({
name: 'Nitro MCP Playground',
version: '1.0.0',
runtime: 'nitro',
nodeVersion: process.version,
platform: process.platform,
uptime: process.uptime(),
}, null, 2),
}],
}
},
})
39 changes: 39 additions & 0 deletions apps/nitro-playground/server/mcp/tools/calculate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { defineMcpTool, jsonResult } from 'nitro-mcp-toolkit'
import { z } from 'zod'

export default defineMcpTool({
description: 'Perform basic arithmetic calculations',
inputSchema: {
operation: z.enum(['add', 'subtract', 'multiply', 'divide']).describe('The operation to perform'),
a: z.number().describe('First number'),
b: z.number().describe('Second number'),
},
handler: async ({ operation, a, b }) => {
let result: number

switch (operation) {
case 'add':
result = a + b
break
case 'subtract':
result = a - b
break
case 'multiply':
result = a * b
break
case 'divide':
if (b === 0) {
return errorResult('Division by zero is not allowed')
}
result = a / b
break
}

return jsonResult({
operation,
a,
b,
result,
})
},
})
42 changes: 42 additions & 0 deletions apps/nitro-playground/server/mcp/tools/get-time.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { defineMcpTool, jsonResult } from 'nitro-mcp-toolkit'
import { z } from 'zod'

export default defineMcpTool({
description: 'Get the current time in various formats',
inputSchema: {
timezone: z.string().optional().describe('Timezone (e.g., "America/New_York", "Europe/Paris")'),
format: z.enum(['iso', 'unix', 'human']).default('iso').describe('Output format'),
},
handler: async ({ timezone, format }) => {
const now = new Date()

let timeString: string

switch (format) {
case 'unix':
timeString = Math.floor(now.getTime() / 1000).toString()
break
case 'human':
timeString = now.toLocaleString('en-US', {
timeZone: timezone || 'UTC',
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
})
break
case 'iso':
default:
timeString = now.toISOString()
}

return jsonResult({
format,
timezone: timezone || 'UTC',
time: timeString,
})
},
})
Loading
Loading