Skip to content

Commit 261f296

Browse files
committed
fix(mcp): restore comma-separated array input; stop spurious draft reset 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.
1 parent 5a0466d commit 261f296

1 file changed

Lines changed: 22 additions & 5 deletions

File tree

  • apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mcp-dynamic-args

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mcp-dynamic-args/mcp-dynamic-args.tsx

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,17 @@ function schemaSignature(schema: unknown): string {
5252
return schema ? JSON.stringify(schema) : ''
5353
}
5454

55+
/**
56+
* True when text looks like an attempted JSON array/object literal (starts with `[`
57+
* or `{`), as opposed to plain freeform text. Used to tell an in-progress, incomplete
58+
* JSON literal (which must not persist until valid — see `requiresJsonValue`) apart
59+
* from the comma-separated/plain-text shorthand array params also accept.
60+
*/
61+
function looksLikeJsonLiteral(text: string): boolean {
62+
const trimmed = text.trim()
63+
return trimmed.startsWith('[') || trimmed.startsWith('{')
64+
}
65+
5566
interface McpDynamicArgsProps {
5667
blockId: string
5768
subBlockId: string
@@ -115,15 +126,16 @@ export function McpDynamicArgs({
115126
* reach tool execution. A draft is only displayed while its baseline still matches
116127
* the live persisted value, so an external change to that value (undo/redo, a diff
117128
* baseline switch, a collaborator's edit) can't be shadowed by stale draft text.
118-
* Drafts also reset wholesale whenever the selected tool or either schema source
119-
* changes — `toolSchema` prefers the cached `_toolSchema` snapshot over the live
120-
* discovered schema, so the reset key tracks both independently rather than the
121-
* resolved `toolSchema`, which wouldn't change on a live-only refresh.
129+
* Drafts also reset wholesale whenever the selected tool or the schema actually
130+
* backing `toolSchema` changes. The live discovered schema only factors in when
131+
* there's no cached snapshot to prefer — otherwise it's not what's rendered, so
132+
* live schema arriving/changing while a cached snapshot is already in effect
133+
* (e.g. `mcpTools` finishing an async load) must not spuriously reset drafts.
122134
*/
123135
const [invalidJsonDrafts, setInvalidJsonDrafts] = useState<
124136
Record<string, { text: string; baseline: string }>
125137
>({})
126-
const draftResetKey = `${selectedTool ?? ''}|${schemaSignature(cachedSchema)}|${schemaSignature(selectedToolConfig?.inputSchema)}`
138+
const draftResetKey = `${selectedTool ?? ''}|${schemaSignature(cachedSchema)}|${cachedSchema ? '' : schemaSignature(selectedToolConfig?.inputSchema)}`
127139
const [prevDraftResetKey, setPrevDraftResetKey] = useState(draftResetKey)
128140
if (prevDraftResetKey !== draftResetKey) {
129141
setPrevDraftResetKey(draftResetKey)
@@ -343,6 +355,11 @@ export function McpDynamicArgs({
343355
updateParameter(paramName, JSON.parse(newValue))
344356
clearDraft()
345357
} catch {
358+
if (paramSchema.type === 'array' && !looksLikeJsonLiteral(newValue)) {
359+
updateParameter(paramName, newValue)
360+
clearDraft()
361+
return
362+
}
346363
setInvalidJsonDrafts((prev) => ({
347364
...prev,
348365
[paramName]: { text: newValue, baseline: valueSignature },

0 commit comments

Comments
 (0)