Improve MCP tool selection guidance
This commit is contained in:
+1
-1
@@ -398,7 +398,7 @@ services:
|
|||||||
# Seed native MCP connections on a fresh Open WebUI database. Secrets
|
# Seed native MCP connections on a fresh Open WebUI database. Secrets
|
||||||
# stay inside the tool containers, so these internal URLs need no keys.
|
# stay inside the tool containers, so these internal URLs need no keys.
|
||||||
TOOL_SERVER_CONNECTIONS: >-
|
TOOL_SERVER_CONNECTIONS: >-
|
||||||
[{"url":"http://mike-ai-mcp-web:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"web-local","name":"Web (lokal)","description":"Kompakte Websuche und Quellenvergleich"}},{"url":"http://mike-ai-mcp-homeassistant:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"homeassistant-local","name":"Home Assistant (lokal)","description":"Home-Assistant-Werkzeuge mit serverseitigem Token"}},{"url":"http://mike-ai-mcp-arr:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"arr-local","name":"ARR (lokal)","description":"Sonarr- und Radarr-Werkzeuge"}},{"url":"http://mike-ai-mcp-unraid-official:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"unraid-readonly-local","name":"Unraid (lokal, read-only)","description":"Begrenzte Unraid-Diagnose"}}]
|
[{"url":"http://mike-ai-mcp-web:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"web-local","name":"Web (öffentlich, read-only)","description":"Für aktuelle öffentliche Internetdaten, Quellenprüfung, GitHub/Hugging Face und Produktsuche. Nicht für Home Assistant, Medienverwaltung oder NAS-Diagnose."}},{"url":"http://mike-ai-mcp-homeassistant:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"homeassistant-local","name":"Home Assistant (lokal)","description":"Nur für Home-Assistant-Entitäten, Zustände, Historie, Automationen, Dashboards und HA-Diagnose. Nicht für Unraid, Sonarr/Radarr oder allgemeine Websuche."}},{"url":"http://mike-ai-mcp-arr:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"arr-local","name":"Sonarr und Radarr (lokal)","description":"Nur für verwaltete Serien/Filme, fehlende Episoden, Queue und Suche über konfigurierte Indexer. Keine allgemeine Websuche; Schreibaktionen benötigen Vorschau und Freigabe."}},{"url":"http://mike-ai-mcp-unraid-official:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"unraid-readonly-local","name":"Unraid (Systemdiagnose)","description":"Nur für Unraid-Host, Array, Datenträger, Docker-Container, Shares, Netzwerk, UPS und Systemlogs. Nicht für Home Assistant oder Medieninhalte; Standardzugriff read-only."}}]
|
||||||
DO_NOT_TRACK: "true"
|
DO_NOT_TRACK: "true"
|
||||||
SCARF_NO_ANALYTICS: "true"
|
SCARF_NO_ANALYTICS: "true"
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ Chats oder privaten Nutzdaten.
|
|||||||
| Reasoning-Filter | Beide globalen Filter besaßen Priorität 0; bei gleicher Priorität entschied die ID-Sortierung statt der gewünschten Logik. | `Reasoning Default Off` läuft mit Priorität 10 sicher vor dem optionalen `Thinking`-Override mit Priorität 20. Filter und sicherer Installer liegen versioniert im Repository. |
|
| Reasoning-Filter | Beide globalen Filter besaßen Priorität 0; bei gleicher Priorität entschied die ID-Sortierung statt der gewünschten Logik. | `Reasoning Default Off` läuft mit Priorität 10 sicher vor dem optionalen `Thinking`-Override mit Priorität 20. Filter und sicherer Installer liegen versioniert im Repository. |
|
||||||
| Folgefragen | OpenWebUI erzeugte nach Antworten zusätzliche Vorschläge und verbrauchte dafür einen weiteren Modellaufruf. | Folgefragengenerierung ist in der persistenten OpenWebUI-Konfiguration und im Compose-Standard deaktiviert. |
|
| Folgefragen | OpenWebUI erzeugte nach Antworten zusätzliche Vorschläge und verbrauchte dafür einen weiteren Modellaufruf. | Folgefragengenerierung ist in der persistenten OpenWebUI-Konfiguration und im Compose-Standard deaktiviert. |
|
||||||
| Werkzeug-/Kontextschutz | Große MCP-Antworten und wiederholte identische Aufrufe konnten Kontextfenster sprengen beziehungsweise Tool-Schleifen erzeugen. | Globaler Stability Guard begrenzt Resultate, verdichtet alte Inhalte profilabhängig und stoppt Wiederholungen; JSON-Schemas und Bilder werden nicht beschädigt. |
|
| Werkzeug-/Kontextschutz | Große MCP-Antworten und wiederholte identische Aufrufe konnten Kontextfenster sprengen beziehungsweise Tool-Schleifen erzeugen. | Globaler Stability Guard begrenzt Resultate, verdichtet alte Inhalte profilabhängig und stoppt Wiederholungen; JSON-Schemas und Bilder werden nicht beschädigt. |
|
||||||
|
| Werkzeugauswahl | Überlappende oder zu allgemeine MCP-Beschreibungen führten zu falschen Werkzeugen, unnötigen Wiederholungen und paralleler Nutzung von MUA und Unraid-Diagnose. | Klare USE-/DO-NOT-USE-Texte auf Server- und Werkzeugebene; Web-Unterwerkzeuge sind nach Lookup, Verifikation, Shopping und Tiefenrecherche getrennt. Bestehende OpenWebUI-Verbindungen werden ohne Änderung von URL, Schlüssel oder Berechtigungen aktualisiert. |
|
||||||
| Leistungsdaten | Benchmarkdaten sollten sichtbar sein, ohne private Chat-Inhalte zu protokollieren. | Ein globaler Abschlussfilter schreibt ausschließlich technische Zahlen in eine lokal rotierende JSONL-Datei und zeigt eine knappe Statuszeile. |
|
| Leistungsdaten | Benchmarkdaten sollten sichtbar sein, ohne private Chat-Inhalte zu protokollieren. | Ein globaler Abschlussfilter schreibt ausschließlich technische Zahlen in eine lokal rotierende JSONL-Datei und zeigt eine knappe Statuszeile. |
|
||||||
| Antwortaktionen | Wiederkehrende Nachbearbeitungen sollten bewusst per Klick statt als permanenter Zusatzprompt laufen. | Eine versionierte globale Action bietet lokale Kurzfassung, Checkliste, Diagnose, Unsicherheits-/Quellenprüfung, Thinking-Verbesserung und Markdown-Kopie; keine Schreib- oder Profilwechselaktion. |
|
| Antwortaktionen | Wiederkehrende Nachbearbeitungen sollten bewusst per Klick statt als permanenter Zusatzprompt laufen. | Eine versionierte globale Action bietet lokale Kurzfassung, Checkliste, Diagnose, Unsicherheits-/Quellenprüfung, Thinking-Verbesserung und Markdown-Kopie; keine Schreib- oder Profilwechselaktion. |
|
||||||
| Sprachausgabe | Beim ersten Leerhostaufbau war kein TTS-Dienst Bestandteil des Compose-Stacks. | Piper `piper-tts` 1.6.0 läuft als eigener interner CPU-Container mit persistenter deutscher Stimme; Open WebUI nutzt ihn ausschließlich über den authentifizierten Router. |
|
| Sprachausgabe | Beim ersten Leerhostaufbau war kein TTS-Dienst Bestandteil des Compose-Stacks. | Piper `piper-tts` 1.6.0 läuft als eigener interner CPU-Container mit persistenter deutscher Stimme; Open WebUI nutzt ihn ausschließlich über den authentifizierten Router. |
|
||||||
|
|||||||
@@ -19,6 +19,25 @@ Prompts heraus, verhindert den früher beobachteten Kontextverbrauch von über
|
|||||||
TinySearch und SearXNG sind interne Abhängigkeiten des Web-MCPs und werden
|
TinySearch und SearXNG sind interne Abhängigkeiten des Web-MCPs und werden
|
||||||
nicht direkt als allgemeine Werkzeuge angeboten.
|
nicht direkt als allgemeine Werkzeuge angeboten.
|
||||||
|
|
||||||
|
## Entscheidungshilfe für das Modell
|
||||||
|
|
||||||
|
Die Server- und Werkzeugbeschreibungen grenzen die Zuständigkeiten absichtlich
|
||||||
|
deutlich voneinander ab. Das Modell soll pro Aufgabe zunächst genau **einen**
|
||||||
|
passenden Server wählen:
|
||||||
|
|
||||||
|
| Aufgabe | Werkzeugserver | Nicht zusätzlich verwenden |
|
||||||
|
|---|---|---|
|
||||||
|
| Aktuelle öffentliche Informationen, Quellen, GitHub/Hugging Face, Produkte | Web | HA, ARR, Unraid |
|
||||||
|
| Entitäten, Zustände, Historie, Automationen und Dashboards | Home Assistant | Web, Unraid |
|
||||||
|
| Serien, Filme, fehlende Episoden und Indexer-Releases | Sonarr und Radarr | Web |
|
||||||
|
| Lesende NAS-, Docker-, Array-, Netzwerk- und Logdiagnose | Unraid (Systemdiagnose) | MUA |
|
||||||
|
| Ausdrücklich benötigte MUA-Verwaltungsaktion | MUA | Unraid-Diagnose nicht parallel |
|
||||||
|
|
||||||
|
Ein leeres Ergebnis ist kein Grund, dieselbe Frage über mehrere unpassende
|
||||||
|
Werkzeuge oder leicht veränderte Suchbegriffe erneut auszuführen. Das Modell
|
||||||
|
soll die Grenze transparent nennen und gezielt nachfragen, wenn eine Freigabe
|
||||||
|
oder ein anderes Werkzeug benötigt wird.
|
||||||
|
|
||||||
## Sicherheitsmodell
|
## Sicherheitsmodell
|
||||||
|
|
||||||
- Kein MCP-Port wird auf eine Host-Adresse veröffentlicht.
|
- Kein MCP-Port wird auf eine Host-Adresse veröffentlicht.
|
||||||
|
|||||||
@@ -92,6 +92,9 @@ services:
|
|||||||
# The local fork adds bounded read-only Sonarr pseudo-actions. Keep the
|
# The local fork adds bounded read-only Sonarr pseudo-actions. Keep the
|
||||||
# patch explicit until upstream publishes a self-contained 2.x image.
|
# patch explicit until upstream publishes a self-contained 2.x image.
|
||||||
- ${ARR_SONARR_PATCH:-./patches/mcp_sonarr.py}:/usr/local/lib/python3.13/site-packages/arr_mcp/mcp/mcp_sonarr.py:ro
|
- ${ARR_SONARR_PATCH:-./patches/mcp_sonarr.py}:/usr/local/lib/python3.13/site-packages/arr_mcp/mcp/mcp_sonarr.py:ro
|
||||||
|
# Upstream's generic "Execute any Radarr API action" text gives small
|
||||||
|
# models no routing boundary. This overlay changes guidance only.
|
||||||
|
- ${ARR_RADARR_PATCH:-./patches/mcp_radarr.py}:/usr/local/lib/python3.13/site-packages/arr_mcp/mcp/mcp_radarr.py:ro
|
||||||
networks: [tools, egress]
|
networks: [tools, egress]
|
||||||
|
|
||||||
mcp-unraid-official:
|
mcp-unraid-official:
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
"""Radarr action-routed MCP tool with model-oriented routing guidance."""
|
||||||
|
|
||||||
|
import json
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from agent_utilities.mcp_utilities import dispatch, run_blocking
|
||||||
|
from fastmcp import FastMCP
|
||||||
|
from pydantic import Field
|
||||||
|
|
||||||
|
from arr_mcp.auth import get_radarr_client
|
||||||
|
|
||||||
|
|
||||||
|
def register_radarr_tools(mcp: FastMCP) -> None:
|
||||||
|
@mcp.tool(tags={"radarr"})
|
||||||
|
async def radarr_action(
|
||||||
|
action: str = Field(
|
||||||
|
description=(
|
||||||
|
"Choose one Radarr operation. Common read choices include get_movie for the "
|
||||||
|
"movie library and get_system_status/get_health for Radarr diagnostics. Use "
|
||||||
|
"list_actions only when an unusual Radarr operation is genuinely required. "
|
||||||
|
"Never guess a modifying action and never change Radarr without explicit user approval."
|
||||||
|
)
|
||||||
|
),
|
||||||
|
params_json: str = Field(
|
||||||
|
default="{}",
|
||||||
|
description=(
|
||||||
|
"JSON object encoded as a string containing only parameters required by the "
|
||||||
|
"selected Radarr action. Use \"{}\" for actions without parameters; never "
|
||||||
|
"invent movie IDs, paths, profile IDs or monitoring settings."
|
||||||
|
),
|
||||||
|
),
|
||||||
|
) -> Any:
|
||||||
|
"""USE ONLY for movies managed by Radarr: inspect the movie library, wanted/queue/history state, releases, profiles, or Radarr health. DO NOT use for TV episodes (use Sonarr), public-web research, media playback, filesystem copying, or direct downloads. Prefer read actions; any mutation requires explicit user approval."""
|
||||||
|
client = get_radarr_client()
|
||||||
|
kwargs = {k: v for k, v in json.loads(params_json).items() if v is not None}
|
||||||
|
return await run_blocking(
|
||||||
|
dispatch, client, action, kwargs, service="arr-radarr"
|
||||||
|
)
|
||||||
@@ -411,14 +411,14 @@ def register_sonarr_tools(mcp: FastMCP) -> None:
|
|||||||
@mcp.tool(tags={"sonarr"})
|
@mcp.tool(tags={"sonarr"})
|
||||||
async def sonarr_action(
|
async def sonarr_action(
|
||||||
action: str = Field(
|
action: str = Field(
|
||||||
description="Sonarr action. Read with find_series {query}, get_season_summary {series_id, season_number}, or search_releases {series_id, season_number}. To download missing episodes, first call preview_episode_search {series_id, season_number, episode_numbers:[2,3,...]}, show its exact preview to the user, then only after explicit approval call start_episode_search with the same scope plus confirm:true and approval_ticket. Monitoring is never changed."
|
description="Choose one Sonarr operation. Normal choices: find_series to resolve a TV-series name; get_season_summary to list present/missing episodes; search_releases to query Sonarr's configured indexers without downloading; preview_episode_search before any download search; start_episode_search only after the user explicitly approves that exact preview. Use list_actions only for an unusual read operation."
|
||||||
),
|
),
|
||||||
params_json: str = Field(
|
params_json: str = Field(
|
||||||
default="{}",
|
default="{}",
|
||||||
description="JSON string of parameters to pass to the action.",
|
description="JSON object encoded as a string. Common forms: find_series {\"query\":\"Title\"}; get_season_summary/search_releases {\"series_id\":123,\"season_number\":2}; preview_episode_search {\"series_id\":123,\"season_number\":2,\"episode_numbers\":[2,3]}. For start_episode_search reuse the exact preview scope and add confirm:true plus approval_ticket.",
|
||||||
),
|
),
|
||||||
) -> Any:
|
) -> Any:
|
||||||
"""Query Sonarr through a server-side allowlist (read-only by default; write actions when ARR_MCP_WRITE=1)."""
|
"""USE ONLY for TV-series tasks managed by Sonarr: identify a series, inspect missing episodes, search configured indexers, or start an explicitly approved missing-episode search. DO NOT use for movies (use Radarr), public-web research, media playback, filesystem copying, or direct URL downloads. Read-only by default; monitoring is never changed."""
|
||||||
if action in {"list_actions", "help", "actions"}:
|
if action in {"list_actions", "help", "actions"}:
|
||||||
return {
|
return {
|
||||||
"service": "sonarr",
|
"service": "sonarr",
|
||||||
|
|||||||
@@ -134,10 +134,94 @@ with con:
|
|||||||
""",
|
""",
|
||||||
(key, json.dumps(value), now),
|
(key, json.dumps(value), now),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Improve model-side tool selection without touching URLs, credentials,
|
||||||
|
# access grants or enable flags from a restored Open WebUI database.
|
||||||
|
row = con.execute(
|
||||||
|
"select value from config where key=?",
|
||||||
|
("tool_server.connections",),
|
||||||
|
).fetchone()
|
||||||
|
if row:
|
||||||
|
connections = json.loads(row[0])
|
||||||
|
if not isinstance(connections, list):
|
||||||
|
raise SystemExit("Unbekanntes Format in tool_server.connections.")
|
||||||
|
descriptions = {
|
||||||
|
"web-local": (
|
||||||
|
"Web (öffentlich, read-only)",
|
||||||
|
"Für aktuelle öffentliche Internetdaten, Quellenprüfung, GitHub/Hugging Face "
|
||||||
|
"und Produktsuche. Nicht für Home Assistant, Medienverwaltung oder NAS-Diagnose.",
|
||||||
|
),
|
||||||
|
"homeassistant-local": (
|
||||||
|
"Home Assistant (lokal)",
|
||||||
|
"Nur für Home-Assistant-Entitäten, Zustände, Historie, Automationen, Dashboards "
|
||||||
|
"und HA-Diagnose. Nicht für Unraid, Sonarr/Radarr oder allgemeine Websuche.",
|
||||||
|
),
|
||||||
|
"arr-local": (
|
||||||
|
"Sonarr und Radarr (lokal)",
|
||||||
|
"Nur für verwaltete Serien/Filme, fehlende Episoden, Queue und Suche über "
|
||||||
|
"konfigurierte Indexer. Keine allgemeine Websuche; Schreibaktionen benötigen "
|
||||||
|
"Vorschau und Freigabe.",
|
||||||
|
),
|
||||||
|
"unraid-readonly-local": (
|
||||||
|
"Unraid (Systemdiagnose)",
|
||||||
|
"Bevorzugtes Werkzeug für lesende Unraid-Diagnose: Host, Array, Datenträger, "
|
||||||
|
"Docker, Shares, Netzwerk, UPS und Logs. Für dieselbe Anfrage nicht zusätzlich "
|
||||||
|
"MUA aufrufen; MUA nur für dessen spezielle oder freigegebene Verwaltungsaktionen.",
|
||||||
|
),
|
||||||
|
"mua": (
|
||||||
|
"MUA (Unraid-Verwaltung)",
|
||||||
|
"Nur für ausdrücklich benötigte MUA-spezifische oder freigegebene Unraid-"
|
||||||
|
"Verwaltungsaktionen. Für reine Statusabfragen und Diagnosen stattdessen "
|
||||||
|
"Unraid (Systemdiagnose) verwenden; niemals beide parallel ausprobieren.",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
changed = False
|
||||||
|
for connection in connections:
|
||||||
|
if not isinstance(connection, dict):
|
||||||
|
continue
|
||||||
|
info = connection.get("info")
|
||||||
|
if not isinstance(info, dict):
|
||||||
|
info = {}
|
||||||
|
connection["info"] = info
|
||||||
|
identity = str(info.get("id", "")).lower()
|
||||||
|
url = str(connection.get("url", "")).lower()
|
||||||
|
if identity in descriptions:
|
||||||
|
match = identity
|
||||||
|
elif "192.168.1.2:3002" in url:
|
||||||
|
match = "mua"
|
||||||
|
elif "mike-ai-mcp-web" in url:
|
||||||
|
match = "web-local"
|
||||||
|
elif "mike-ai-mcp-homeassistant" in url:
|
||||||
|
match = "homeassistant-local"
|
||||||
|
elif "mike-ai-mcp-arr" in url:
|
||||||
|
match = "arr-local"
|
||||||
|
elif "mike-ai-mcp-unraid-official" in url:
|
||||||
|
match = "unraid-readonly-local"
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
name, description = descriptions[match]
|
||||||
|
if info.get("name") != name or info.get("description") != description:
|
||||||
|
info["name"] = name
|
||||||
|
info["description"] = description
|
||||||
|
changed = True
|
||||||
|
if changed:
|
||||||
|
con.execute(
|
||||||
|
"""
|
||||||
|
insert into config (key,value,updated_at) values (?,?,?)
|
||||||
|
on conflict(key) do update set
|
||||||
|
value=excluded.value,
|
||||||
|
updated_at=excluded.updated_at
|
||||||
|
""",
|
||||||
|
(
|
||||||
|
"tool_server.connections",
|
||||||
|
json.dumps(connections, ensure_ascii=False),
|
||||||
|
now,
|
||||||
|
),
|
||||||
|
)
|
||||||
print(
|
print(
|
||||||
"OpenWebUI konfiguriert: Default Off=10, Thinking=20, "
|
"OpenWebUI konfiguriert: Default Off=10, Thinking=20, "
|
||||||
"Stability Guard=30, Secret Redaction=40, Local Metrics=90, "
|
"Stability Guard=30, Secret Redaction=40, Local Metrics=90, "
|
||||||
"Quick Actions=100, Folgefragen=aus, Piper-TTS=aktiv"
|
"Quick Actions=100, Folgefragen=aus, Piper-TTS=aktiv, Werkzeugwahl=optimiert"
|
||||||
)
|
)
|
||||||
PY
|
PY
|
||||||
|
|
||||||
|
|||||||
@@ -56,12 +56,11 @@ TOOLS = [
|
|||||||
{
|
{
|
||||||
"name": "web_search",
|
"name": "web_search",
|
||||||
"description": (
|
"description": (
|
||||||
"Fast read-only web discovery. Returns a compact list of titles, direct URLs, "
|
"USE for a quick lookup of current public internet information or candidate URLs. "
|
||||||
"previews and upstream dates. Search previews are discovery hints, not verified "
|
"DO NOT use for Home Assistant, Sonarr/Radarr, Unraid, product prices (use "
|
||||||
"facts. Use web_compare when factual claims must be checked, and web_shop for "
|
"web_shop), source-verified claims (use web_compare), or difficult multi-source "
|
||||||
"products or prices. The result already includes the retrieval timestamp; do not "
|
"research (use web_research). Results are unverified discovery hints. Make one "
|
||||||
"call another clock tool. One call is normally sufficient. If no direct match is "
|
"call; if nothing relevant is found, say so instead of retrying variants."
|
||||||
"returned, report not found; do not retry wording variants."
|
|
||||||
),
|
),
|
||||||
"inputSchema": {
|
"inputSchema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -70,7 +69,7 @@ TOOLS = [
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"minLength": 2,
|
"minLength": 2,
|
||||||
"maxLength": 500,
|
"maxLength": 500,
|
||||||
"description": "Search query preserving names, constraints and intent.",
|
"description": "One precise public-web query. Preserve exact names, versions, dates and constraints from the user.",
|
||||||
},
|
},
|
||||||
"max_results": {
|
"max_results": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
@@ -82,7 +81,7 @@ TOOLS = [
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["auto", "web", "github", "huggingface"],
|
"enum": ["auto", "web", "github", "huggingface"],
|
||||||
"default": "auto",
|
"default": "auto",
|
||||||
"description": "Use auto unless the requested source is explicit.",
|
"description": "Use auto normally; choose github or huggingface only when that source is explicitly requested.",
|
||||||
},
|
},
|
||||||
"include_domains": {
|
"include_domains": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
@@ -106,15 +105,20 @@ TOOLS = [
|
|||||||
{
|
{
|
||||||
"name": "web_compare",
|
"name": "web_compare",
|
||||||
"description": (
|
"description": (
|
||||||
"Read-only evidence comparison for factual research. Discovers sources, crawls up "
|
"USE when the user asks to verify a factual claim, check whether information is "
|
||||||
"to five public pages, and returns short source-bound evidence. Treat a claim as "
|
"correct, or answer with trustworthy citations. It discovers and reads up to five "
|
||||||
"verified only when it appears in page_evidence; never promote a search preview to "
|
"public pages. DO NOT use for a simple URL lookup, shopping, or private systems. "
|
||||||
"a fact. Prefer primary sources when available and cite the supplied URL."
|
"Only page_evidence is verified; cite its URLs and expose conflicts or missing evidence."
|
||||||
),
|
),
|
||||||
"inputSchema": {
|
"inputSchema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"query": {"type": "string", "minLength": 2, "maxLength": 500},
|
"query": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 2,
|
||||||
|
"maxLength": 500,
|
||||||
|
"description": "The exact claim or question to verify, including relevant date/version context.",
|
||||||
|
},
|
||||||
"max_sources": {
|
"max_sources": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 2,
|
"minimum": 2,
|
||||||
@@ -142,11 +146,10 @@ TOOLS = [
|
|||||||
{
|
{
|
||||||
"name": "web_shop",
|
"name": "web_shop",
|
||||||
"description": (
|
"description": (
|
||||||
"Read-only product and price lookup designed for small models. Separates the "
|
"USE ONLY for finding products, current prices, availability, pack sizes, or a "
|
||||||
"requested retailer from comparison sites, extracts pack-size and price evidence, "
|
"purchase link. DO NOT use web_search for shopping. Preserve the requested retailer, "
|
||||||
"and marks whether price and direct product URL were actually verified. Recommend "
|
"brand and total budget. Recommend retailer-specific results only when "
|
||||||
"only candidates with price_verified_on_retailer=true when the user requested a "
|
"price_verified_on_retailer=true; never invent price, stock, quantity or URL."
|
||||||
"specific retailer. Never invent a missing link, pack size, availability or price."
|
|
||||||
),
|
),
|
||||||
"inputSchema": {
|
"inputSchema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -196,27 +199,32 @@ TOOLS = [
|
|||||||
{
|
{
|
||||||
"name": "web_research",
|
"name": "web_research",
|
||||||
"description": (
|
"description": (
|
||||||
"Read-only multi-source research for difficult questions. Uses local hybrid "
|
"USE ONLY for difficult, broad, or niche questions that require several sources, "
|
||||||
"BM25 plus dense ONNX reranking, crawls only the best pages, removes duplicates, "
|
"cross-checking, or discovery variants. For one factual claim use web_compare; for "
|
||||||
"and returns short source-bound evidence. Use depth=deep only when one search is "
|
"a quick lookup use web_search; for products use web_shop. This tool already runs "
|
||||||
"unlikely to be enough. The tool never decides unsupported facts: cite evidence "
|
"bounded variants internally, so never repeat the same research with another web "
|
||||||
"URLs and say insufficient when evidence is missing or conflicting. This tool "
|
"tool. Cite returned evidence URLs and state when evidence is insufficient."
|
||||||
"already performs bounded variants internally; never follow it with more searches "
|
|
||||||
"for the same request."
|
|
||||||
),
|
),
|
||||||
"inputSchema": {
|
"inputSchema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"query": {"type": "string", "minLength": 2, "maxLength": 500},
|
"query": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 2,
|
||||||
|
"maxLength": 500,
|
||||||
|
"description": "The complete research question, including scope, timeframe, versions and comparison criteria.",
|
||||||
|
},
|
||||||
"depth": {
|
"depth": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["quick", "deep"],
|
"enum": ["quick", "deep"],
|
||||||
"default": "quick",
|
"default": "quick",
|
||||||
|
"description": "Use quick by default. Use deep only for genuinely complex or poorly indexed topics.",
|
||||||
},
|
},
|
||||||
"backend": {
|
"backend": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["auto", "web", "github", "huggingface"],
|
"enum": ["auto", "web", "github", "huggingface"],
|
||||||
"default": "auto",
|
"default": "auto",
|
||||||
|
"description": "Use auto unless the user explicitly restricts research to GitHub or Hugging Face.",
|
||||||
},
|
},
|
||||||
"max_sources": {
|
"max_sources": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
|
|||||||
Reference in New Issue
Block a user