opera-devtools-mcp 0.4.2 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -205,15 +205,21 @@ If you run into any issues, checkout our [troubleshooting guide](./docs/troubles
|
|
|
205
205
|
- [`get_heapsnapshot_retainers`](docs/tool-reference.md#get_heapsnapshot_retainers)
|
|
206
206
|
- [`get_heapsnapshot_retaining_paths`](docs/tool-reference.md#get_heapsnapshot_retaining_paths)
|
|
207
207
|
- [`get_heapsnapshot_summary`](docs/tool-reference.md#get_heapsnapshot_summary)
|
|
208
|
-
- **Opera** (
|
|
208
|
+
- **Opera** (14 tools)
|
|
209
|
+
- [`opera_authenticate_mcp_server`](docs/tool-reference.md#opera_authenticate_mcp_server)
|
|
209
210
|
- [`opera_call_mcp_tool`](docs/tool-reference.md#opera_call_mcp_tool)
|
|
210
211
|
- [`opera_chat`](docs/tool-reference.md#opera_chat)
|
|
212
|
+
- [`opera_connect_mcp_server`](docs/tool-reference.md#opera_connect_mcp_server)
|
|
213
|
+
- [`opera_disable_mcp_server`](docs/tool-reference.md#opera_disable_mcp_server)
|
|
211
214
|
- [`opera_do`](docs/tool-reference.md#opera_do)
|
|
215
|
+
- [`opera_enable_mcp_server`](docs/tool-reference.md#opera_enable_mcp_server)
|
|
212
216
|
- [`opera_list_mcp_servers`](docs/tool-reference.md#opera_list_mcp_servers)
|
|
213
217
|
- [`opera_list_mcp_tools`](docs/tool-reference.md#opera_list_mcp_tools)
|
|
214
218
|
- [`opera_list_models`](docs/tool-reference.md#opera_list_models)
|
|
215
219
|
- [`opera_make`](docs/tool-reference.md#opera_make)
|
|
220
|
+
- [`opera_register_mcp_server`](docs/tool-reference.md#opera_register_mcp_server)
|
|
216
221
|
- [`opera_research`](docs/tool-reference.md#opera_research)
|
|
222
|
+
- [`opera_unregister_mcp_server`](docs/tool-reference.md#opera_unregister_mcp_server)
|
|
217
223
|
- **Extensions** (5 tools)
|
|
218
224
|
- [`install_extension`](docs/tool-reference.md#install_extension)
|
|
219
225
|
- [`list_extensions`](docs/tool-reference.md#list_extensions)
|
|
@@ -898,6 +898,18 @@ export const commands = {
|
|
|
898
898
|
},
|
|
899
899
|
},
|
|
900
900
|
},
|
|
901
|
+
opera_authenticate_mcp_server: {
|
|
902
|
+
description: 'Complete OAuth sign-in for an MCP server that requires authentication. Opens a browser popup for the OAuth flow; requires a headed (visible) browser. Only available when connected to Opera Neon.',
|
|
903
|
+
category: 'Opera',
|
|
904
|
+
args: {
|
|
905
|
+
server: {
|
|
906
|
+
name: 'server',
|
|
907
|
+
type: 'string',
|
|
908
|
+
description: 'The MCP server name to authenticate.',
|
|
909
|
+
required: true,
|
|
910
|
+
},
|
|
911
|
+
},
|
|
912
|
+
},
|
|
901
913
|
opera_call_mcp_tool: {
|
|
902
914
|
description: 'Execute a tool on a specific MCP server registered in the browser. Use opera_list_mcp_servers to discover available servers and tools. Only available when connected to Opera Neon.',
|
|
903
915
|
category: 'Opera',
|
|
@@ -938,6 +950,36 @@ export const commands = {
|
|
|
938
950
|
description: 'Model ID to use for the chat. Omit to use the browser default. Use opera_list_models to discover available IDs.',
|
|
939
951
|
required: false,
|
|
940
952
|
},
|
|
953
|
+
conversationId: {
|
|
954
|
+
name: 'conversationId',
|
|
955
|
+
type: 'string',
|
|
956
|
+
description: 'Conversation ID to continue an existing conversation. Omit to start a new conversation.',
|
|
957
|
+
required: false,
|
|
958
|
+
},
|
|
959
|
+
},
|
|
960
|
+
},
|
|
961
|
+
opera_connect_mcp_server: {
|
|
962
|
+
description: 'Connect to a registered MCP server. If the server requires OAuth, the response includes requiresAuth: "needed" — follow with opera_authenticate_mcp_server. Only available when connected to Opera Neon.',
|
|
963
|
+
category: 'Opera',
|
|
964
|
+
args: {
|
|
965
|
+
server: {
|
|
966
|
+
name: 'server',
|
|
967
|
+
type: 'string',
|
|
968
|
+
description: 'The MCP server name to connect.',
|
|
969
|
+
required: true,
|
|
970
|
+
},
|
|
971
|
+
},
|
|
972
|
+
},
|
|
973
|
+
opera_disable_mcp_server: {
|
|
974
|
+
description: 'Disable an MCP server without unregistering it. Only available when connected to Opera Neon.',
|
|
975
|
+
category: 'Opera',
|
|
976
|
+
args: {
|
|
977
|
+
server: {
|
|
978
|
+
name: 'server',
|
|
979
|
+
type: 'string',
|
|
980
|
+
description: 'The MCP server name to disable.',
|
|
981
|
+
required: true,
|
|
982
|
+
},
|
|
941
983
|
},
|
|
942
984
|
},
|
|
943
985
|
opera_do: {
|
|
@@ -952,6 +994,18 @@ export const commands = {
|
|
|
952
994
|
},
|
|
953
995
|
},
|
|
954
996
|
},
|
|
997
|
+
opera_enable_mcp_server: {
|
|
998
|
+
description: 'Enable a disabled MCP server. Only available when connected to Opera Neon.',
|
|
999
|
+
category: 'Opera',
|
|
1000
|
+
args: {
|
|
1001
|
+
server: {
|
|
1002
|
+
name: 'server',
|
|
1003
|
+
type: 'string',
|
|
1004
|
+
description: 'The MCP server name to enable.',
|
|
1005
|
+
required: true,
|
|
1006
|
+
},
|
|
1007
|
+
},
|
|
1008
|
+
},
|
|
955
1009
|
opera_list_mcp_servers: {
|
|
956
1010
|
description: 'List MCP servers registered in the browser, including their connection status. Only available when connected to Opera Neon.',
|
|
957
1011
|
category: 'Opera',
|
|
@@ -986,6 +1040,24 @@ export const commands = {
|
|
|
986
1040
|
},
|
|
987
1041
|
},
|
|
988
1042
|
},
|
|
1043
|
+
opera_register_mcp_server: {
|
|
1044
|
+
description: 'Register an MCP server in the browser. Does not connect or authenticate — follow with opera_connect_mcp_server. Only available when connected to Opera Neon.',
|
|
1045
|
+
category: 'Opera',
|
|
1046
|
+
args: {
|
|
1047
|
+
server: {
|
|
1048
|
+
name: 'server',
|
|
1049
|
+
type: 'string',
|
|
1050
|
+
description: 'The MCP server name to register.',
|
|
1051
|
+
required: true,
|
|
1052
|
+
},
|
|
1053
|
+
url: {
|
|
1054
|
+
name: 'url',
|
|
1055
|
+
type: 'string',
|
|
1056
|
+
description: 'The HTTP URL of the MCP server.',
|
|
1057
|
+
required: true,
|
|
1058
|
+
},
|
|
1059
|
+
},
|
|
1060
|
+
},
|
|
989
1061
|
opera_research: {
|
|
990
1062
|
description: "Ask Opera's built-in AI to research a topic and return a summary. Only available when connected to Opera Neon.",
|
|
991
1063
|
category: 'Opera',
|
|
@@ -1005,6 +1077,18 @@ export const commands = {
|
|
|
1005
1077
|
},
|
|
1006
1078
|
},
|
|
1007
1079
|
},
|
|
1080
|
+
opera_unregister_mcp_server: {
|
|
1081
|
+
description: 'Remove a registered MCP server and its stored auth tokens. Only available when connected to Opera Neon.',
|
|
1082
|
+
category: 'Opera',
|
|
1083
|
+
args: {
|
|
1084
|
+
server: {
|
|
1085
|
+
name: 'server',
|
|
1086
|
+
type: 'string',
|
|
1087
|
+
description: 'The MCP server name to unregister.',
|
|
1088
|
+
required: true,
|
|
1089
|
+
},
|
|
1090
|
+
},
|
|
1091
|
+
},
|
|
1008
1092
|
performance_analyze_insight: {
|
|
1009
1093
|
description: 'Provides more detailed information on a specific Performance Insight of an insight set that was highlighted in the results of a trace recording.',
|
|
1010
1094
|
category: 'Performance',
|
|
@@ -71,9 +71,13 @@ export const operaChat = definePageTool({
|
|
|
71
71
|
.string()
|
|
72
72
|
.optional()
|
|
73
73
|
.describe('Model ID to use for the chat. Omit to use the browser default. Use opera_list_models to discover available IDs.'),
|
|
74
|
+
conversationId: zod
|
|
75
|
+
.string()
|
|
76
|
+
.optional()
|
|
77
|
+
.describe('Conversation ID to continue an existing conversation. Omit to start a new conversation.'),
|
|
74
78
|
},
|
|
75
79
|
handler: async (request, response) => {
|
|
76
|
-
//
|
|
80
|
+
// puppeteer's _client() is internal; cast to the shape getCDPSession needs
|
|
77
81
|
const session = getCDPSession(request.page.pptrPage);
|
|
78
82
|
try {
|
|
79
83
|
const payload = {
|
|
@@ -83,6 +87,9 @@ export const operaChat = definePageTool({
|
|
|
83
87
|
if (request.params.model !== undefined) {
|
|
84
88
|
payload['model'] = request.params.model;
|
|
85
89
|
}
|
|
90
|
+
if (request.params.conversationId !== undefined) {
|
|
91
|
+
payload['conversationId'] = request.params.conversationId;
|
|
92
|
+
}
|
|
86
93
|
const result = await dispatchAction(session, payload);
|
|
87
94
|
response.appendResponseLine(result);
|
|
88
95
|
}
|
|
@@ -106,7 +113,7 @@ export const operaDo = definePageTool({
|
|
|
106
113
|
.describe('The action to perform, described in natural language.'),
|
|
107
114
|
},
|
|
108
115
|
handler: async (request, response) => {
|
|
109
|
-
//
|
|
116
|
+
// puppeteer's _client() is internal; cast to the shape getCDPSession needs
|
|
110
117
|
const session = getCDPSession(request.page.pptrPage);
|
|
111
118
|
try {
|
|
112
119
|
const result = await dispatchWithStreamedResponse(session, {
|
|
@@ -136,7 +143,7 @@ export const operaMake = definePageTool({
|
|
|
136
143
|
prompt: zod.string().describe('Description of what to create or generate.'),
|
|
137
144
|
},
|
|
138
145
|
handler: async (request, response) => {
|
|
139
|
-
//
|
|
146
|
+
// puppeteer's _client() is internal; cast to the shape getCDPSession needs
|
|
140
147
|
const session = getCDPSession(request.page.pptrPage);
|
|
141
148
|
try {
|
|
142
149
|
const result = await dispatchAction(session, {
|
|
@@ -167,7 +174,7 @@ export const operaResearch = definePageTool({
|
|
|
167
174
|
.describe('Depth of research. "local" uses only on-page context, "one-minute" performs a quick web search, "deep" performs a thorough multi-source search.'),
|
|
168
175
|
},
|
|
169
176
|
handler: async (request, response) => {
|
|
170
|
-
//
|
|
177
|
+
// puppeteer's _client() is internal; cast to the shape getCDPSession needs
|
|
171
178
|
const session = getCDPSession(request.page.pptrPage);
|
|
172
179
|
const payload = {
|
|
173
180
|
action: 'research',
|
|
@@ -199,7 +206,7 @@ export const operaListModels = definePageTool({
|
|
|
199
206
|
},
|
|
200
207
|
schema: {},
|
|
201
208
|
handler: async (request, response) => {
|
|
202
|
-
//
|
|
209
|
+
// puppeteer's _client() is internal; cast to the shape getCDPSession needs
|
|
203
210
|
const session = getCDPSession(request.page.pptrPage);
|
|
204
211
|
try {
|
|
205
212
|
const result = await dispatchAction(session, { action: 'listModels' });
|
|
@@ -223,7 +230,7 @@ export const operaListMcpServers = definePageTool({
|
|
|
223
230
|
},
|
|
224
231
|
schema: {},
|
|
225
232
|
handler: async (request, response) => {
|
|
226
|
-
//
|
|
233
|
+
// puppeteer's _client() is internal; cast to the shape getCDPSession needs
|
|
227
234
|
const session = getCDPSession(request.page.pptrPage);
|
|
228
235
|
try {
|
|
229
236
|
const result = await dispatchAction(session, {
|
|
@@ -255,7 +262,7 @@ export const operaListMcpTools = definePageTool({
|
|
|
255
262
|
.describe('The MCP server name (from opera_list_mcp_servers).'),
|
|
256
263
|
},
|
|
257
264
|
handler: async (request, response) => {
|
|
258
|
-
//
|
|
265
|
+
// puppeteer's _client() is internal; cast to the shape getCDPSession needs
|
|
259
266
|
const session = getCDPSession(request.page.pptrPage);
|
|
260
267
|
try {
|
|
261
268
|
const result = await dispatchAction(session, {
|
|
@@ -297,7 +304,7 @@ export const operaCallMcpTool = definePageTool({
|
|
|
297
304
|
.describe('Parameters to pass to the tool. Omit if the tool takes none.'),
|
|
298
305
|
},
|
|
299
306
|
handler: async (request, response) => {
|
|
300
|
-
//
|
|
307
|
+
// puppeteer's _client() is internal; cast to the shape getCDPSession needs
|
|
301
308
|
const session = getCDPSession(request.page.pptrPage);
|
|
302
309
|
try {
|
|
303
310
|
const payload = {
|
|
@@ -320,4 +327,182 @@ export const operaCallMcpTool = definePageTool({
|
|
|
320
327
|
}
|
|
321
328
|
},
|
|
322
329
|
});
|
|
330
|
+
export const operaRegisterMcpServer = definePageTool({
|
|
331
|
+
name: 'opera_register_mcp_server',
|
|
332
|
+
description: 'Register an MCP server in the browser. Does not connect or authenticate — ' +
|
|
333
|
+
'follow with opera_connect_mcp_server. Only available when connected to Opera Neon.',
|
|
334
|
+
blockedByDialog: false,
|
|
335
|
+
verifyFilesSchema: {},
|
|
336
|
+
annotations: {
|
|
337
|
+
category: ToolCategory.OPERA,
|
|
338
|
+
readOnlyHint: false,
|
|
339
|
+
},
|
|
340
|
+
schema: {
|
|
341
|
+
server: zod.string().min(1).describe('The MCP server name to register.'),
|
|
342
|
+
url: zod.string().min(1).describe('The HTTP URL of the MCP server.'),
|
|
343
|
+
},
|
|
344
|
+
handler: async (request, response) => {
|
|
345
|
+
// puppeteer's _client() is internal; cast to the shape getCDPSession needs
|
|
346
|
+
const session = getCDPSession(request.page.pptrPage);
|
|
347
|
+
try {
|
|
348
|
+
const result = await dispatchAction(session, {
|
|
349
|
+
action: 'registerMcpServer',
|
|
350
|
+
type: 'REGISTER_SERVER',
|
|
351
|
+
server: request.params.server,
|
|
352
|
+
transportInfo: { type: 'http', url: request.params.url },
|
|
353
|
+
});
|
|
354
|
+
response.appendResponseLine(result);
|
|
355
|
+
}
|
|
356
|
+
catch (e) {
|
|
357
|
+
response.appendResponseLine(`Opera.dispatchAction(registerMcpServer) failed with error: ${e.message}`);
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
});
|
|
361
|
+
export const operaConnectMcpServer = definePageTool({
|
|
362
|
+
name: 'opera_connect_mcp_server',
|
|
363
|
+
description: 'Connect to a registered MCP server. If the server requires OAuth, ' +
|
|
364
|
+
'the response includes requiresAuth: "needed" — follow with ' +
|
|
365
|
+
'opera_authenticate_mcp_server. Only available when connected to Opera Neon.',
|
|
366
|
+
blockedByDialog: false,
|
|
367
|
+
verifyFilesSchema: {},
|
|
368
|
+
annotations: {
|
|
369
|
+
category: ToolCategory.OPERA,
|
|
370
|
+
readOnlyHint: false,
|
|
371
|
+
},
|
|
372
|
+
schema: {
|
|
373
|
+
server: zod.string().min(1).describe('The MCP server name to connect.'),
|
|
374
|
+
},
|
|
375
|
+
handler: async (request, response) => {
|
|
376
|
+
const session = getCDPSession(request.page.pptrPage);
|
|
377
|
+
try {
|
|
378
|
+
const result = await dispatchAction(session, {
|
|
379
|
+
action: 'connectMcpServer',
|
|
380
|
+
type: 'CONNECT_SERVER',
|
|
381
|
+
server: request.params.server,
|
|
382
|
+
});
|
|
383
|
+
response.appendResponseLine(result);
|
|
384
|
+
}
|
|
385
|
+
catch (e) {
|
|
386
|
+
response.appendResponseLine(`Opera.dispatchAction(connectMcpServer) failed with error: ${e.message}`);
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
});
|
|
390
|
+
export const operaAuthenticateMcpServer = definePageTool({
|
|
391
|
+
name: 'opera_authenticate_mcp_server',
|
|
392
|
+
description: 'Complete OAuth sign-in for an MCP server that requires authentication. ' +
|
|
393
|
+
'Opens a browser popup for the OAuth flow; requires a headed (visible) browser. ' +
|
|
394
|
+
'Only available when connected to Opera Neon.',
|
|
395
|
+
blockedByDialog: false,
|
|
396
|
+
verifyFilesSchema: {},
|
|
397
|
+
annotations: {
|
|
398
|
+
category: ToolCategory.OPERA,
|
|
399
|
+
readOnlyHint: false,
|
|
400
|
+
},
|
|
401
|
+
schema: {
|
|
402
|
+
server: zod
|
|
403
|
+
.string()
|
|
404
|
+
.min(1)
|
|
405
|
+
.describe('The MCP server name to authenticate.'),
|
|
406
|
+
},
|
|
407
|
+
handler: async (request, response) => {
|
|
408
|
+
const session = getCDPSession(request.page.pptrPage);
|
|
409
|
+
try {
|
|
410
|
+
const result = await dispatchWithStreamedResponse(session, {
|
|
411
|
+
action: 'authenticateMcpServer',
|
|
412
|
+
type: 'AUTHENTICATE_SERVER',
|
|
413
|
+
server: request.params.server,
|
|
414
|
+
}, chunk => response.sendLog(chunk), request.signal);
|
|
415
|
+
response.appendResponseLine(result);
|
|
416
|
+
}
|
|
417
|
+
catch (e) {
|
|
418
|
+
if (e.name === 'AbortError') {
|
|
419
|
+
throw e;
|
|
420
|
+
}
|
|
421
|
+
response.appendResponseLine(`Opera.dispatchWithStreamedResponse(authenticateMcpServer) failed with error: ${e.message}`);
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
});
|
|
425
|
+
export const operaUnregisterMcpServer = definePageTool({
|
|
426
|
+
name: 'opera_unregister_mcp_server',
|
|
427
|
+
description: 'Remove a registered MCP server and its stored auth tokens. ' +
|
|
428
|
+
'Only available when connected to Opera Neon.',
|
|
429
|
+
blockedByDialog: false,
|
|
430
|
+
verifyFilesSchema: {},
|
|
431
|
+
annotations: {
|
|
432
|
+
category: ToolCategory.OPERA,
|
|
433
|
+
readOnlyHint: false,
|
|
434
|
+
},
|
|
435
|
+
schema: {
|
|
436
|
+
server: zod.string().min(1).describe('The MCP server name to unregister.'),
|
|
437
|
+
},
|
|
438
|
+
handler: async (request, response) => {
|
|
439
|
+
const session = getCDPSession(request.page.pptrPage);
|
|
440
|
+
try {
|
|
441
|
+
const result = await dispatchAction(session, {
|
|
442
|
+
action: 'unregisterMcpServer',
|
|
443
|
+
type: 'UNREGISTER_SERVER',
|
|
444
|
+
server: request.params.server,
|
|
445
|
+
});
|
|
446
|
+
response.appendResponseLine(result);
|
|
447
|
+
}
|
|
448
|
+
catch (e) {
|
|
449
|
+
response.appendResponseLine(`Opera.dispatchAction(unregisterMcpServer) failed with error: ${e.message}`);
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
export const operaEnableMcpServer = definePageTool({
|
|
454
|
+
name: 'opera_enable_mcp_server',
|
|
455
|
+
description: 'Enable a disabled MCP server. Only available when connected to Opera Neon.',
|
|
456
|
+
blockedByDialog: false,
|
|
457
|
+
verifyFilesSchema: {},
|
|
458
|
+
annotations: {
|
|
459
|
+
category: ToolCategory.OPERA,
|
|
460
|
+
readOnlyHint: false,
|
|
461
|
+
},
|
|
462
|
+
schema: {
|
|
463
|
+
server: zod.string().min(1).describe('The MCP server name to enable.'),
|
|
464
|
+
},
|
|
465
|
+
handler: async (request, response) => {
|
|
466
|
+
const session = getCDPSession(request.page.pptrPage);
|
|
467
|
+
try {
|
|
468
|
+
const result = await dispatchAction(session, {
|
|
469
|
+
action: 'enableMcpServer',
|
|
470
|
+
type: 'ENABLE_SERVER',
|
|
471
|
+
server: request.params.server,
|
|
472
|
+
});
|
|
473
|
+
response.appendResponseLine(result);
|
|
474
|
+
}
|
|
475
|
+
catch (e) {
|
|
476
|
+
response.appendResponseLine(`Opera.dispatchAction(enableMcpServer) failed with error: ${e.message}`);
|
|
477
|
+
}
|
|
478
|
+
},
|
|
479
|
+
});
|
|
480
|
+
export const operaDisableMcpServer = definePageTool({
|
|
481
|
+
name: 'opera_disable_mcp_server',
|
|
482
|
+
description: 'Disable an MCP server without unregistering it. ' +
|
|
483
|
+
'Only available when connected to Opera Neon.',
|
|
484
|
+
blockedByDialog: false,
|
|
485
|
+
verifyFilesSchema: {},
|
|
486
|
+
annotations: {
|
|
487
|
+
category: ToolCategory.OPERA,
|
|
488
|
+
readOnlyHint: false,
|
|
489
|
+
},
|
|
490
|
+
schema: {
|
|
491
|
+
server: zod.string().min(1).describe('The MCP server name to disable.'),
|
|
492
|
+
},
|
|
493
|
+
handler: async (request, response) => {
|
|
494
|
+
const session = getCDPSession(request.page.pptrPage);
|
|
495
|
+
try {
|
|
496
|
+
const result = await dispatchAction(session, {
|
|
497
|
+
action: 'disableMcpServer',
|
|
498
|
+
type: 'DISABLE_SERVER',
|
|
499
|
+
server: request.params.server,
|
|
500
|
+
});
|
|
501
|
+
response.appendResponseLine(result);
|
|
502
|
+
}
|
|
503
|
+
catch (e) {
|
|
504
|
+
response.appendResponseLine(`Opera.dispatchAction(disableMcpServer) failed with error: ${e.message}`);
|
|
505
|
+
}
|
|
506
|
+
},
|
|
507
|
+
});
|
|
323
508
|
//# sourceMappingURL=opera.js.map
|
package/build/src/version.js
CHANGED