
# Prompts

> Reusable message templates, filled in by the client.

A prompt returns messages the client can drop into a conversation. Clients list them with `prompts/list` and expand them with `prompts/get`.

```ts
import { defineMcpPrompt } from "h3-mcp";

const reviewPrompt = defineMcpPrompt({
  name: "code-review",
  title: "Code review",
  description: "Review code for best practices",
  args: [
    { name: "code", description: "Code to review", required: true },
    { name: "language", description: "Programming language" },
  ],
  handler: async (args, event) => ({
    messages: [
      {
        role: "user",
        content: {
          type: "text",
          text: `Review this ${args.language || ""} code:\n\n${args.code}`,
        },
      },
    ],
  }),
});
```

## With and Without Arguments

The definition is a tagged union: declare `args` and your handler receives `(args, event)`; omit it and the handler takes `(event)` alone.

```ts
const helpPrompt = defineMcpPrompt({
  name: "help",
  description: "Show available commands",
  handler: async (event) => ({
    messages: [
      {
        role: "assistant",
        content: { type: "text", text: "Here are the available commands..." },
      },
    ],
  }),
});
```

Arguments declared `required: true` are enforced before the handler runs — a `prompts/get` missing one is rejected at the boundary, so `args.code` above is always present.

## Message Content

Messages carry the same content blocks as tool results, so a prompt can embed an image or a resource:

```ts
handler: async (args) => ({
  messages: [
    { role: "user", content: { type: "text", text: "What changed in this diff?" } },
    {
      role: "user",
      content: {
        type: "resource",
        resource: { uri: "app:///HEAD.diff", mimeType: "text/x-diff", text: await getDiff() },
      },
    },
  ],
});
```

## Autocompletion

Give an argument a `complete` callback and clients can autocomplete it as the user types:

```ts
const deployPrompt = defineMcpPrompt({
  name: "deploy",
  args: [
    {
      name: "environment",
      required: true,
      complete: async (value, event) => ({
        values: ["production", "staging", "development"].filter((e) => e.startsWith(value)),
      }),
    },
  ],
  handler: async (args) => ({
    messages: [{ role: "user", content: { type: "text", text: `Deploy to ${args.environment}` } }],
  }),
});
```

:read-more{to="/guide/basics/completions" title="Completions"}

## Icons

```ts
defineMcpPrompt({
  name: "summarize",
  icons: [{ src: "https://example.com/summarize.svg", mimeType: "image/svg+xml" }],
  handler: async (event) => ({ messages: [] }),
});
```
