docs(mcp): Q2 gains upstream's tool surface as measured prior art
sources/base.py plus tools/source_tools.py is the same problem phase 5 option (A) contemplates, already solved in ADK-specific form: a data system exposed as model-callable tools. Recorded under Q2 because that question calls the tool surface the real design work, and this is a worked example of it. Three signals, each with the reason it is a signal: enumerate and read are abstract while sample_rows defaults to None, so sampling is advisory; the surface is per-concept, which is evidence that Door B's per-run collision gate and index generation are the side that has to give; and two things not to copy — an untyped dict[str, Any] return that only a model can interpret, and a find() that linear-scans list_concepts() and so assumes total enumeration is cheap, against this library's rule that nothing enumerates unless a profile says derived. Read at the pinned commit, not vendored.
This commit is contained in:
parent
ff9f2f82ca
commit
ddc8f76446
1 changed files with 24 additions and 0 deletions
|
|
@ -66,6 +66,30 @@ something:
|
||||||
`process_inbox` over a directory. An MCP tool taking one concept at a time is
|
`process_inbox` over a directory. An MCP tool taking one concept at a time is
|
||||||
a different granularity, and the collision gate and index generation are
|
a different granularity, and the collision gate and index generation are
|
||||||
currently per-run rather than per-concept. This is the real design work.
|
currently per-run rather than per-concept. This is the real design work.
|
||||||
|
|
||||||
|
**Prior art, measured 2026-07-27 at the pinned upstream commit.** Upstream has
|
||||||
|
already built this surface in ADK-specific form, and it is worth reading before
|
||||||
|
we draw our own. `sources/base.py` (38 lines, stdlib only) defines a `Source`
|
||||||
|
ABC; `tools/source_tools.py` wraps its methods as model-callable tools, which
|
||||||
|
`agent.py` registers. Three things in it are design signals rather than
|
||||||
|
incidental:
|
||||||
|
|
||||||
|
- **`list_concepts` and `read_concept` are abstract; `sample_rows` is optional
|
||||||
|
with a `None` default; `find` ships a default implementation.** So the
|
||||||
|
surface's obligations are *enumerate* and *read*, and sampling is advisory.
|
||||||
|
A tool surface that made sampling mandatory would be claiming more than the
|
||||||
|
problem needs.
|
||||||
|
- **It is per-CONCEPT** (`read_concept(ref)`), which is the granularity this
|
||||||
|
question is about. That an independent implementation landed on per-concept
|
||||||
|
is evidence that the per-run shape — Door B's collision gate and index
|
||||||
|
generation — is the side that has to give, not the tool surface.
|
||||||
|
- **What not to copy.** `read_concept` returns `dict[str, Any]`, untyped
|
||||||
|
because a model interprets it; we render bytes and cannot. And `find` is a
|
||||||
|
linear scan over `list_concepts()`, which assumes total enumeration is cheap
|
||||||
|
— colliding directly with this library's rule that nothing enumerates unless
|
||||||
|
a profile says derived.
|
||||||
|
|
||||||
|
Read, not vendored. The point is the shape of the question they answered.
|
||||||
- **Q3 — Transport.** stdio is the vendorable, zero-dependency answer and
|
- **Q3 — Transport.** stdio is the vendorable, zero-dependency answer and
|
||||||
matches how the marketplace consumes things. HTTP would be a second network
|
matches how the marketplace consumes things. HTTP would be a second network
|
||||||
surface with its own gate question.
|
surface with its own gate question.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue