MCP
Tool manifests for Model Context Protocol servers. An MCP server such as the Grav MCP Server already has tools for everything the API plugin does itself, but it can't know about routes that other plugins add through onApiRegisterRoutes. A plugin describes those routes as tools, in an mcp.yaml...
Tool manifests for Model Context Protocol servers. An MCP server such as the Grav MCP Server already has tools for everything the API plugin does itself, but it can't know about routes that other plugins add through onApiRegisterRoutes. A plugin describes those routes as tools, in an mcp.yaml file at its root or in code through the onApiMcpTools event, and List MCP Tools serves the union of every enabled plugin's tools so the MCP server can register them at startup without code written per plugin.
Permissions: api.access. Each tool is filtered further by the permission it names.
List MCP Tools
/mcp/tools
{"data": {"tools": [{"name": "kahunacart_list_products", "plugin": "kahunacart", "title": "List products", "description": "List catalog products with paging, search and status filters.", "method": "GET", "path": "/kahunacart/products", "permission": "kahunacart.products.manage", "annotations": {"readOnly": true, "destructive": false, "idempotent": true}, "input_schema": {"type": "object", "properties": {"q": {"type": "string"}}}, "path_params": [], "query": [], "body": null}], "plugins": [{"slug": "kahunacart", "name": "KahunaCart", "version": "0.1.0", "tools": 1}], "warnings": [], "fingerprint": "5f1d9c2a7b3e4d08"}}
Response Codes
Each tool has:
| Field | Meaning |
|---|---|
name |
The tool name an MCP client registers, {prefix}_{name} from the manifest, 64 characters or fewer |
plugin |
Slug of the plugin that contributed it |
title |
Human title an MCP client may show, or null |
description |
What the tool does and returns, and when to use it |
method |
GET, POST, PATCH, PUT or DELETE |
path |
Route path relative to the API base; {name} placeholders are filled from the arguments |
permission |
The permission the route enforces, or null |
annotations |
readOnly, destructive and idempotent, always filled in with the per-method defaults |
input_schema |
JSON Schema object for the arguments; a tool with no arguments has {"type": "object", "properties": {}} |
path_params |
The {name} placeholders in path, in order |
query |
For write methods, the properties sent as query parameters instead of in the body (a GET sends every non-path property as a query parameter) |
body |
The one property whose value is the whole request body, or null when the body is built from the remaining properties |
plugins[].tools counts the tools this caller can see, not how many the manifest declares. warnings has one line for each manifest entry that was skipped and why, for example an unsupported JSON Schema keyword. fingerprint changes when the set of enabled plugins or any manifest file changes, and it is also the response's ETag.