chore(deps): bump mcp-toolsets-runtime to 0.2.1, document receipts - #20
Merged
Conversation
0.2.1 is runtime#40: a parameter filled from session state now leaves a
receipt on the tool message naming the key, the kind and the publishing
tool. Purely additive — new `mcp_state.receipts` module, new exports, no
signature changed — so nothing here needed a code change, and none was
made.
## Why the README changed anyway
Receipts close a gap the README's session-state section had described
only half of. It said a `Kind` tag buys resolution between tools and
removal from the model's schema. Removal from the schema is exactly what
made a fill untraceable: the parameter is absent from the tool call the
model produced, so neither the model nor a step panel could tell the call
had run against a stored value. The receipt is what makes the hidden
parameter accountable, so it belongs next to the thing that hides it.
Verified which side of that these toolsets fall on rather than assuming.
Nothing here tags a `Kind`, so nothing here produces a *visible* receipt:
handle | receipts_of: {'collections': {'key': 'stac-explorer/collections',
'via': 'handle', ...}}
handle | supplied: {} # host renders nothing
handle | breadcrumb: None # model is told nothing
declared | supplied: {'aoi': {...}}
declared | breadcrumb: [state used: aoi ← x/geometry, published by search]
The handle path records a receipt and shows it nowhere, by design — the
model wrote `@state:<key>` itself, so the key is already in the arguments.
Both hosts confirmed against the live local server:
CLI (untagged): []
web (untagged): {'name': 'dev'}
CLI (tagged): ['aoi ← x/geometry, published by search']
web (tagged): {'dataset_id': 'chirps',
'aoi': '← x/geometry · geojson.AreaOfInterest · from search'}
So the README says what receipts give you and that nothing here triggers
one yet — the same framing it already uses for tagging, rather than
describing a feature as if it were live.
## The tracing caveat
0.2.1's docs also document something that is not new behaviour but is
easy to get wrong here, since this repo deploys the chat: LangChain hands
every tool call the whole agent state, so a tracing backend records
stored payloads on every subsequent call. Values deliberately kept out of
the transcript still leave the process. That is upstream behaviour with
or without `mcp_state`, but it is the wrong thing to find out after
turning tracing on, so it is now a sentence in the section that promises
values stay out of the context — the promise is about the model, not the
process.
Also moves the view bridge lockfile to `@developmentseed/mcp-view` 0.2.1,
released in lockstep. `package.json` already allowed it; only the pin
moved, and the package is unchanged but for its reported version.
## Checks
`./scripts/lint` clean, `./scripts/test` 18 passed, `./scripts/build-views`
rebuilt both views, `mcp-agent install-elements` rewrote McpView.jsx.
Live against `mcp-serve-local`: all three toolsets ok, `hello` returns
`{"message": "Hello, dev!"}`, agent graph builds with `tool_state`
present and nothing withheld. `pyproject.toml`/`uv.lock` change is
version-only — 0.2.1 added no dependencies.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Upgrades the pinned runtime 0.2.0 → 0.2.1, and the view bridge lockfile to
@developmentseed/mcp-view0.2.1.What 0.2.1 is
runtime#40 — the other direction from capture. Capture tells the model what a tool wrote to
tool_state; nothing recorded what a tool read out of it. Now a parameter filled from session state leaves a receipt on the tool message's artifact:{"aoi": {"key": "dataset-search/geometry", "via": "declaration", "kind": "geojson.AreaOfInterest", "tool": "search_datasets"}}Purely additive — new
mcp_state.receiptsmodule, new exports, no signature changed. No code change was required here and none was made.But the README did need one
Its session-state section said a
Kindtag buys two things: resolution between tools, and removal from the model's schema. Removal from the schema is precisely what made a fill untraceable — the parameter is absent from the tool call the model produced, so neither the model nor a step panel could tell the call ran against a stored value:The receipt is what makes the hidden parameter accountable, so it belongs next to the thing that hides it. Added as the third thing tagging buys.
Which side of it these toolsets are on
Checked rather than assumed. Nothing here tags a
Kind, so nothing here produces a visible receipt — but the reason is more specific than "no tags", and worth stating precisely:The handle path — the only one available to an untagged toolset — does record a receipt, and shows it on neither side by design: the model wrote
@state:<key>itself, so the key is already in the tool call arguments and repeating it would buy nothing.Both hosts, against the live local server:
mcp-agent)mcp-agent-web)[]{'name': 'dev'}Kindaoi ← x/geometry, published by search{'dataset_id': 'chirps', 'aoi': '← x/geometry · geojson.AreaOfInterest · from search'}So the README describes what receipts give you and says nothing here triggers one yet — the same framing it already uses for tagging, rather than documenting a feature as though it were live.
One more thing worth having in this repo's README
0.2.1's docs also record something that is not new behaviour but is easy to get wrong here, since this repo is what deploys the chat:
Values deliberately kept out of the transcript still leave the process. This is upstream behaviour with or without
mcp_state— but it directly qualifies a promise our README makes, and it is the wrong thing to discover after wiring a tracing backend tochat.mcp-toolsets.ds.io. Now one sentence in that section: the guarantee is about what reaches the model, not about what leaves the process.The npm half
package.jsonalready allowed 0.2.1 via^0.2.0, so only the lockfile pin moved (npm update). The package is unchanged but for its reportedappInfo.version, which is what the MCP Apps host sees — worth keeping truthful.Verification
./scripts/lintclean ·./scripts/test18 passed ·./scripts/build-viewsrebuilt both views ·mcp-agent install-elementsrewrotepublic/elements/McpView.jsx.Live against
uv run mcp-serve-local:ok;mcp-cli call hello name=dev→{"message": "Hello, dev!"}tool_statepresent, 3 tools loaded, nothing withheldpyproject.toml+uv.lockchange is version-only — 0.2.1 added no dependencies.On merge
uv.lockis a shared build input, so every toolset, the index and the chat rebuild and redeploy. Chat conversations are checkpointed in pod memory and are lost, as on every runtime bump.🤖 Generated with Claude Code