Documentation
¶
Overview ¶
Example: typed MCP tools — one tool per verb.
Each tool is a thin wrapper around a method on the blog store. The args struct says exactly what the tool needs (no "optional unless action=…" gymnastics), the return type is a concrete domain object that gets JSON-marshaled and advertised via `outputSchema` on tools/list, and every handler reads like normal Go — no map[string]any assertions.
One tool is kept on the older builder API (search_posts) so the two shapes stay visible side by side. Use the typed shape for new tools and the builder when you need to hand-tune a schema the typed generator doesn't emit yet.
The example also registers a subscribable resource template: blog://posts/{id}. `resources/templates/list` advertises the family, `resources/read` resolves concrete post IDs, and SSE/stdio clients can subscribe for standard `notifications/resources/updated` invalidations.
Try it:
go run ./examples/mcp-extensions &
# tools/list now carries inputSchema AND outputSchema for typed tools.
curl -s -X POST localhost:8080/mcp -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | jq .
curl -s -X POST localhost:8080/mcp -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{
"name":"create_post",
"arguments":{"title":"hello","author":"ada","content":"first","tags":["intro"]}
}}'
# Validation: required field missing surfaces through the MCP error envelope.
curl -s -X POST localhost:8080/mcp -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{
"name":"create_post","arguments":{"title":"hello"}
}}'