Skip to content

Prompts

How to expose a prompt: pair a spec Prompt definition with the renderer that serves its prompts/get, and register both with addPrompt().

use Nexus\Mcp\Core\Schema\Enum\Role;
use Nexus\Mcp\Core\Schema\Prompt\Prompt;
use Nexus\Mcp\Core\Schema\Prompt\PromptMessage;
use Nexus\Mcp\Core\Schema\Result\GetPromptResult;

->addPrompt(
    prompt: new Prompt(name: 'summarise', description: 'Summarises the user input.'),
    renderer: static fn(?array $args, ServerContext $context): GetPromptResult => new GetPromptResult(messages: [
        new PromptMessage(
            role: Role::User,
            content: new TextContent(text: 'Summarise the following ...'),
        ),
    ]),
)

The renderer is a \Closure or a PromptRendererInterface.

Attribute sugar

#[AsPrompt] marks a method as a prompt. The same ServerBuilder::register() walk discovers it as the other attributes. Each parameter becomes a prompt argument. It is required when it has no default, and its @param text becomes the description. The call's arguments are bound back to the parameters by name:

use Nexus\Mcp\Server\Attribute\AsPrompt;

final class SummaryPrompts
{
    /**
     * @param string $tone The desired tone.
     */
    #[AsPrompt(name: 'summarise', description: 'Summarises the user input.')]
    public function summarise(string $tone = 'neutral'): string
    {
        return "Summarise the following in a {$tone} tone: ...";
    }
}

A string return becomes a single User text message. A PromptMessage, a list of them, or a full GetPromptResult passes through. Prompt arguments arrive as strings, so every non-injected parameter must accept one: string, an enum hydrated from the value, or untyped. Attribute discovery has the full binding rules.

Message content types

PromptMessage::$content takes any single content block, so a prompt can carry images and embedded resources beside text:

use Nexus\Mcp\Core\Schema\ContentBlock\EmbeddedResource;
use Nexus\Mcp\Core\Schema\ContentBlock\ImageContent;
use Nexus\Mcp\Core\Schema\Resource\TextResourceContents;

return new GetPromptResult(messages: [
    new PromptMessage(role: Role::User, content: new TextContent(text: 'Describe this diagram:')),
    new PromptMessage(role: Role::User, content: new ImageContent(data: base64_encode($png), mimeType: 'image/png')),
    new PromptMessage(role: Role::User, content: new EmbeddedResource(
        resource: new TextResourceContents(uri: 'guides://style.md', text: $styleGuide),
    )),
]);

Each message holds exactly one block. To pair a caption with an image, send two messages, as above. The block types are the same five a tool result carries.