# MCP Server Prompts

The MCP (Model Context Protocol) Server handler supports prompts in addition to
tools, enabling you to provide reusable, parameterized prompt templates through
the MCP protocol.

MCP prompts allow AI clients to request and execute structured prompt templates
with dynamic parameters, making it easy to standardize and share prompt patterns
and context across different AI workflows.

## Overview

Much like tools, Zuplo's MCP prompts work by utilizing structured API routes as
prompt generators that return formatted messages for AI consumption. When an MCP
client calls a prompt, your route handler returns a structured message array
that the AI can use directly.

But unlike MCP tools that perform actions and return data, MCP prompts return
formatted instructions or context that guide AI reasoning and responses.

## Configuration

### Route Configuration

Configure a route in your OpenAPI doc utilizing the `x-zuplo-route.mcp.type`
property:

```json
{
  "/greeting": {
    "post": {
      "operationId": "greeting",
      "summary": "Generate a personalized greeting",
      "description": "Creates a customized greeting for a given person",
      "requestBody": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string",
                  "description": "The name of the person to greet"
                }
              },
              "required": ["name"]
            }
          }
        }
      },
      "x-zuplo-route": {
        "corsPolicy": "none",
        "handler": {
          "export": "default",
          "module": "$import(./modules/greeting)"
        },
        "mcp": {
          "type": "prompt",
          "name": "greeting_generator",
          "description": "Utilize this prompt to generate a personalized greeting message"
        }
      }
    }
  }
}
```

The `x-zuplo-route.mcp` configuration for prompts supports:

- `type`: Must be set to `"prompt"` otherwise this will be registered as a tool.
- `name` - (optional) The identifier for the MCP prompt. If not provided, falls
  back to the `operationId` of the route. If no `operationId` is set, falls back
  to an auto-generated name.
- `description` - (optional) Description of what the prompt generates. If not
  provided, falls back to the operation's `description` or `summary` fields. If
  those are not set, uses an auto-generated description.

### MCP Server Handler Configuration

Add prompt configuration to your MCP Server handler options using the
`operations` array:

```json
{
  "paths": {
    "/mcp": {
      "post": {
        "x-zuplo-route": {
          "handler": {
            "export": "mcpServerHandler",
            "module": "$import(@zuplo/runtime)",
            "options": {
              "name": "example-mcp-server",
              "version": "1.0.0",
              "operations": [
                {
                  "file": "./config/routes.oas.json",
                  "id": "greeting"
                }
              ]
            }
          }
        }
      }
    }
  }
}
```

See further details in the
[MCP Server Handler documentation](../handlers/mcp-server.mdx).

## Route Handler Implementation

Your route handler must return a structured response with a `messages` array
containing properly formatted message objects: these are the message objects
that will populate the LLM's context and guide it, based on the templatized user
input, towards the desired result:

```typescript
export default async function (request: ZuploRequest, context: ZuploContext) {
  const { name } = await request.json();

  return {
    messages: [
      {
        role: "assistant",
        content: {
          type: "text",
          text: `Create a personalized greeting for ${name}. Make it friendly and welcoming!`,
        },
      },
    ],
  };
}
```

For more information on the format of messages to return to the LLM,

- `role`: Either “user” or “assistant” to indicate the speaker in the message
  flow.
- `content`: One of the following content
  [types defined by the MCP specification](https://modelcontextprotocol.io/specification/2025-06-18/server/prompts#promptmessage).

For more information, review
[the `PromptMessage` type and "Data Types" described in the MCP specification](https://modelcontextprotocol.io/specification/2025-06-18/server/prompts#promptmessage).

### Multiple Messages

You can return multiple messages to create complex and dynamic templates:

```typescript
return {
  messages: [
    {
      role: "assistant",
      content: {
        type: "text",
        text: "You are a helpful assistant that generates personalized greetings.",
      },
    },
    {
      role: "assistant",
      content: {
        type: "text",
        text: `Create a warm greeting for ${name} in ${location}. Consider local customs and time of day.`,
      },
    },
  ],
};
```

## Testing MCP Prompts

### List Available Prompts

Use the MCP `prompts/list` method to see available prompts:

```bash
curl localhost:9000/mcp \
  -X POST \
  -H 'accept: application/json, text/event-stream' \
  -d '{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "prompts/list"
  }'
```

Response:

```json
{
  "jsonrpc": "2.0",
  "id": "1",
  "result": {
    "prompts": [
      {
        "name": "greeting_generator",
        "description": "Generate a personalized greeting message for someone in a specific location",
        "arguments": [
          {
            "name": "name",
            "description": "The name of the person to greet",
            "required": true
          }
        ]
      }
    ]
  }
}
```

### Execute a Prompt

Use the MCP `prompts/get` method to execute a prompt with parameters:

```bash
curl localhost:9000/mcp \
  -X POST \
  -H 'accept: application/json, text/event-stream' \
  -d '{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "prompts/get",
    "params": {
      "name": "greeting_generator",
      "arguments": {
        "name": "john"
      }
    }
  }'
```

Response:

```json
{
  "jsonrpc": "2.0",
  "id": "1",
  "result": {
    "description": "Generate a personalized greeting message for someone in a specific location",
    "messages": [
      {
        "role": "assistant",
        "content": {
          "type": "text",
          "text": "Create a personalized greeting for john. Make it friendly and welcoming!"
        }
      }
    ]
  }
}
```

## Best Practices

### Prompt Design

- Write clear, specific prompt instructions that guide AI behavior
- Use parameter interpolation to create dynamic, contextual prompts
- Include relevant context and constraints in your prompt text
- Consider the target AI model's strengths and prompt formatting preferences

### Parameter Schema

- Define comprehensive JSON schemas for prompt parameters - this _must_ appear
  as a `application/json` request body in a `POST` to your route. Typically,
  this will point to a module that programmatically can craft the prompt.
- Include helpful descriptions for each parameter
- Mark required parameters appropriately
- Use validation to ensure parameter quality

### Message Organization

- Use `system` messages for general behavior instructions
- Use `assistant` messages for specific task guidance
- Structure complex prompts as multiple focused messages
- Keep individual messages concise and purposeful
