Prompts
What are Prompts?
Prompts are reusable message templates that can be used by AI assistants. They can include dynamic arguments and return pre-formatted messages.
Why Use Prompts?
MCP prompts offer several advantages over ad-hoc instructions:
Reusability
Standardization
Customization
IDE Integration
IDE Integration
MCP prompts integrate seamlessly with modern development environments. When your MCP server is connected, prompts become available directly in your IDE.
Using Prompts in Cursor / VS Code
- Type
/: In the chat, type/to see all available MCP prompts - Select a prompt: Choose from the list (e.g.,
local-mcp/setup-mcp-server) - Fill Arguments: For prompt templates, a dialog will appear to fill in the required arguments
Auto-Generated Name and Title
You can omit name and title - they will be automatically generated from the filename:
import { defineMcpPrompt } from '@nuxtjs/mcp-toolkit/server' // optional
export default defineMcpPrompt({
// name and title are auto-generated from filename:
// name: 'greeting'
// title: 'Greeting'
description: 'Generate a personalized greeting message',
handler: async () => {
// ...
},
})
The filename greeting.ts automatically becomes:
name:greeting(kebab-case)title:Greeting(title case)
You can still provide name or title explicitly to override the auto-generated values.
Simple Prompt (No Arguments)
Create a prompt without arguments:
import { defineMcpPrompt } from '@nuxtjs/mcp-toolkit/server' // optional
export default defineMcpPrompt({
name: 'greeting',
title: 'Greeting',
description: 'Generate a personalized greeting message',
handler: async () => {
const hour = new Date().getHours()
const timeOfDay = hour < 12 ? 'morning' : hour < 18 ? 'afternoon' : 'evening'
return {
messages: [{
role: 'user',
content: {
type: 'text',
text: `Good ${timeOfDay}! How can I help you today?`,
},
}],
}
},
})
Prompt with Arguments
Create a prompt that accepts arguments:
import { z } from 'zod'
import { defineMcpPrompt } from '@nuxtjs/mcp-toolkit/server' // optional
export default defineMcpPrompt({
name: 'summarize',
title: 'Text Summarizer',
description: 'Summarize any text content',
inputSchema: {
text: z.string().describe('The text to summarize'),
maxLength: z.string().optional().describe('Maximum length of summary in words'),
},
handler: async ({ text, maxLength }) => {
const words = text.split(/\s+/)
const maxWords = maxLength ? Number.parseInt(maxLength) : Math.ceil(words.length * 0.3)
const summary = words.slice(0, maxWords).join(' ')
return {
messages: [{
role: 'user',
content: {
type: 'text',
text: `Summary (${maxWords} words): ${summary}${words.length > maxWords ? '...' : ''}`,
},
}],
}
},
})
Prompt Structure
A prompt definition consists of:
import { defineMcpPrompt } from '@nuxtjs/mcp-toolkit/server' // optional
export default defineMcpPrompt({
name: 'prompt-name', // Unique identifier
handler: async () => { // Handler function
return { messages: [...] }
},
})
import { defineMcpPrompt } from '@nuxtjs/mcp-toolkit/server' // optional
export default defineMcpPrompt({
name: 'prompt-name',
title: 'Prompt Title', // Human-readable title
description: 'Description', // What the prompt does
inputSchema: { ... }, // Zod schema for arguments
handler: async (args) => { // Handler with arguments
return { messages: [...] }
},
})
Input Schema
Use Zod to define and validate prompt arguments:
import { z } from 'zod'
import { defineMcpPrompt } from '@nuxtjs/mcp-toolkit/server' // optional
export default defineMcpPrompt({
name: 'translate',
inputSchema: {
// Required string argument
text: z.string().describe('Text to translate'),
// Required enum argument
targetLanguage: z.enum(['en', 'fr', 'es', 'de']).describe('Target language'),
// Optional argument
sourceLanguage: z.string().optional().describe('Source language (auto-detect if not provided)'),
// Optional with default
formality: z.enum(['formal', 'informal']).default('formal'),
},
handler: async ({ text, targetLanguage, sourceLanguage, formality }) => {
// Implementation
},
})
Common Argument Types
| Zod Type | Example | Description |
|---|---|---|
z.string() | z.string().min(1) | String with validation |
z.enum() | z.enum(['a', 'b']) | Enumeration |
z.optional() | z.string().optional() | Optional field |
z.default() | z.string().default('value') | Field with default |
z.string() and convert to other types in your handler if needed.Handler Function
The handler receives validated arguments (if inputSchema is provided) and returns messages:
// Prompt without arguments
handler: async () => {
return {
messages: [{
role: 'user',
content: {
type: 'text',
text: 'Message text',
},
}],
}
}
// Prompt with arguments
handler: async (args, extra) => {
// args: Validated arguments matching inputSchema
// extra: Request handler extra information
return {
messages: [{
role: 'user',
content: {
type: 'text',
text: 'Message text',
},
}],
}
}
Message Roles
Prompts can return messages with different roles:
return {
messages: [{
role: 'user',
content: {
type: 'text',
text: 'User message with instructions',
},
}],
}
return {
messages: [{
role: 'assistant',
content: {
type: 'text',
text: 'Pre-filled assistant response',
},
}],
}
user and assistant roles. To provide context or instructions, include them in the user message text.Multiple Messages
Return multiple messages to create a conversation flow:
import { defineMcpPrompt } from '@nuxtjs/mcp-toolkit/server' // optional
export default defineMcpPrompt({
name: 'conversation-starter',
inputSchema: {
topic: z.string().describe('Conversation topic'),
},
handler: async ({ topic }) => {
return {
messages: [
{
role: 'user',
content: {
type: 'text',
text: `You are a helpful assistant. Let's discuss ${topic}.`,
},
},
{
role: 'assistant',
content: {
type: 'text',
text: `I'd be happy to discuss ${topic} with you.`,
},
},
],
}
},
})
Use Cases
Prompts are particularly useful for:
1. Setup and Onboarding
Help new developers or AI assistants understand how to work with your codebase:
import { defineMcpPrompt } from '@nuxtjs/mcp-toolkit/server' // optional
export default defineMcpPrompt({
description: 'Provide complete setup instructions for this project',
handler: async () => {
return {
messages: [{
role: 'user',
content: {
type: 'text',
text: `You are setting up this Nuxt project. Here's what you need to know:
1. Install dependencies: \`pnpm install\`
2. Start dev server: \`pnpm dev\`
3. Project structure follows Nuxt conventions
4. MCP tools are available in server/mcp/
Ask me what you'd like to build!`,
},
}],
}
},
})
2. Code Review Standards
Ensure consistent code review criteria:
import { z } from 'zod'
import { defineMcpPrompt } from '@nuxtjs/mcp-toolkit/server' // optional
export default defineMcpPrompt({
description: 'Apply team code review standards',
inputSchema: {
focus: z.enum(['security', 'performance', 'maintainability', 'all']).default('all'),
},
handler: async ({ focus }) => {
return {
messages: [
{
role: 'user',
content: {
type: 'text',
text: `You are a code reviewer following our team standards. Focus on: ${focus}.
Review the code I provide, checking for best practices and potential issues.`,
},
},
],
}
},
})
3. Documentation Generation
Standardize documentation format:
import { z } from 'zod'
import { defineMcpPrompt } from '@nuxtjs/mcp-toolkit/server' // optional
export default defineMcpPrompt({
description: 'Generate documentation in team format',
inputSchema: {
type: z.enum(['api', 'component', 'function']).describe('What to document'),
},
handler: async ({ type }) => {
const templates = {
api: 'Document this API endpoint with: endpoint, method, parameters, response format, and examples.',
component: 'Document this Vue component with: props, emits, slots, and usage examples.',
function: 'Document this function with: parameters, return value, and usage examples.',
}
return {
messages: [{
role: 'user',
content: {
type: 'text',
text: templates[type],
},
}],
}
},
})
4. Troubleshooting Workflows
Guide debugging for common issues:
import { z } from 'zod'
import { defineMcpPrompt } from '@nuxtjs/mcp-toolkit/server' // optional
export default defineMcpPrompt({
description: 'Help debug common issues',
inputSchema: {
area: z.enum(['api', 'auth', 'database', 'frontend']).describe('Area of the issue'),
},
handler: async ({ area }) => {
return {
messages: [{
role: 'user',
content: {
type: 'text',
text: `You are debugging a ${area} issue. Ask clarifying questions and suggest diagnostic steps.`,
},
}],
}
},
})
File Organization
Organize your prompts in the server/mcp/prompts/ directory:
server/
└── mcp/
└── prompts/
├── greeting.ts
├── summarize.ts
└── translate.ts
Each file should export a default prompt definition.
Type Safety
The module provides full TypeScript type inference:
// Argument types are inferred from inputSchema
handler: async ({ text, maxLength }) => {
// text is typed as string
// maxLength is typed as string | undefined
}
Best Practices
1. Design for AI Understanding
Write prompts that give the AI clear context and expectations:
// Good: Clear context and instructions
handler: async ({ code }) => ({
messages: [{
role: 'user',
content: {
type: 'text',
text: `You are a senior developer reviewing code for a Nuxt application.
Review this code for Vue 3 best practices:\n\n${code}`,
},
}],
})
// Less effective: Vague instructions
handler: async ({ code }) => ({
messages: [{
role: 'user',
content: { type: 'text', text: code },
}],
})
2. Use Descriptive Arguments
Always use .describe() on Zod fields to help both users and AI understand what's expected:
inputSchema: {
// Good: Clear descriptions
language: z.enum(['typescript', 'javascript']).describe('Programming language of the code'),
strict: z.boolean().default(true).describe('Whether to enforce strict TypeScript rules'),
// Less helpful: No descriptions
lang: z.string(),
s: z.boolean(),
}
3. Use Conversation Flow
Use user and assistant messages to guide the AI:
// Effective: User provides context, assistant acknowledges
messages: [
{ role: 'user', content: { type: 'text', text: 'You are an expert in accessibility. Review this HTML for a11y issues.' } },
{ role: 'assistant', content: { type: 'text', text: 'I\'ll analyze the HTML for accessibility issues.' } },
]
4. Keep Prompts Focused
Each prompt should have a single, clear purpose. Create multiple prompts instead of one complex one:
// Good: Separate focused prompts
// server/mcp/prompts/review-security.ts
// server/mcp/prompts/review-performance.ts
// server/mcp/prompts/review-style.ts
// Less maintainable: One complex prompt trying to do everything
5. Provide Default Values
Use .default() for optional arguments to improve usability:
inputSchema: {
format: z.enum(['brief', 'detailed']).default('detailed').describe('Output format'),
language: z.string().default('en').describe('Response language'),
}
6. Include Examples in Complex Prompts
For prompts that need specific output formats, include examples:
handler: async () => ({
messages: [{
role: 'user',
content: {
type: 'text',
text: `Generate a commit message following this format:
type(scope): description
Example:
feat(auth): add OAuth2 login support
Types: feat, fix, docs, style, refactor, test, chore`,
},
}],
})
Next Steps
- Prompt Examples - See advanced prompt examples
- Tools - Create tools to perform actions
- Resources - Create resources to expose data
- Handlers - Create custom MCP endpoints