Skip to content

fix(mcp): route object params to JSON editor, keep invalid drafts out of tool args#5570

Merged
waleedlatif1 merged 8 commits into
stagingfrom
worktree-fix-mcp-args-json-coercion
Jul 10, 2026
Merged

fix(mcp): route object params to JSON editor, keep invalid drafts out of tool args#5570
waleedlatif1 merged 8 commits into
stagingfrom
worktree-fix-mcp-args-json-coercion

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Route plain object-typed MCP tool params (no enum) to the long-input JSON editor — getInputType previously only handled array-typed and non-primitive-enum params, leaving object params on the short-input's raw toString() path
  • Keep invalid/in-progress JSON edits out of the actual tool argument store — an incomplete edit (e.g. {"a":1 before the closing brace) used to fall back to storing the raw text, which the MCP execute route's array-coercion step could then silently wrap into a corrupted array instead of failing validation. Invalid text now lives in local per-param draft state so the textarea stays responsive but the persisted argument is always either the last valid parsed value or untouched

Type of Change

  • Bug fix

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…ts out of tool args

Two follow-up gaps from the earlier MCP schema fix:

- getInputType only routed array-typed and non-primitive-enum params to
  the long-input JSON editor; a plain object-typed param (no enum) fell
  through to the default short-input, which stores raw text via
  toString() and never round-trips a real object.

- The long-input onChange fell back to storing the raw typed text
  whenever JSON.parse failed (needed to keep the controlled textarea
  responsive mid-edit), but that meant an incomplete/invalid edit
  (e.g. `{"a":1` before the closing brace) could persist into the
  actual tool arguments. If executed in that state, the MCP execute
  route's array-coercion step would silently wrap the malformed string
  into a corrupted array instead of failing validation.

Invalid-edit text now lives in local `invalidJsonDrafts` state, keyed
by param name, instead of the real argument store — the textarea still
reflects every keystroke, but the persisted tool argument is always
either the last successfully parsed value or untouched. Drafts reset
when the selected tool changes.
@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 10, 2026 9:24pm

Request Review

@cursor

cursor Bot commented Jul 10, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Workflow-editor UI only; improves argument persistence for MCP blocks without touching auth, APIs, or execution routes directly.

Overview
Fixes MCP dynamic tool argument editing so object-typed parameters use the long JSON editor (same as arrays), and incomplete JSON edits no longer get written into persisted toolArgs.

For params that must be real JSON values (object, array, or non-primitive enum), invalid or in-progress text is held in local draft state keyed to the last valid value. The stored argument stays the last successfully parsed value (or unchanged), which avoids malformed strings reaching execution paths that could coerce them into bad array shapes. Array params still accept comma-separated plain text when the input does not look like a [/{ JSON literal.

Drafts are cleared when the selected tool or cached schema changes, or when the live discovered schema signature changes after a genuine refresh (with logic to ignore initial load and transient empty refetches).

Reviewed by Cursor Bugbot for commit 9cd9120. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR improves MCP dynamic argument editing for structured tool params. The main changes are:

  • Object params now use the long JSON editor.
  • Invalid JSON drafts stay local instead of being written to tool arguments.
  • Drafts reset when the selected tool or effective schema changes.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mcp-dynamic-args/mcp-dynamic-args.tsx Updates MCP argument rendering and draft handling for object, array, and structured JSON-like params.

Reviews (8): Last reviewed commit: "fix(mcp): re-baseline live schema tracke..." | Re-trigger Greptile

…hange

The draft reset only fired when the selected tool id changed, so a
same-tool schema refresh (e.g. re-discovering tools from the live MCP
server) could leave a stale invalid draft displayed under a param name
whose shape had since changed. Key the reset off both the tool id and
a signature of the effective schema's properties, so any change to
what's actually being edited clears stale drafts.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 0f7b3a5. Configure here.

…oolSchema

toolSchema resolves to cachedSchema || selectedToolConfig?.inputSchema,
so a live-only schema refresh (the discovered tool's inputSchema
changes but the cached _toolSchema snapshot doesn't) left the reset
key unchanged and could keep a stale invalid draft on screen. Track a
signature of each schema source independently so a change in either
one clears drafts, regardless of which source toolSchema resolves to.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

…ernal value changes

Two more follow-up gaps:

- schemaSignature only serialized schema.properties, so a same-tool
  refresh that changed only top-level fields like `required` (properties
  byte-identical) left the reset key unchanged. Sign the entire schema
  instead of cherry-picking fields, so nothing schema-level can be missed.

- A draft only reset on tool/schema change, so if the persisted argument
  changed for any other reason (undo/redo, a diff baseline switch, a
  collaborator's concurrent edit), the draft could keep shadowing the
  now-current value in the editor while execution used the real one.
  Drafts now carry a baseline signature of the value they were typed
  against; a draft only displays while that baseline still matches the
  live persisted value, so any external change makes it fall back to
  showing the real value instead of stale text.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

…set on tool load

Two more follow-up gaps:

- Holding every JSON.parse failure in a local draft blocked the
  documented comma-separated array shorthand (see the placeholder text)
  from ever reaching toolArgs, since plain comma-separated text is
  never valid JSON. Only an in-progress JSON array/object literal
  (starting with `[` or `{`) needs to stay in the draft until valid;
  plain array-typed text that isn't attempting JSON persists
  immediately as before, letting the execute route's existing
  comma-split/wrap coercion handle it as designed.

- draftResetKey always included the live selectedToolConfig schema
  signature, even when cachedSchema wins the `toolSchema` resolution.
  That segment flips from empty to populated the moment mcpTools
  finishes an unrelated async load, wiping in-progress drafts though
  neither the rendered schema nor the stored args changed. The live
  signature now only factors into the key when there's no cached
  snapshot for toolSchema to prefer.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 261f296. Configure here.

…irst load

Excluding the live schema signature whenever a cached snapshot exists
(the prior fix for a Cursor finding about mcpTools' initial load
spuriously wiping drafts) went too far the other way: a genuine
same-tool live schema refresh while a cached snapshot is still present
would no longer reset drafts either.

Track the live schema signature unconditionally, but only treat a
change as a real reset trigger when it goes from one non-empty
signature to a *different* non-empty one. The bare empty → non-empty
transition (mcpTools completing its initial fetch) is excluded, since
that's not a schema change; a populated → differently-populated
transition (an actual re-discovery) still resets drafts regardless of
whether a cached snapshot is present.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 72bdb1f. Configure here.

… render

Comparing the live schema signature only against the immediately
preceding render's value meant a schema that dropped to empty and then
reappeared with different content was invisible to the reset check —
both the drop (X → '') and the reappearance ('' → Y) look like a bare
empty/non-empty transition, which was deliberately excluded to avoid
resetting on mcpTools' initial load. Track the last non-empty value
actually observed instead, so a transient empty gap no longer erases
the baseline: the schema reset now fires correctly when the tool
reappears with a genuinely different schema, while a real first-ever
load (no prior non-empty value at all) still doesn't spuriously reset.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

lastNonEmptyLiveSchemaSignature carried over across a tool switch
whenever the newly-selected tool's live schema hadn't loaded yet in
that same render (still empty). When it loaded a moment later, the
comparison was against the *previous* tool's signature, so the new
tool's first schema load could be misread as a "genuine refresh" and
wipe drafts the user had already started typing against the new tool.
A tool/cached-schema change now always re-baselines the live-schema
tracker to the new tool's current signature (even if still empty), so
the "same tool" refresh comparison never bleeds across tool switches.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 9cd9120. Configure here.

@waleedlatif1 waleedlatif1 merged commit bbff34a into staging Jul 10, 2026
18 checks passed
@waleedlatif1 waleedlatif1 deleted the worktree-fix-mcp-args-json-coercion branch July 10, 2026 21:37
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