Files

65 lines
1.9 KiB
Python

"""Package a vendor verb and a tool as a reusable, advertised extension (SEP-2133).
`custom_methods/` registers a verb on the lowlevel `Server` by hand; this story
bundles the same idea as an `Extension`: declared contributions, a settings entry
under `ServerCapabilities.extensions`, and a `require_client_extension` gate on
the vendor method.
"""
from collections.abc import Sequence
from typing import Any
from pydantic import Field
import mcp.types as types
from mcp.server.context import ServerRequestContext
from mcp.server.extension import Extension, MethodBinding, ToolBinding
from mcp.server.mcpserver import MCPServer, require_client_extension
from stories._hosting import run_server_from_args
EXTENSION_ID = "com.example/catalog"
class SearchParams(types.RequestParams):
"""Subclass `RequestParams` so `_meta` (and the 2026 envelope keys) parse uniformly."""
query: str
limit: int = Field(default=3, ge=1, le=25)
class SearchResult(types.Result):
items: list[str]
def suggest(prefix: str) -> str:
"""Suggest a catalog entry for a prefix."""
return f"{prefix}-suggestion"
async def search(ctx: ServerRequestContext[Any, Any], params: SearchParams) -> SearchResult:
require_client_extension(ctx, EXTENSION_ID)
return SearchResult(items=[f"{params.query}-{n}" for n in range(params.limit)])
class Catalog(Extension):
"""One identifier, three contributions: settings, a tool, a vendor method."""
identifier = EXTENSION_ID
def settings(self) -> dict[str, Any]:
return {"suggest": True}
def tools(self) -> Sequence[ToolBinding]:
return [ToolBinding(fn=suggest)]
def methods(self) -> Sequence[MethodBinding]:
return [MethodBinding("com.example/search", SearchParams, search)]
def build_server() -> MCPServer:
return MCPServer("extensions-example", extensions=[Catalog()])
if __name__ == "__main__":
run_server_from_args(build_server)