feat(agent): cross-char search_items tool + bump timeouts

Adds an MCP tool wrapping the inventory-service /search/items endpoint
with include_all_characters=true, so questions like 'find me a bracelet
with Legendary Acid Ward on any unequipped char' resolve in ONE tool call
instead of looping get_inventory over 60+ chars (which timed out at 120s).

- agent/tools.py: search_items_global wrapper
- agent/mcp_overlord.py: register new tool with detailed schema doc
- agent/claude_wrapper.py: include in --allowed-tools whitelist;
  bump timeout 120s -> 240s
- nginx/overlord.conf: bump /api/agent/ proxy timeout 180s -> 300s
- CLAUDE.md: brief Claude to USE search_items for cross-char searches
This commit is contained in:
Erik 2026-04-25 21:13:26 +02:00
parent d3943e894c
commit 4ae18536be
5 changed files with 82 additions and 8 deletions

View file

@ -127,10 +127,8 @@ TOOL_DEFS: dict[str, dict[str, Any]] = {
},
"get_inventory_search": {
"description": (
"Filtered inventory search for one character. Pass filter query "
"params as the `filters` object. Common filters: name (substring), "
"armor_level_min, armor_level_max, material, item_set, has_spell. "
"Returns matching items in the same shape as get_inventory."
"Filtered inventory search for ONE character. Use search_items "
"instead when the user wants to find something across ALL chars."
),
"schema": {
"type": "object",
@ -147,6 +145,39 @@ TOOL_DEFS: dict[str, dict[str, Any]] = {
str(args["character_name"]), args.get("filters") or {}
),
},
"search_items": {
"description": (
"CROSS-CHARACTER item search — one query that scans every "
"character's inventory. Use this whenever the user asks "
"'find me an X on any of my chars'. **Do not** iterate "
"get_inventory per character — this single tool call is far "
"faster and avoids agent timeouts.\n\n"
"Filter keys (pass as `filters` object, all optional):\n"
" include_all_characters: true (default if no scope given)\n"
" character: 'Name' (single char)\n"
" characters: 'A,B,C' (specific list, comma-separated)\n"
" text: substring of item name/description\n"
" has_spell: 'Legendary Acid Ward' (exact spell name match)\n"
" spell_contains: 'Legendary' (substring)\n"
" legendary_cantrips: 'Foo,Bar'\n"
" equipment_status: 'equipped' | 'unequipped'\n"
" equipment_slot: int bitmask (4=chest, 2048=bracelet, 4096=ring)\n"
" slot_names: 'Bracelet,Ring'\n"
" armor_only / jewelry_only / weapon_only: bool\n"
" min_armor / max_armor / min_damage / max_damage: int\n"
),
"schema": {
"type": "object",
"required": ["filters"],
"properties": {
"filters": {
"type": "object",
"description": "Query params dict — see tool description for keys.",
},
},
},
"fn": lambda args: T.search_items_global(args.get("filters") or {}),
},
"get_combat_stats": {
"description": (
"Lifetime + session combat stats for one character. Includes total "