Prompts

MCP spec includes Prompts, which enable servers to define reusable prompt templates and workflows that clients can easily surface to users and LLMs.

Defining Prompts

The MCP::Prompt class provides three ways to create prompts.

1. As a class definition with metadata

Subclass MCP::Prompt and declare the metadata with class-level helpers; template builds the result:

class MyPrompt < MCP::Prompt
  prompt_name "my_prompt"  # Optional - defaults to underscored class name
  title "My Prompt"
  description "This prompt performs specific functionality..."
  arguments [
    MCP::Prompt::Argument.new(
      name: "message",
      title: "Message Title",
      description: "Input message",
      required: true
    )
  ]
  meta({ version: "1.0", category: "example" })

  class << self
    def template(args, server_context:)
      MCP::Prompt::Result.new(
        description: "Response description",
        messages: [
          MCP::Prompt::Message.new(
            role: "user",
            content: MCP::Content::Text.new("User message")
          ),
          MCP::Prompt::Message.new(
            role: "assistant",
            content: MCP::Content::Text.new(args["message"])
          )
        ]
      )
    end
  end
end

prompt = MyPrompt

2. Using the MCP::Prompt.define method

MCP::Prompt.define builds a prompt from keyword arguments, with the block as its template:

prompt = MCP::Prompt.define(
  name: "my_prompt",
  title: "My Prompt",
  description: "This prompt performs specific functionality...",
  arguments: [
    MCP::Prompt::Argument.new(
      name: "message",
      title: "Message Title",
      description: "Input message",
      required: true
    )
  ],
  meta: { version: "1.0", category: "example" }
) do |args, server_context:|
  MCP::Prompt::Result.new(
    description: "Response description",
    messages: [
      MCP::Prompt::Message.new(
        role: "user",
        content: MCP::Content::Text.new("User message")
      ),
      MCP::Prompt::Message.new(
        role: "assistant",
        content: MCP::Content::Text.new(args["message"])
      )
    ]
  )
end

3. Using the MCP::Server#define_prompt method

MCP::Server#define_prompt registers the prompt directly on a server instance:

server = MCP::Server.new
server.define_prompt(
  name: "my_prompt",
  description: "This prompt performs specific functionality...",
  arguments: [
    Prompt::Argument.new(
      name: "message",
      title: "Message Title",
      description: "Input message",
      required: true
    )
  ],
  meta: { version: "1.0", category: "example" }
) do |args, server_context:|
  Prompt::Result.new(
    description: "Response description",
    messages: [
      Prompt::Message.new(
        role: "user",
        content: Content::Text.new("User message")
      ),
      Prompt::Message.new(
        role: "assistant",
        content: Content::Text.new(args["message"])
      )
    ]
  )
end

The server_context parameter is the server_context passed into the server and can be used to pass per request information, e.g. around authentication state or user preferences.

Icons for prompts are documented on the Icons page.

Key Components

  • MCP::Prompt::Argument - Defines input parameters for the prompt template with name, title, description, and required flag
  • MCP::Prompt::Message - Represents a message in the conversation with a role and content
  • MCP::Prompt::Result - The output of a prompt template containing description and messages
  • MCP::Content::Text - Text content for messages

Registering Prompts

Register prompts with the MCP server:

server = MCP::Server.new(
  name: "my_server",
  prompts: [MyPrompt],
  server_context: { user_id: current_user.id },
)

The server will handle prompt listing and execution through the MCP protocol methods:

  • prompts/list - Lists all registered prompts and their schemas
  • prompts/get - Retrieves and executes a specific prompt with arguments

Prompts with Image and Embedded Resource Content

Prompt messages are not limited to text. The same MCP::Content types used in tool responses can be used as message content, letting a prompt template include images or inline resource contents. Unlike tool responses, the content object is passed directly rather than as a hash; MCP::Prompt::Message serializes it when the prompt result is returned:

class CodeReviewPrompt < MCP::Prompt
  prompt_name "code_review"
  description "Review a source file with an accompanying diagram"
  arguments [
    MCP::Prompt::Argument.new(name: "file_uri", description: "URI of the file to review", required: true),
  ]

  class << self
    def template(args, server_context:)
      MCP::Prompt::Result.new(
        messages: [
          MCP::Prompt::Message.new(
            role: "user",
            content: MCP::Content::EmbeddedResource.new(
              MCP::Resource::TextContents.new(
                uri: args["file_uri"],
                mime_type: "text/x-ruby",
                text: read_source(args["file_uri"]),
              ),
            ),
          ),
          MCP::Prompt::Message.new(
            role: "user",
            content: MCP::Content::Image.new(architecture_diagram_base64, "image/png"),
          ),
          MCP::Prompt::Message.new(
            role: "user",
            content: MCP::Content::Text.new("Please review the code above, using the diagram for context."),
          ),
        ],
      )
    end
  end
end