Add prompts primitive (prompts/list, prompts/get) #6

Closed
opened 2026-05-17 15:56:08 +00:00 by claude-noether · 1 comment
Collaborator

Add the Prompts primitive — server exposes reusable parameterised prompt templates the client surfaces as a menu (slash-commands, snippets, "insert template").

Goal

A small server can ship a library of canned prompts ("explain this diff", "draft a release note for version X") without baking them into each client. The MCP spec defines this surface; lmcp currently has none of it.

Methods to add

Method Notes
prompts/list { prompts: [{ name, description?, arguments?: [{ name, description?, required? }] }], nextCursor? }
prompts/get Args { name, arguments?: { … } }{ description?, messages: [{ role, content: { type, text } }] }
notifications/prompts/list_changed Sent on dynamic add/remove.

API for lmcp

server:prompt("release_note", "Draft release notes for a version", {
    { name = "version", required = true },
    { name = "since",   required = false },
}, function(args)
    return {
        description = "Release-note draft prompt",
        messages = {
            { role = "user", content = { type = "text",
              text = "Write release notes for " .. args.version .. " since " .. (args.since or "previous tag") } },
        },
    }
end)

Capabilities

capabilities = {
    tools   = { listChanged = false },
    prompts = { listChanged = true },
}

Scope (v1)

  • prompts/list, prompts/get.
  • notifications/prompts/list_changed if a prompt is registered post-init.
  • Returns only text content blocks in v1. Image/audio/resource-link content can come later if needed.

Out of scope

  • Argument autocompletion (separate Completion issue).
  • Multi-modal content blocks.

Priority

Medium. Smaller surface than Resources, but mechanical to implement (mirrors the existing tool-registration machinery). Half a day.

Add the **Prompts** primitive — server exposes reusable parameterised prompt templates the client surfaces as a menu (slash-commands, snippets, "insert template"). ## Goal A small server can ship a library of canned prompts ("explain this diff", "draft a release note for version X") without baking them into each client. The MCP spec defines this surface; lmcp currently has none of it. ## Methods to add | Method | Notes | |---|---| | `prompts/list` | `{ prompts: [{ name, description?, arguments?: [{ name, description?, required? }] }], nextCursor? }` | | `prompts/get` | Args `{ name, arguments?: { … } }` → `{ description?, messages: [{ role, content: { type, text } }] }` | | `notifications/prompts/list_changed` | Sent on dynamic add/remove. | ## API for lmcp ```lua server:prompt("release_note", "Draft release notes for a version", { { name = "version", required = true }, { name = "since", required = false }, }, function(args) return { description = "Release-note draft prompt", messages = { { role = "user", content = { type = "text", text = "Write release notes for " .. args.version .. " since " .. (args.since or "previous tag") } }, }, } end) ``` ## Capabilities ``` capabilities = { tools = { listChanged = false }, prompts = { listChanged = true }, } ``` ## Scope (v1) - `prompts/list`, `prompts/get`. - `notifications/prompts/list_changed` if a prompt is registered post-init. - Returns only `text` content blocks in v1. Image/audio/resource-link content can come later if needed. ## Out of scope - Argument autocompletion (separate **Completion** issue). - Multi-modal content blocks. ## Priority **Medium**. Smaller surface than Resources, but mechanical to implement (mirrors the existing tool-registration machinery). Half a day.
Author
Collaborator

Implemented. Added in lmcp.lua:

  • self.prompts storage + opts.prompts opt-in flag mirroring resources discipline
  • server:prompt(name, opts, handler) registration. handler returns string (single user text message) or { description?, messages = {...} } for full control
  • prompts/list + prompts/get dispatch branches
  • notify_prompts_changed() + notifications/prompts/list_changed queue path (delivery NYI per #16)
  • Extracted shared _enqueue_list_changed(self, method) helper used by both resources and prompts
  • Capability advertised iff a prompt is registered OR opts.prompts=true
  • prompts/list uses the same paginate helper from #12

Added one sample prompt (release_note) to example_server.lua + the LMCP_TRANSPORT=stdio switch.

Verified live over stdio: capabilities include prompts, list returns one entry with arguments schema, get returns spec-shaped messages, missing-name → -32602, unknown name → -32002 (MCP-conventional "not found").

Implemented. Added in lmcp.lua: - `self.prompts` storage + `opts.prompts` opt-in flag mirroring resources discipline - `server:prompt(name, opts, handler)` registration. handler returns string (single user text message) or `{ description?, messages = {...} }` for full control - `prompts/list` + `prompts/get` dispatch branches - `notify_prompts_changed()` + `notifications/prompts/list_changed` queue path (delivery NYI per #16) - Extracted shared `_enqueue_list_changed(self, method)` helper used by both resources and prompts - Capability advertised iff a prompt is registered OR opts.prompts=true - `prompts/list` uses the same paginate helper from #12 Added one sample prompt (`release_note`) to example_server.lua + the LMCP_TRANSPORT=stdio switch. Verified live over stdio: capabilities include prompts, list returns one entry with arguments schema, get returns spec-shaped messages, missing-name → -32602, unknown name → -32002 (MCP-conventional "not found").
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marfrit/lmcp#6