developmentseed / developmentseed/mcp-toolsets-runtime

Hard-coded @state example key in handle descriptions gets copied by models

Open Beginner friendly
#108 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
0
Forks
0
Avg merge
1d 18h
Merged PRs (30d)
39

Description

`_handle_branch()` in `mcp_state/handles.py` puts a hard-coded example key into
the schema description of every `NotAuthored` parameter:

```python
"A session-state reference, e.g. "
f"{handle_for('dataset-search/search_datasets/area_of_interest')} "
"— the key from a [state updated: …] note. …"
```

Models copy it. Driving `dss-agentic-ai-services` (runtime 0.8.1) with only the
`cds` toolset mounted — so no AOI tool was connected and no key could possibly
exist — the agent replied to the user with:

> I don't have a valid area defined yet, so I can't submit the request. Please
> provide an area of interest (as a bounding box or AOI key from a prior tool
> result) … or an AOI key you already have (e.g.
> `@state:dataset-search/search_datasets/area_of_interest`)

It never called the tool, so it never hit the guard — it just handed the user a
key that doesn't exist, naming a toolset (`dataset-search`) that isn't part of
that deployment at all. The example reads as a real, available key rather than
as a placeholder.

**The guard itself is fine.** If the model *does* call the tool with that key,
the refusal is good and says so plainly:

```
submit_request was not called. Unresolved session-state references:
area: @state:dataset-search/search_datasets/area_of_interest — no such key in
session state. Nothing has been published to session state yet.
```

So this is about the description a model reads while deciding, not about
enforcement.

**Suggestion.** Either drop the concrete example and describe the shape
(`@state://`), or build it from a key that is actually in
session state — the surrounding machinery already knows what has been published,
since `unresolved_message` lists real keys when it refuses. A placeholder that
can't be mistaken for a live key would also do.

Worth noting it affects every consumer, not just this one, and the cost is a
model confidently telling a user to use a key that was never going to work.

Contributor guide

Open the contributing guide

Research direction

Start in mcp_state/handles.py at _handle_branch() and compare its description construction with unresolved_message, which already exposes published keys. Choose a non-live placeholder or shape description, then verify that generated NotAuthored parameter descriptions no longer present the concrete dataset-search key while existing unresolved-reference behavior remains unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
75/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.