Reloads the things that can be changed without restarting the server: tool files from tools/, context providers from context_providers/, and every configured MCP server (reconnected, its tools re-registered). Call it after writing or editing any of them.
It takes no parameters.
{}
The output is one line per fact, and the call's success is false if any of them reported an error:
Tools (4): get_current_datetime, gmail, weather, my_tool. Tool errors (1): broken.py: SyntaxError: invalid syntax (broken.py, line 3) Context providers (2): hostname, server_status. MCP tools (37): mcp__tgclient__..., mcp__navi-web__...
Tool errors / Context provider errors — file by file. Errors are isolated: a broken file does not stop the others from loading, and does not stop the call from being useful. Fix the named file and reload again.Warning: enabled.json names N tool(s) that do not exist... — tools/enabled.json lists a name no tool answers to. Those names are silently dropped from every profile, so the tool you thought you enabled is simply absent. Check the name matches the tool's name exactly.MCP reload error — the MCP leg failed as a whole; the tools above it were still reloaded.Put a .py file in tools/. Files starting with _ are ignored (_template.py is a scaffold, not a tool).
Module style — the simple form:
name = "notes"
description = "Save and retrieve short text notes by key. Actions: save, get, list."
parameters = {
"type": "object",
"properties": {
"action": {"type": "string", "enum": ["save", "get", "list"]},
"key": {"type": "string", "description": "Note identifier"},
"value": {"type": "string", "description": "Note content (for save)"},
},
"required": ["action"],
}
async def execute(params: dict) -> str:
if params["action"] == "list":
return "No notes saved yet."
return f"Saved: {params['key']}"
All four names are required (name, description, parameters, execute), execute must be async, it takes params only, and it returns a string — a dict or None becomes str(...). Raise an exception to signal failure: it surfaces as a failed tool result with the exception type. description is what the model reads when deciding whether to call the tool, so write it for that decision, not as a title.
Class style — a subclass of Tool needs class-level name, description, parameters, and execute(self, params) or execute(self, params, ctx=None). Other signatures are rejected with a "wrong signature" error, and the class must be instantiable with no arguments.
To make the tool visible to a profile, its name must be declared — in the profile config, or in tools/enabled.json. A file that loads but is named nowhere is registered and still uncallable; list_tools is where that shows up.
Tool errors line, and the report is then partly about your editor.