Runs the tools the Eugene Plexus hub runs itself — web search, and remote MCP on the Responses door — for one tool provider account.
OpenAI's and Anthropic's APIs define web_search as a tool the provider
runs. Point Codex or Claude Code at a local model and nobody runs it: Codex
silently loses its search and Claude Code's WebSearch fails. With a
tool-driver in the install, the gateway
offers the model a search tool, sends each search the model makes here, and
hands the results back, so the model answers with sources.
An install runs zero or more instances, one per search account:
- SearXNG — free and self-hosted. Give it the instance's address. The
instance must allow JSON output: add
jsontosearch.formatsin itssettings.yml(it answers403otherwise, and this component says so). - Brave Search — a paid service with its own index. Give it your API key.
- Google Search (Gemini API key) — Google's search, reached through a Gemini model (Grounding with Google Search). Give it a Gemini key from Google AI Studio. Billed per search; Google's terms require its answer and Search Suggestions to be shown unmodified to the person who asked.
- Tavily — a paid search service made for AI models. Give it your API key; each search costs 1 credit (basic depth) or 2 (advanced).
Either way the words searched for leave your machine: a SearXNG on your LAN forwards them to public engines. That is why a client key marked local-only never has a search run for it.
It holds the account's secret (sealed at rest, like an inference-driver's API
key) and serves POST /v1/tools/web_search. It does not run the loop
that decides when to search, how many times, or what the model is told — that
is the gateway's, so every door (chat completions, Responses, Anthropic
messages) behaves the same. It never runs tools that act on your machine;
files, shells and your own local MCP servers stay in apps and clients.
Remote MCP (POST /v1/tools/mcp/list_tools and /v1/tools/mcp/call,
for the install's gateway only): when an API client names an MCP server on
a Responses request, the gateway asks this process to list its tools and to
call them. The server is reached on the internet only, over https, unless
the owner chose Internet and this network in the gateway's settings; this
machine's loopback, link-local and cloud metadata addresses are never
reached. Every address a name resolves to is checked, and the connection
goes to the address that was checked. The caller's headers go to that one
server for that one call, and are never logged or kept. Limits: 30 s a
call, 8 MiB in all that a server sends for one call, 64 tools.
The contract is openapi/tool-driver.yaml
in specs; the design is
docs/design/server-run-tools.md.
The agent supervises it: add a search account from the console
(Backends → Add a search account), or declare a component of kind
tool-driver. Standalone, for development:
python -m eugene_plexus_tool_driver # binds 127.0.0.1:8190, no authpython -m venv .venv && .venv/bin/pip install -e ".[dev]"
python scripts/codegen.py # regenerate models at the pinned SPECS_REF
ruff check . && ruff format --check . && mypy src/ && pytestApache-2.0. Contributions are signed off (DCO), not assigned.