diff --git a/webmcp/declarative/executeTool-abort.https.html b/webmcp/declarative/executeTool-abort.https.html index b5b6bb4c55669c..4fcdc6dc1f29bd 100644 --- a/webmcp/declarative/executeTool-abort.https.html +++ b/webmcp/declarative/executeTool-abort.https.html @@ -39,7 +39,7 @@ const tool = tools.find(t => t.name === 'submit_test'); const controller = new AbortController(); - const executionPromise = document.modelContext.executeTool(tool, '{}', { signal: controller.signal }); + const executionPromise = document.modelContext.executeTool(tool, {}, { signal: controller.signal }); await toolActivatedPromise; diff --git a/webmcp/declarative/executeTool-respondWith-circular-object.https.html b/webmcp/declarative/executeTool-respondWith-circular-object.https.html index a7dddbf5305f32..2f6fda2bdfa7d6 100644 --- a/webmcp/declarative/executeTool-respondWith-circular-object.https.html +++ b/webmcp/declarative/executeTool-respondWith-circular-object.https.html @@ -27,7 +27,7 @@ await promise_rejects_dom( t, 'UnknownError', - document.modelContext.executeTool(tool, '{}'), + document.modelContext.executeTool(tool), 'executeTool() should reject with UnknownError when respondWith is passed a circular object' ); }, 'Declarative tool executeTool() rejects when respondWith() receives a circular object'); diff --git a/webmcp/declarative/execute_tool_change_event.https.html b/webmcp/declarative/execute_tool_change_event.https.html index 3cec95b69a3f77..b332cc9242a15e 100644 --- a/webmcp/declarative/execute_tool_change_event.https.html +++ b/webmcp/declarative/execute_tool_change_event.https.html @@ -37,16 +37,16 @@ } } - let inputArgs = JSON.stringify({ + let inputObject = { text: "regular text", number: 42, checkbox: true, radio: "radio2", textarea: "some text area content", select: "opt2" - }); + }; - await document.modelContext.executeTool(tool, inputArgs); + await document.modelContext.executeTool(tool, inputObject); assert_equals(document.getElementById('myinput').value, 'regular text'); assert_true(events['myinput'].inputFired, 'text input event should fire'); diff --git a/webmcp/declarative/execute_tool_submit_from_js.https.html b/webmcp/declarative/execute_tool_submit_from_js.https.html index d626c061859c8d..fa6cb031ccc769 100644 --- a/webmcp/declarative/execute_tool_submit_from_js.https.html +++ b/webmcp/declarative/execute_tool_submit_from_js.https.html @@ -24,7 +24,7 @@ }); // Call executeTool. If it throws, the test fails automatically. - await document.modelContext.executeTool(tool, '{}'); + await document.modelContext.executeTool(tool); assert_true(submitFired, 'submit event should have fired'); }, 'executeTool resolves successfully when submit handler calls form.submit()'); diff --git a/webmcp/declarative/form_removal_submit_crash.https.html b/webmcp/declarative/form_removal_submit_crash.https.html index d6e705782e06b3..4d4b0980d22574 100644 --- a/webmcp/declarative/form_removal_submit_crash.https.html +++ b/webmcp/declarative/form_removal_submit_crash.https.html @@ -36,7 +36,7 @@ // Execute the tool. This asynchronously fires the `submit` event at the form. // The tool execution should resolve successfully even if the form is removed // from the document during submission. - const promise = document.modelContext.executeTool(tool, '{}'); + const promise = document.modelContext.executeTool(tool); await promise; assert_true(submitFired); diff --git a/webmcp/declarative/opaque-origin-tools.https.html b/webmcp/declarative/opaque-origin-tools.https.html index 491a4cd1acf224..ffed048e6006ee 100644 --- a/webmcp/declarative/opaque-origin-tools.https.html +++ b/webmcp/declarative/opaque-origin-tools.https.html @@ -26,7 +26,7 @@ await promise_rejects_dom( t, 'NotSupportedError', - document.modelContext.executeTool(tool, '{"param1":"value"}'), + document.modelContext.executeTool(tool, {"param1":"value"}), 'executeTool() must reject with NotSupportedError in opaque origin documents' ); }, 'An opaque origin document can register but not execute its own declarative tools'); @@ -36,7 +36,7 @@ const tool = tools.find(t => t.name === 'opaque_tool'); let events = []; - const p = document.modelContext.executeTool(tool, '{}'); + const p = document.modelContext.executeTool(tool); // Since `executeTool()` synchronously rejects the Promise for opaque origins, // the microtask to run the catch reaction is already queued before @@ -49,7 +49,7 @@ await promise_rejects_dom( t, 'NotSupportedError', - document.modelContext.executeTool(tool, '{"param1":"value"}'), + document.modelContext.executeTool(tool, {"param1":"value"}), 'executeTool() must reject with NotSupportedError in opaque origin documents' ); diff --git a/webmcp/declarative/select-multiple-events.https.html b/webmcp/declarative/select-multiple-events.https.html index 613aba8cff53a7..0164174760fe68 100644 --- a/webmcp/declarative/select-multiple-events.https.html +++ b/webmcp/declarative/select-multiple-events.https.html @@ -37,10 +37,10 @@ changeEventCount++; }); - let inputArgs = JSON.stringify({ fruits: ['apple', 'banana'] }); + let inputObject = { fruits: ['apple', 'banana'] }; // This should dispatch events. - await document.modelContext.executeTool(tool, inputArgs); + await document.modelContext.executeTool(tool, inputObject); assert_true(fruits.options[0].selected); assert_false(fruits.options[1].selected); @@ -50,7 +50,7 @@ assert_equals(changeEventCount, 1); // Executing with the same arguments again does not trigger events. - await document.modelContext.executeTool(tool, inputArgs); + await document.modelContext.executeTool(tool, inputObject); assert_equals(inputEventCount, 1); assert_equals(changeEventCount, 1); diff --git a/webmcp/declarative/unregister-during-executeTool.https.html b/webmcp/declarative/unregister-during-executeTool.https.html index ff662f8980a90b..3ed0444ce15a0d 100644 --- a/webmcp/declarative/unregister-during-executeTool.https.html +++ b/webmcp/declarative/unregister-during-executeTool.https.html @@ -33,7 +33,7 @@ const tool = tools.find(t => t.name === 'endless_tool'); assert_true(!!tool, 'Tool should be registered'); - const execute_promise = document.modelContext.executeTool(tool, '{}'); + const execute_promise = document.modelContext.executeTool(tool); // Wait deterministically for the form to submit and call respondWith(). await submitted_promise; @@ -79,7 +79,7 @@ const tool = tools.find(t => t.name === 'endless_tool_attr'); assert_true(!!tool, 'Tool should be registered'); - const execute_promise = document.modelContext.executeTool(tool, '{}'); + const execute_promise = document.modelContext.executeTool(tool); // Wait deterministically for the form to submit and call respondWith(). await submitted_promise; diff --git a/webmcp/imperative/cancel-reentrancy-crash.https.html b/webmcp/imperative/cancel-reentrancy-crash.https.html index 7aac08f4befef6..82da4f25ca84c7 100644 --- a/webmcp/imperative/cancel-reentrancy-crash.https.html +++ b/webmcp/imperative/cancel-reentrancy-crash.https.html @@ -44,8 +44,8 @@ const regA = tools.find(t => t.name === 'toolA'); const regB = tools.find(t => t.name === 'toolB'); - document.modelContext.executeTool(regA, '{}', { signal: controllerA.signal }); - document.modelContext.executeTool(regB, '{}'); + document.modelContext.executeTool(regA, {}, { signal: controllerA.signal }); + document.modelContext.executeTool(regB); // Wait for both tool execute callbacks to run and return, ensuring they are // inserted into pending_executions_. diff --git a/webmcp/imperative/detached-frame-executeTool.https.html b/webmcp/imperative/detached-frame-executeTool.https.html index 6ae14e9fc9e31b..872ba33428f7ce 100644 --- a/webmcp/imperative/detached-frame-executeTool.https.html +++ b/webmcp/imperative/detached-frame-executeTool.https.html @@ -40,7 +40,7 @@ iframe.remove(); // Calling executeTool() should reject with InvalidStateError. - await promise_rejects_dom(t, 'InvalidStateError', iDOMException, iframe_modelContext.executeTool(tool, '{}')); + await promise_rejects_dom(t, 'InvalidStateError', iDOMException, iframe_modelContext.executeTool(tool)); }, 'executeTool() throws `InvalidStateError` in detached frame'); diff --git a/webmcp/imperative/executeTool-abort.https.html b/webmcp/imperative/executeTool-abort.https.html index c18b523adce64a..43d9f0bba0ede5 100644 --- a/webmcp/imperative/executeTool-abort.https.html +++ b/webmcp/imperative/executeTool-abort.https.html @@ -23,7 +23,7 @@ }, { signal: regController.signal }); const [tool] = await document.modelContext.getTools(); - const result = await document.modelContext.executeTool(tool, '{}'); + const result = await document.modelContext.executeTool(tool); assert_equals(result, 'success'); assert_true(received_signal instanceof AbortSignal, 'options.signal should be an AbortSignal instance'); assert_false(received_signal.aborted, 'signal should not be aborted'); @@ -63,7 +63,7 @@ const [tool] = await document.modelContext.getTools(); const controller = new AbortController(); - const executionPromise = document.modelContext.executeTool(tool, '{}', { signal: controller.signal }); + const executionPromise = document.modelContext.executeTool(tool, {}, { signal: controller.signal }); const { promise: toolCancelPromise, resolve: resolveToolCancel } = Promise.withResolvers(); window.addEventListener('toolcancel', e => { @@ -103,7 +103,7 @@ const [tool] = await document.modelContext.getTools(); const signal = AbortSignal.abort('already aborted'); let executionRejectionValue = null; - document.modelContext.executeTool(tool, '{}', { signal }).catch(e => executionRejectionValue = e); + document.modelContext.executeTool(tool, {}, { signal }).catch(e => executionRejectionValue = e); // Await a Promise that resolved synchronously, so that we guarantee that in // the next microtask, `execute_promise` has already rejected. This asserts @@ -133,7 +133,7 @@ const [tool] = await document.modelContext.getTools(); const controller = new AbortController(); const executePromise = - document.modelContext.executeTool(tool, '{}', { signal: controller.signal }); + document.modelContext.executeTool(tool, {}, { signal: controller.signal }); // By the time this `abort()` is processed, the tool will have already started // running and the abort handler will have already been registered. @@ -184,8 +184,8 @@ const c1 = new AbortController(); const c2 = new AbortController(); - const execPromise1 = document.modelContext.executeTool(tool, '{}', { signal: c1.signal }); - const execPromise2 = document.modelContext.executeTool(tool, '{}', { signal: c2.signal }); + const execPromise1 = document.modelContext.executeTool(tool, {}, { signal: c1.signal }); + const execPromise2 = document.modelContext.executeTool(tool, {}, { signal: c2.signal }); await Promise.all([exec1Started, exec2Started]); diff --git a/webmcp/imperative/executeTool-across-trees.https.html b/webmcp/imperative/executeTool-across-trees.https.html index a904c5e30bcab5..633e6fe69b5a1e 100644 --- a/webmcp/imperative/executeTool-across-trees.https.html +++ b/webmcp/imperative/executeTool-across-trees.https.html @@ -29,7 +29,7 @@ const [tool] = await windowB.document.modelContext.getTools(); assert_equals(tool.window, windowB); - const execute_promise = document.modelContext.executeTool(tool, '{}'); + const execute_promise = document.modelContext.executeTool(tool); await promise_rejects_dom(t, 'UnknownError', execute_promise); }, 'executeTool() rejects when the tool is hosted in another frame tree'); diff --git a/webmcp/imperative/executeTool-error-window-onerror.https.html b/webmcp/imperative/executeTool-error-window-onerror.https.html index a29449f2ce3fa7..4bd1282a9c033e 100644 --- a/webmcp/imperative/executeTool-error-window-onerror.https.html +++ b/webmcp/imperative/executeTool-error-window-onerror.https.html @@ -33,7 +33,7 @@ // `executeTool()` should reject since the tool execution failed. await promise_rejects_dom(t, 'UnknownError', - document.modelContext.executeTool(tool, '{}'), + document.modelContext.executeTool(tool), 'executeTool() rejects when the tool execution throws'); assert_false(errorFired, 'window.onerror/error event should not be fired'); @@ -66,7 +66,7 @@ // `executeTool()` should reject since serializing the return value throws a TypeError. await promise_rejects_dom(t, 'UnknownError', - document.modelContext.executeTool(tool, '{}'), + document.modelContext.executeTool(tool), 'executeTool() rejects when the tool execution returns a circular object'); assert_false(errorFired, 'window.onerror/error event should not be fired'); diff --git a/webmcp/imperative/executeTool-invalid-dictionary.https.html b/webmcp/imperative/executeTool-invalid-dictionary.https.html index dc43a9426e0d58..713d0af3158dd4 100644 --- a/webmcp/imperative/executeTool-invalid-dictionary.https.html +++ b/webmcp/imperative/executeTool-invalid-dictionary.https.html @@ -31,7 +31,7 @@ await promise_rejects_js( t, TypeError, - document.modelContext.executeTool(invalidTool, '{}'), + document.modelContext.executeTool(invalidTool), "executeTool() must reject with TypeError if 'origin' member is omitted" ); }, "executeTool() rejects with TypeError when the required 'origin' dictionary member is omitted"); @@ -47,13 +47,32 @@ const tool = tools.find(t => t.name === "json-test-tool"); assert_true(!!tool, "Legitimate tool must be successfully discovered"); - await promise_rejects_dom( + const circularObject = {}; + circularObject.self = circularObject; + await promise_rejects_js( t, - "UnknownError", - document.modelContext.executeTool(tool, "invalid-json"), - "executeTool() must reject with UnknownError for invalid JSON input" + TypeError, + document.modelContext.executeTool(tool, circularObject), + "executeTool() must reject with TypeError for circular JSON input" + ); + + const undefinedToJSON = { + toJSON: () => undefined + }; + await promise_rejects_js( + t, + TypeError, + document.modelContext.executeTool(tool, undefinedToJSON), + "executeTool() must reject with TypeError when toJSON returns undefined" + ); + + await promise_rejects_js( + t, + TypeError, + document.modelContext.executeTool(tool, BigInt(42)), + "executeTool() must reject with TypeError for non-serializable types JSON input" ); -}, "executeTool() rejects with UnknownError for invalid JSON arguments"); +}, "executeTool() rejects with TypeError for invalid JSON arguments"); promise_test(async t => { const dummyTool = { @@ -66,7 +85,7 @@ await promise_rejects_dom( t, "UnknownError", - document.modelContext.executeTool(dummyTool, "{}"), + document.modelContext.executeTool(dummyTool), "executeTool() must reject with UnknownError for non-existent tool object" ); }, "executeTool() rejects with UnknownError when a non-existent tool object is supplied"); diff --git a/webmcp/imperative/executeTool-signal-cross-origin.https.html b/webmcp/imperative/executeTool-signal-cross-origin.https.html index 655ef4b65ab32e..8425731549a566 100644 --- a/webmcp/imperative/executeTool-signal-cross-origin.https.html +++ b/webmcp/imperative/executeTool-signal-cross-origin.https.html @@ -60,7 +60,7 @@ t.add_cleanup(() => window.removeEventListener('message', message_handler)); const controller = new AbortController(); - const execute_promise = document.modelContext.executeTool(tool, '{}', { signal: controller.signal }); + const execute_promise = document.modelContext.executeTool(tool, {}, { signal: controller.signal }); await tool_started; controller.abort('parent cross-origin abort reason'); diff --git a/webmcp/imperative/executeTool-target-detachment.https.html b/webmcp/imperative/executeTool-target-detachment.https.html index 9b93fca8fec1b6..a962346eb6643f 100644 --- a/webmcp/imperative/executeTool-target-detachment.https.html +++ b/webmcp/imperative/executeTool-target-detachment.https.html @@ -54,7 +54,7 @@ await promise_rejects_dom( t, 'InvalidStateError', - document.modelContext.executeTool(tool, '{}'), + document.modelContext.executeTool(tool), 'Promise should be rejected with InvalidStateError when target frame is detached before execution' ); }, 'executeTool() rejects when target frame is detached before execution'); @@ -95,7 +95,7 @@ assert_true(!!tool, 'Tool should be retrieved successfully'); // Execute the tool (hangs forever). - const execute_promise = document.modelContext.executeTool(tool, '{}'); + const execute_promise = document.modelContext.executeTool(tool); iframe.remove(); diff --git a/webmcp/imperative/executeTool-target-navigation.https.html b/webmcp/imperative/executeTool-target-navigation.https.html index bbbc59f9cbe125..e9916447a3e378 100644 --- a/webmcp/imperative/executeTool-target-navigation.https.html +++ b/webmcp/imperative/executeTool-target-navigation.https.html @@ -40,7 +40,7 @@ // Invoke tool and immediately navigate iframe away. const tools = await document.modelContext.getTools(); const tool = tools.find(t => t.name === 'iframe_tool'); - const promise = document.modelContext.executeTool(tool, '{}'); + const promise = document.modelContext.executeTool(tool); iframe.src = 'about:blank'; // The promise should be rejected because the target document died. diff --git a/webmcp/imperative/executeTool-unauthorized-origin.https.html b/webmcp/imperative/executeTool-unauthorized-origin.https.html index 7c07a14f365065..f0f14ebb5ab4b8 100644 --- a/webmcp/imperative/executeTool-unauthorized-origin.https.html +++ b/webmcp/imperative/executeTool-unauthorized-origin.https.html @@ -54,7 +54,7 @@ }; // Parent attempts to execute the unexposed tool directly. This should reject with UnknownError. - const promise = document.modelContext.executeTool(fake_tool, '{}'); + const promise = document.modelContext.executeTool(fake_tool); await promise_rejects_dom(t, 'UnknownError', promise, 'executeTool should reject with UnknownError when parent is not authorized to execute the iframe tool'); }, 'executeTool() rejects when parent frame attempts unauthorized execution of cross-origin iframe tool'); diff --git a/webmcp/imperative/executeTool-unregister-resolution-race.https.html b/webmcp/imperative/executeTool-unregister-resolution-race.https.html index 85619287676c88..32acc2765eeb7e 100644 --- a/webmcp/imperative/executeTool-unregister-resolution-race.https.html +++ b/webmcp/imperative/executeTool-unregister-resolution-race.https.html @@ -30,7 +30,7 @@ }, {signal: ac.signal}); const [tool] = await document.modelContext.getTools(); - const execute_promise = document.modelContext.executeTool(tool, '{}'); + const execute_promise = document.modelContext.executeTool(tool); const result = await execute_promise; assert_equals(result, '{"status":"resolved"}'); diff --git a/webmcp/imperative/exposedTo-cross-origin-child.https.html b/webmcp/imperative/exposedTo-cross-origin-child.https.html index c2fcda8204bc8b..61f4905fba298b 100644 --- a/webmcp/imperative/exposedTo-cross-origin-child.https.html +++ b/webmcp/imperative/exposedTo-cross-origin-child.https.html @@ -109,7 +109,7 @@ }), 'Tool details should match'); // Parent executes iframe's tool. - const result = await document.modelContext.executeTool(tool, '{}'); + const result = await document.modelContext.executeTool(tool); assert_equals(result, 'hello from iframe', 'Parent should get correct result from iframe tool'); // Tell the iframe to unregister its tool, and confirm that `toolchange` fires here. diff --git a/webmcp/imperative/exposedTo-defaults-same-origin.https.html b/webmcp/imperative/exposedTo-defaults-same-origin.https.html index db91516725cf13..92bb2465a84e3e 100644 --- a/webmcp/imperative/exposedTo-defaults-same-origin.https.html +++ b/webmcp/imperative/exposedTo-defaults-same-origin.https.html @@ -143,7 +143,7 @@ }), 'Tool details should match'); // Parent executes iframe's tool. - const result = await document.modelContext.executeTool(tool, '{}'); + const result = await document.modelContext.executeTool(tool); assert_equals(result, 'hello from iframe', 'Parent should get correct result from iframe tool'); // Unregister tool. @@ -182,7 +182,7 @@ }), 'Tool details should match'); // Parent executes iframe's tool. - const result = await document.modelContext.executeTool(tool, '{}'); + const result = await document.modelContext.executeTool(tool); assert_equals(result, 'hello from iframe', 'Parent should get correct result from iframe tool'); // Unregister tool. diff --git a/webmcp/imperative/exposedTo-invalid-origins.https.html b/webmcp/imperative/exposedTo-invalid-origins.https.html index 80927e046c4e32..42235a94897ff3 100644 --- a/webmcp/imperative/exposedTo-invalid-origins.https.html +++ b/webmcp/imperative/exposedTo-invalid-origins.https.html @@ -90,7 +90,7 @@ // 6. Execute the cached RegisteredTool. // This must execute callback2 and resolve to 'callback2', not callback3. - const result = await document.modelContext.executeTool(tool, '{}'); + const result = await document.modelContext.executeTool(tool); assert_equals(result, 'callback2', 'Executing the cached RegisteredTool must run callback2'); }, 'Aborting a signal from a rejected registration must not unregister a later valid tool with the same name'); diff --git a/webmcp/imperative/object-arguments.https.html b/webmcp/imperative/object-arguments.https.html index 54247f115f49f3..003068ad95710c 100644 --- a/webmcp/imperative/object-arguments.https.html +++ b/webmcp/imperative/object-arguments.https.html @@ -19,30 +19,46 @@ const [registeredTool] = await document.modelContext.getTools(); // Pass an array. Since arrays are ECMAScript objects, this succeeds. - const arrayArgs = `[1, 2, 3]`; + const arrayArgs = [1, 2, 3]; const result = await document.modelContext.executeTool(registeredTool, arrayArgs); assert_equals(result, "Success"); assert_array_equals(executeReceivedArgs, [1, 2, 3]); // Now pass non-Object JSON primitives as the argument, and observe a failure. - const stringArgs = `"hello"`; - await promise_rejects_dom(t, "UnknownError", + const stringArgs = "hello"; + await promise_rejects_js(t, TypeError, document.modelContext.executeTool(registeredTool, stringArgs), "Primitive string should be rejected"); - const numberArgs = `123`; - await promise_rejects_dom(t, "UnknownError", + const numberArgs = 123; + await promise_rejects_js(t, TypeError, document.modelContext.executeTool(registeredTool, numberArgs), "Primitive number should be rejected"); - const booleanArgs = `true`; - await promise_rejects_dom(t, "UnknownError", + const booleanArgs = true; + await promise_rejects_js(t, TypeError, document.modelContext.executeTool(registeredTool, booleanArgs), "Primitive boolean should be rejected"); - const nullArgs = `null`; - await promise_rejects_dom(t, "UnknownError", + const nullArgs = null; + await promise_rejects_js(t, TypeError, document.modelContext.executeTool(registeredTool, nullArgs), "null should be rejected"); + + const undefinedArgs = null; + await promise_rejects_js(t, TypeError, + document.modelContext.executeTool(registeredTool, undefinedArgs), + "undefined should be rejected"); + + // Pass an object whose toJSON() method returns undefined, and observe + // a failure. + const nullishObject = { toJSON: () => undefined }; + await promise_rejects_js(t, TypeError, + document.modelContext.executeTool(registeredTool, nullishObject), + "Object whose toJSON() returns undefined should be rejected"); + // Omitting input argument defaults to {} + const defaultResult = await document.modelContext.executeTool(registeredTool); + assert_equals(defaultResult, "Success"); + assert_object_equals(executeReceivedArgs, {}); }, "tool execution requires a JSON Object input argument; and Arrays are Objects"); diff --git a/webmcp/imperative/opaque-origin-tools.https.html b/webmcp/imperative/opaque-origin-tools.https.html index 4c5e29b098a06c..549c0cd1d92416 100644 --- a/webmcp/imperative/opaque-origin-tools.https.html +++ b/webmcp/imperative/opaque-origin-tools.https.html @@ -26,7 +26,7 @@ await promise_rejects_dom( t, 'NotSupportedError', - document.modelContext.executeTool(tool, '{}'), + document.modelContext.executeTool(tool), 'executeTool() must reject with NotSupportedError in opaque origin documents' ); }, 'An opaque origin document can register but not execute its own tools'); @@ -49,7 +49,7 @@ assert_equals(tool.origin, "null", "getTools() gives"); let events = []; - const p = document.modelContext.executeTool(tool, '{}'); + const p = document.modelContext.executeTool(tool); // Since `executeTool()` synchronously rejects the Promise for opaque origins, // the microtask to run the catch reaction is already queued before @@ -62,7 +62,7 @@ await promise_rejects_dom( t, 'NotSupportedError', - document.modelContext.executeTool(tool, '{"param1":"value"}'), + document.modelContext.executeTool(tool, {"param1":"value"}), 'executeTool() must reject with NotSupportedError in opaque origin documents' ); @@ -81,7 +81,7 @@ }; let events = []; - const p = document.modelContext.executeTool(fake_tool, '{}'); + const p = document.modelContext.executeTool(fake_tool); p.catch(() => events.push('rejection')); // Queue another microtask immediately after. @@ -90,7 +90,7 @@ await promise_rejects_dom( t, 'NotSupportedError', - document.modelContext.executeTool(fake_tool, '{"param1":"value"}')); + document.modelContext.executeTool(fake_tool, {"param1":"value"})); assert_array_equals(events, ['rejection', 'microtask'], 'returned promise is rejected before custom microtask is queued'); diff --git a/webmcp/imperative/register_tool_invalid_json_schema.https.html b/webmcp/imperative/register_tool_invalid_json_schema.https.html index 5e353248ac3ebc..3182f028315ce8 100644 --- a/webmcp/imperative/register_tool_invalid_json_schema.https.html +++ b/webmcp/imperative/register_tool_invalid_json_schema.https.html @@ -8,7 +8,7 @@ diff --git a/webmcp/imperative/resources/iframe-caller-and-target-crash.html b/webmcp/imperative/resources/iframe-caller-and-target-crash.html index 2f52500addd696..5ceaa1a9b1d0a6 100644 --- a/webmcp/imperative/resources/iframe-caller-and-target-crash.html +++ b/webmcp/imperative/resources/iframe-caller-and-target-crash.html @@ -11,7 +11,7 @@ }); const tools = await document.modelContext.getTools(); const tool = tools.find(t => t.name === "test_tool"); - document.modelContext.executeTool(tool, "{}"); + document.modelContext.executeTool(tool); } run(); diff --git a/webmcp/imperative/resources/iframe-caller.html b/webmcp/imperative/resources/iframe-caller.html index 602b23d903c636..f44ebfe031f329 100644 --- a/webmcp/imperative/resources/iframe-caller.html +++ b/webmcp/imperative/resources/iframe-caller.html @@ -11,7 +11,7 @@ const options = e.data.options || {}; document.modelContext.getTools(options).then(tools => { const tool = tools.find(t => t.name === e.data.name); - document.modelContext.executeTool(tool, '{}').then(result => { + document.modelContext.executeTool(tool).then(result => { parent.postMessage({action: 'executeResponse', result: result, success: true}, '*'); }).catch(err => { parent.postMessage({action: 'executeResponse', result: String(err), success: false}, '*'); @@ -22,7 +22,7 @@ const controller = new AbortController(); document.modelContext.getTools(options).then(tools => { const tool = tools.find(t => t.name === e.data.name); - document.modelContext.executeTool(tool, '{}', { signal: controller.signal }).then(result => { + document.modelContext.executeTool(tool, {}, { signal: controller.signal }).then(result => { parent.postMessage({action: 'executeResponse', result: result, success: true}, '*'); }).catch(err => { parent.postMessage({action: 'executeResponse', result: String(err), success: false}, '*'); diff --git a/webmcp/imperative/resources/iframe-register-tool.html b/webmcp/imperative/resources/iframe-register-tool.html index f977a6d93f8cf2..759712e1f4eccc 100644 --- a/webmcp/imperative/resources/iframe-register-tool.html +++ b/webmcp/imperative/resources/iframe-register-tool.html @@ -91,7 +91,7 @@ }); } else if (action === 'execute') { const name = e.data.name; - const args = e.data.args || '{}'; + const args = e.data.args || {}; const options = e.data.options || {}; document.modelContext.getTools(options).then(tools => { const tool = tools.find(t => t.name === name); @@ -108,7 +108,7 @@ window: window, origin: self.origin }; - document.modelContext.executeTool(fake_tool, '{}').then(result => { + document.modelContext.executeTool(fake_tool).then(result => { parent.postMessage({action: 'executeFakeToolResponse', result: result, success: true}, '*'); }).catch(err => { parent.postMessage({action: 'executeFakeToolResponse', result: String(err), success: false, error_name: err.name}, '*'); diff --git a/webmcp/imperative/unregister-during-executeTool.https.html b/webmcp/imperative/unregister-during-executeTool.https.html index c23bf779a7e380..5ee502ef6bd010 100644 --- a/webmcp/imperative/unregister-during-executeTool.https.html +++ b/webmcp/imperative/unregister-during-executeTool.https.html @@ -53,7 +53,7 @@ // 2. Run the tool, and wait for the iframe to report back that execution has // begun. - const executePromise = document.modelContext.executeTool(tool, '{}'); + const executePromise = document.modelContext.executeTool(tool); await toolStartedPromise; // Before we tell the iframe to unregister the tool, set up a handler to @@ -103,7 +103,7 @@ }, { signal: regController.signal }); const [tool] = await document.modelContext.getTools(); - const executePromise = document.modelContext.executeTool(tool, '{}'); + const executePromise = document.modelContext.executeTool(tool); await toolStartedPromise;