Lesson 9 - Step 3 of 5

The prompts/list Method

Implement the method that lets clients discover available prompts.

Understanding prompts/list

The prompts/list method allows clients to discover what prompts your server offers. This is typically the first prompt-related request a client makes.

Request Format

The client sends a simple request with no required parameters:

json
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "prompts/list",
    "params": {}
}
Optional Cursor Parameter

Like tools/list and resources/list, the prompts/list method supports pagination with an optional cursor parameter. For most servers with a small number of prompts, pagination isn't needed.

Response Format

The server responds with a list of all available prompts:

json
{
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
        "prompts": [
            {
                "name": "code-review",
                "description": "Review code for bugs, style issues, and improvements",
                "arguments": [
                    {
                        "name": "code",
                        "description": "The code to review",
                        "required": true
                    },
                    {
                        "name": "language",
                        "description": "Programming language (python, javascript, etc.)",
                        "required": true
                    },
                    {
                        "name": "focus",
                        "description": "Review focus: security, performance, style, or all",
                        "required": false
                    }
                ]
            },
            {
                "name": "explain-code",
                "description": "Explain what a piece of code does in plain English",
                "arguments": [
                    {
                        "name": "code",
                        "description": "The code to explain",
                        "required": true
                    }
                ]
            },
            {
                "name": "summarize",
                "description": "Summarize text content concisely",
                "arguments": [
                    {
                        "name": "text",
                        "description": "The text to summarize",
                        "required": true
                    }
                ]
            }
        ]
    }
}

Python Implementation

Here's how to implement prompts/list in your MCP server:

python
"""
mcp_server.py - MCP Server with prompts support
"""

# Define available prompts
PROMPTS = {
    "code-review": {
        "name": "code-review",
        "description": "Review code for bugs, style issues, and improvements",
        "arguments": [
            {
                "name": "code",
                "description": "The code to review",
                "required": True
            },
            {
                "name": "language",
                "description": "Programming language (python, javascript, etc.)",
                "required": True
            },
            {
                "name": "focus",
                "description": "Review focus: security, performance, style, or all",
                "required": False
            }
        ]
    },
    "explain-code": {
        "name": "explain-code",
        "description": "Explain what a piece of code does in plain English",
        "arguments": [
            {
                "name": "code",
                "description": "The code to explain",
                "required": True
            }
        ]
    },
    "summarize": {
        "name": "summarize",
        "description": "Summarize text content concisely",
        "arguments": [
            {
                "name": "text",
                "description": "The text to summarize",
                "required": True
            },
            {
                "name": "max_length",
                "description": "Maximum length in sentences (default: 3)",
                "required": False
            }
        ]
    }
}


def handle_prompts_list(params):
    """Handle the prompts/list method."""
    # Return all prompts as a list
    return {
        "prompts": list(PROMPTS.values())
    }


def handle_request(method, params, request_id):
    """Route JSON-RPC requests to appropriate handlers."""
    if method == "prompts/list":
        result = handle_prompts_list(params)
        return {
            "jsonrpc": "2.0",
            "id": request_id,
            "result": result
        }

    # Handle other methods...
    return {
        "jsonrpc": "2.0",
        "id": request_id,
        "error": {
            "code": -32601,
            "message": f"Method not found: {method}"
        }
    }

Declaring Prompts Capability

For clients to know your server supports prompts, you must declare the capability in your initialize response:

python
def handle_initialize(params, request_id):
    """Handle the initialize method."""
    return {
        "jsonrpc": "2.0",
        "id": request_id,
        "result": {
            "protocolVersion": "2024-11-05",
            "capabilities": {
                "prompts": {},      # Declare prompts support
                "tools": {},        # If you also support tools
                "resources": {}     # If you also support resources
            },
            "serverInfo": {
                "name": "my-prompt-server",
                "version": "1.0.0"
            }
        }
    }
Empty Capabilities Object

The "prompts": {} capability object is currently empty, but including it tells clients that your server supports the prompts/list and prompts/get methods.

Testing with curl

Test your prompts/list implementation:

bash
# List all prompts
curl -X POST http://localhost:8080 \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "prompts/list",
    "params": {}
  }'

# Expected response:
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "prompts": [
      {
        "name": "code-review",
        "description": "Review code for bugs, style issues, and improvements",
        "arguments": [...]
      },
      ...
    ]
  }
}

Complete Server Example

Here's a complete HTTP server with prompts/list support:

python
"""
prompts_server.py - MCP server with prompts support
"""

import json
from http.server import HTTPServer, BaseHTTPRequestHandler

PROMPTS = {
    "code-review": {
        "name": "code-review",
        "description": "Review code for bugs and improvements",
        "arguments": [
            {"name": "code", "description": "Code to review", "required": True},
            {"name": "language", "description": "Programming language", "required": True}
        ]
    },
    "summarize": {
        "name": "summarize",
        "description": "Summarize text concisely",
        "arguments": [
            {"name": "text", "description": "Text to summarize", "required": True}
        ]
    }
}


class MCPHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        # Read and parse request
        length = int(self.headers.get("Content-Length", 0))
        body = json.loads(self.rfile.read(length).decode())

        method = body.get("method")
        params = body.get("params", {})
        request_id = body.get("id")

        # Route to handler
        if method == "initialize":
            result = {
                "protocolVersion": "2024-11-05",
                "capabilities": {"prompts": {}},
                "serverInfo": {"name": "prompts-server", "version": "1.0.0"}
            }
        elif method == "prompts/list":
            result = {"prompts": list(PROMPTS.values())}
        else:
            self.send_error_response(request_id, -32601, f"Unknown: {method}")
            return

        self.send_json({"jsonrpc": "2.0", "id": request_id, "result": result})

    def send_json(self, data):
        body = json.dumps(data).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", len(body))
        self.end_headers()
        self.wfile.write(body)

    def send_error_response(self, request_id, code, message):
        self.send_json({
            "jsonrpc": "2.0",
            "id": request_id,
            "error": {"code": code, "message": message}
        })


if __name__ == "__main__":
    server = HTTPServer(("localhost", 8080), MCPHandler)
    print("Server running on http://localhost:8080")
    server.serve_forever()

What's Next?

Now that clients can discover your prompts, let's implement prompts/get to actually retrieve and expand prompts with user-provided arguments.