@@ -8,8 +8,10 @@ import assert from 'node:assert';
88import { describe , it } from 'node:test' ;
99
1010import type { ParsedArguments } from '../../src/bin/chrome-devtools-mcp-cli-options.js' ;
11+ import type { McpContext } from '../../src/McpContext.js' ;
12+ import type { McpResponse } from '../../src/McpResponse.js' ;
1113import type { ToolGroup , ToolDefinition } from '../../src/tools/inPage.js' ;
12- import { listInPageTools } from '../../src/tools/inPage.js' ;
14+ import { executeInPageTool , listInPageTools } from '../../src/tools/inPage.js' ;
1315import { withMcpContext } from '../utils.js' ;
1416
1517describe ( 'inPage' , ( ) => {
@@ -145,4 +147,200 @@ describe('inPage', () => {
145147 ) ;
146148 } ) ;
147149 } ) ;
150+
151+ describe ( 'execute_in_page_tool' , ( ) => {
152+ async function setupInPageTools (
153+ response : McpResponse ,
154+ context : McpContext ,
155+ evaluateFn : ( ) => void ,
156+ ) {
157+ const page = await context . newPage ( ) ;
158+ await page . pptrPage . evaluate ( evaluateFn ) ;
159+ await listInPageTools . handler ( { params : { } , page} , response , context ) ;
160+ await response . handle ( 'list_in_page_tools' , context ) ;
161+ }
162+
163+ it ( 'executes a tool' , async ( ) => {
164+ await withMcpContext (
165+ async ( response , context ) => {
166+ await setupInPageTools ( response , context , ( ) => {
167+ window . __dtmcp = {
168+ toolGroup : {
169+ name : 'test-group' ,
170+ description : 'test description' ,
171+ tools : [
172+ {
173+ name : 'test-tool' ,
174+ description : 'test tool description' ,
175+ inputSchema : {
176+ type : 'object' ,
177+ properties : {
178+ arg : { type : 'string' } ,
179+ } ,
180+ required : [ 'arg' ] ,
181+ } ,
182+ execute : ( ) => 'result' ,
183+ } ,
184+ ] ,
185+ } ,
186+ } ;
187+ window . addEventListener ( 'devtoolstooldiscovery' , ( e : Event ) => {
188+ // @ts -expect-error Event has `respondWith`
189+ e . respondWith ( window . __dtmcp ?. toolGroup ) ;
190+ } ) ;
191+ } ) ;
192+
193+ await executeInPageTool . handler (
194+ {
195+ params : {
196+ toolName : 'test-tool' ,
197+ params : { arg : 'value' } ,
198+ } ,
199+ page : context . getSelectedMcpPage ( ) ,
200+ } ,
201+ response ,
202+ context ,
203+ ) ;
204+ assert . strictEqual (
205+ response . responseLines [ 0 ] ,
206+ JSON . stringify ( { result : 'result' } , null , 2 ) ,
207+ ) ;
208+ } ,
209+ undefined ,
210+ { categoryInPageTools : true } as ParsedArguments ,
211+ ) ;
212+ } ) ;
213+
214+ it ( 'throws if tool not found in list' , async ( ) => {
215+ await withMcpContext ( async ( response , context ) => {
216+ await setupInPageTools ( response , context , ( ) => {
217+ window . __dtmcp = {
218+ toolGroup : {
219+ name : 'test-group' ,
220+ description : 'test description' ,
221+ tools : [ ] ,
222+ } ,
223+ } ;
224+ window . addEventListener ( 'devtoolstooldiscovery' , ( e : Event ) => {
225+ // @ts -expect-error Event has `respondWith`
226+ e . respondWith ( window . __dtmcp ?. toolGroup ) ;
227+ } ) ;
228+ } ) ;
229+
230+ await assert . rejects (
231+ async ( ) => {
232+ await executeInPageTool . handler (
233+ {
234+ params : {
235+ toolName : 'missing-tool' ,
236+ params : { } ,
237+ } ,
238+ page : context . getSelectedMcpPage ( ) ,
239+ } ,
240+ response ,
241+ context ,
242+ ) ;
243+ } ,
244+ { message : / T o o l m i s s i n g - t o o l n o t f o u n d / } ,
245+ ) ;
246+ } ) ;
247+ } ) ;
248+
249+ it ( 'throws if parameters are invalid' , async ( ) => {
250+ await withMcpContext (
251+ async ( response , context ) => {
252+ await setupInPageTools ( response , context , ( ) => {
253+ window . __dtmcp = {
254+ toolGroup : {
255+ name : 'test-group' ,
256+ description : 'test description' ,
257+ tools : [
258+ {
259+ name : 'test-tool' ,
260+ description : 'test tool description' ,
261+ inputSchema : {
262+ type : 'object' ,
263+ properties : {
264+ arg : { type : 'string' } ,
265+ } ,
266+ required : [ 'arg' ] ,
267+ } ,
268+ execute : ( ) => 'result' ,
269+ } ,
270+ ] ,
271+ } ,
272+ } ;
273+ window . addEventListener ( 'devtoolstooldiscovery' , ( e : Event ) => {
274+ // @ts -expect-error Event has `respondWith`
275+ e . respondWith ( window . __dtmcp ?. toolGroup ) ;
276+ } ) ;
277+ } ) ;
278+
279+ await assert . rejects (
280+ async ( ) => {
281+ await executeInPageTool . handler (
282+ {
283+ params : {
284+ toolName : 'test-tool' ,
285+ params : { } , // Missing required 'arg'
286+ } ,
287+ page : context . getSelectedMcpPage ( ) ,
288+ } ,
289+ response ,
290+ context ,
291+ ) ;
292+ } ,
293+ { message : / I n v a l i d p a r a m e t e r s f o r t o o l t e s t - t o o l / } ,
294+ ) ;
295+ } ,
296+ undefined ,
297+ { categoryInPageTools : true } as ParsedArguments ,
298+ ) ;
299+ } ) ;
300+
301+ it ( 'handles JSON result' , async ( ) => {
302+ await withMcpContext (
303+ async ( response , context ) => {
304+ await setupInPageTools ( response , context , ( ) => {
305+ window . __dtmcp = {
306+ toolGroup : {
307+ name : 'test-group' ,
308+ description : 'test description' ,
309+ tools : [
310+ {
311+ name : 'test-tool' ,
312+ description : 'test tool description' ,
313+ inputSchema : { } ,
314+ execute : ( ) => ( { foo : 'bar' } ) ,
315+ } ,
316+ ] ,
317+ } ,
318+ } ;
319+ window . addEventListener ( 'devtoolstooldiscovery' , ( e : Event ) => {
320+ // @ts -expect-error Event has `respondWith`
321+ e . respondWith ( window . __dtmcp ?. toolGroup ) ;
322+ } ) ;
323+ } ) ;
324+
325+ await executeInPageTool . handler (
326+ {
327+ params : {
328+ toolName : 'test-tool' ,
329+ params : { } ,
330+ } ,
331+ page : context . getSelectedMcpPage ( ) ,
332+ } ,
333+ response ,
334+ context ,
335+ ) ;
336+ assert . strictEqual (
337+ response . responseLines [ 0 ] ,
338+ JSON . stringify ( { result : { foo : 'bar' } } , null , 2 ) ,
339+ ) ;
340+ } ,
341+ undefined ,
342+ { categoryInPageTools : true } as ParsedArguments ,
343+ ) ;
344+ } ) ;
345+ } ) ;
148346} ) ;
0 commit comments