Skip to content

Fix create_scenario reporting false failures and storing duplicates - #2

Open
92Infinitus92 wants to merge 2 commits into
feat/pyth-price-feed-fieldsfrom
fix/mcp-async-http
Open

Fix create_scenario reporting false failures and storing duplicates#2
92Infinitus92 wants to merge 2 commits into
feat/pyth-price-feed-fieldsfrom
fix/mcp-async-http

Conversation

@92Infinitus92

@92Infinitus92 92Infinitus92 commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

The MCP tools ran HTTP through reqwest's blocking client from async tool functions.
A create_scenario the server had already stored (POST /v1/scenarios 200 in the
CLI log) could still be reported to the model as a connection failure — it retried,
and a second scenario landed under the same id, so the studio showed two identical
cards. All three affected tools now use the async client.

POST /v1/scenarios is idempotent by content: same id and same document is a
no-op, different content under a taken id returns 409. The check shares the write
lock with the insert, and create_scenario turns a 409 into an actionable message.

The template-registry read guard moved into its own scope — holding it across the
new await made the future non-Send.

Testing. cargo test: cli 20/20 (new test: create → identical retry →
conflicting content), mcp 5/5, core pyth 3/3; fmt clean. Live with Claude and
OpenAI: three scenarios in a row, one POST each, no retries, clean logs.

Not addressed here: MCP failures still come back as successful tool results
carrying an error payload — fixing that means honouring isError in the shared
client path used by all five providers, a separate change.

Greptile Summary

The PR makes scenario creation idempotent and migrates MCP HTTP operations from blocking to asynchronous reqwest calls.

  • Returns a no-op success for identical scenario retries and a conflict for reused IDs with different content.
  • Keeps the scenario write lock across duplicate detection and insertion.
  • Releases the template-registry read guard before awaiting HTTP work.
  • Converts token-account and scenario HTTP operations to async calls.
  • Adds coverage for initial creation, identical retry, and conflicting content.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
crates/cli/src/http/mod.rs Adds atomic duplicate detection and content-based idempotency to scenario creation, with focused endpoint coverage.
crates/mcp/src/surfpool/mod.rs Migrates MCP HTTP calls to async reqwest, scopes template-registry locking before awaits, and maps scenario conflicts to an actionable response.
crates/mcp/src/surfpool/set_token_account.rs Converts token-account RPC execution and response-body handling to asynchronous reqwest operations.

Sequence Diagram

sequenceDiagram
    participant MCP as MCP create_scenario
    participant API as POST /v1/scenarios
    participant Store as Scenario store
    MCP->>API: POST scenario
    API->>Store: Acquire write lock and find ID
    alt ID absent
        API->>Store: Insert scenario
        API-->>MCP: "200 {id}"
    else Same ID and document
        API-->>MCP: "200 {id} (no-op)"
    else Same ID, different document
        API-->>MCP: 409 conflict
        MCP-->>MCP: Return actionable error payload
    end
Loading

Reviews (2): Last reviewed commit: "Merge branch 'feat/pyth-price-feed-field..." | Re-trigger Greptile

…storing duplicates

The MCP tools called HTTP through reqwest's blocking client from async tool
functions, so a create_scenario the server had accepted could still be reported
as a connection failure; the model retried and stored a duplicate. They now use
the async client, and POST /v1/scenarios treats an identical retry as a no-op
while rejecting different content under a taken id with 409.
@92Infinitus92 92Infinitus92 self-assigned this Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant