What
Assistants and agents call tools, and a plant-care tool answered by an ungrounded model is the failure Sprout exists to prevent. Add sprout mcp (stdio transport, offline by default, optional extra): tools ask, toxicity_check, and identify, each returning the same structured Answer payload the JSON API returns (sentences, citations with fetch dates, confidence band, refusal reason, escalation card) and never free text without a source. The output guard runs on every tool result. Nothing is persisted.
Add --target mcp to sprout eval so all suites run through the MCP boundary, and the report names the target so a reader can see the numbers came through the tool surface rather than in-process.
Why it matters
The value of Sprout is the contract, not the chat. An MCP surface lets a household assistant or a vet clinic's agent use the cited pipeline while the contract holds; evaluating through the boundary is what proves the boundary did not weaken it (the same reason plumbline-live.sh exists in cairn).
Scope
- Server module, tool schemas mirroring
models.py, pyproject extra, docs.
- Eval target implementation via the plugin API (ADR-0019).
- Structured logging through
obs.py, PII-free.
Out of scope
- Remote transports or auth (loopback stdio only).
- Reminders or Family Greenhouse data over MCP.
Done when
sprout eval --target mcp byte-matches the in-process report's verdicts and scores.
- A tool call for an out-of-corpus species returns a refusal object with the routing line, not prose.
- A test proves no tool result can contain a certification string.
- The server starts and answers with the network blocked.
Pointers
src/sprout/server.py, src/sprout/answer.py, src/sprout/models.py, src/sprout/guards.py, src/sprout/eval/runner.py, docs/adr/0019
Proposed with AI assistance.
What
Assistants and agents call tools, and a plant-care tool answered by an ungrounded model is the failure Sprout exists to prevent. Add
sprout mcp(stdio transport, offline by default, optional extra): toolsask,toxicity_check, andidentify, each returning the same structuredAnswerpayload the JSON API returns (sentences, citations with fetch dates, confidence band, refusal reason, escalation card) and never free text without a source. The output guard runs on every tool result. Nothing is persisted.Add
--target mcptosprout evalso all suites run through the MCP boundary, and the report names the target so a reader can see the numbers came through the tool surface rather than in-process.Why it matters
The value of Sprout is the contract, not the chat. An MCP surface lets a household assistant or a vet clinic's agent use the cited pipeline while the contract holds; evaluating through the boundary is what proves the boundary did not weaken it (the same reason
plumbline-live.shexists in cairn).Scope
models.py,pyprojectextra, docs.obs.py, PII-free.Out of scope
Done when
sprout eval --target mcpbyte-matches the in-process report's verdicts and scores.Pointers
src/sprout/server.py,src/sprout/answer.py,src/sprout/models.py,src/sprout/guards.py,src/sprout/eval/runner.py,docs/adr/0019Proposed with AI assistance.