Registration
You register a prompt withserver.prompt(config, handler), the same config-first shape as tools and resources. The difference is in how inputs are declared. A prompt has no input schema — this is MCP’s own model, not a limitation of FastMCP. A prompt’s inputs are a flat list of named arguments, each with an optional description and a required flag, and the client fills them in by name. The handler receives a Record<string, string> of whatever the client supplied.
server.ts
required flags before your handler runs. If the client omits a required argument, the request returns ProtocolError(InvalidParams) and the handler is never invoked — so inside the handler a required argument is always present. Because arguments are named and untyped strings, any further validation of their contents is yours to do; the framework guarantees presence, not shape.
Messages
A prompt’s job is to produce messages, and FastMCP gives you a short path for the common case and a full one for everything else. The common case is a single user turn: return a string and FastMCP wraps it in one user text message. That alone covers most prompts.server.ts
PromptMessage objects. Each message has a role and a content block, and the content block can be text, image, audio, resource (an embedded resource), or resource_link (a reference to one). Returning a single PromptMessage wraps it in a one-element array; returning an array of them gives you a multi-turn sequence used as-is.
For full control — a multi-turn exchange together with a description that overrides the one in the config — return a PromptResult. It carries the message array and an optional description, and is passed through without conversion.
server.ts
Return values
The same magic conversion that maps tool and resource return values maps prompt return values to aGetPromptResult, driven by what you return.
PromptResult is the escape hatch the last row points to — reach for it when you want to set the result description or hand-build the message array.
Argument completion
A prompt argument can suggest values as the user types it. When a client supports completion, it sends acompletion/complete request carrying the partial value, and the server routes that request to the matching argument’s complete callback. This is how a UI fills a dropdown for a prompt argument, so the user picks a valid value instead of the model guessing one.
Attach a complete callback to any argument. It receives the partial value the user has typed and an optional context holding the values already chosen for the prompt’s other arguments, and it returns either a plain string[] or a CompletionResult with explicit total and hasMore pagination hints. The callback may be async, so it can query a database or an API. Completion works on both protocol eras unchanged — the method is in both wire registries.
server.ts
context argument narrows suggestions against earlier answers — the example offers production for a normal service but withholds it for worker. FastMCP caps a bare string[] to the 100-item wire maximum and fills in total and hasMore for you; return a CompletionResult yourself only when you page the matches. The same complete callback shape serves resource template variables too.
Configuration
Beyondname, description, and arguments, the config object accepts these fields. Each is optional.
Dynamic registration
You can register a prompt before or afterserver.run(). Adding one to a running server sends notifications/prompts/list_changed to connected clients automatically, the same way the tool and resource notifications work — the registration system is uniform across the three primitives.
server.ts