Skip to content

Tools

Tools are functions that an LLM can call to perform actions. They are the primary mechanism for servers to expose executable functionality.

Registering a Tool

cpp
server->RegisterTool("get_weather",
    ToolOptions{}.Description("Get current weather for a location"),
    [](const RequestContext<CallToolRequestParams>& ctx) -> CallToolResult {
        std::string location;
        if (ctx.Params().arguments) {
            auto* v = ctx.Params().arguments->Find("location");
            if (v) location = v->GetString();
        }

        CallToolResult result;
        result.content.push_back(
            TextContent{"text", "The weather in " + location + " is sunny."});
        return result;
    });

Tool with Annotations

cpp
ToolOptions opts;
opts.title = "Delete File";
opts.description = "Permanently delete a file by path";
opts.destructive = true;   // marks as destructive_hint
opts.idempotent = false;

server->RegisterTool("delete_file", opts,
    [](const RequestContext<CallToolRequestParams>& ctx) -> CallToolResult {
        // ...
    });

Available annotations via ToolOptions:

FieldTypeDescription
destructiveoptional<bool>Marks the tool as destructive
idempotentoptional<bool>Calling multiple times has same effect as once
read_only_hintoptional<bool>Tool does not modify state
open_world_hintoptional<bool>Tool may interact with external systems

Structured Content

Tools can return structured JSON data instead of text:

cpp
CallToolResult result;
result.content.push_back(TextContent{"text", "Processed."});
result.structured_content = JsonValue::Parse(R"({
    "records_updated": 42,
    "duration_ms": 153
})");

The structured_content field is a 2026-07-28 protocol feature. Set use_structured_content = true on ToolOptions to opt in, which sets output_schema to {"type": "object"}.

Input Schema

Set the tool's input_schema via ToolOptions::InputSchema() or directly:

cpp
auto schema = JsonValue::Parse(R"({
    "type": "object",
    "properties": {
        "location": {"type": "string"},
        "units": {"type": "string", "enum": ["celsius", "fahrenheit"]}
    },
    "required": ["location"]
})");

server->RegisterTool("get_weather",
    ToolOptions{}.InputSchema(std::move(schema)),
    [](const RequestContext<CallToolRequestParams>& ctx) -> CallToolResult {
        // ...
    });