ios-webkit-mcp 0.18.3
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/CONTRIBUTING.md +61 -0
- package/LICENSE +202 -0
- package/NOTICE +16 -0
- package/README.md +187 -0
- package/build/src/bin/ios-webkit-mcp.d.ts +2 -0
- package/build/src/bin/ios-webkit-mcp.js +14 -0
- package/build/src/bin/ios-webkit-mcp.js.map +1 -0
- package/build/src/capability.d.ts +61 -0
- package/build/src/capability.js +146 -0
- package/build/src/capability.js.map +1 -0
- package/build/src/index.d.ts +1 -0
- package/build/src/index.js +2 -0
- package/build/src/index.js.map +1 -0
- package/build/src/page-session.d.ts +108 -0
- package/build/src/page-session.js +331 -0
- package/build/src/page-session.js.map +1 -0
- package/build/src/server.d.ts +11 -0
- package/build/src/server.js +144 -0
- package/build/src/server.js.map +1 -0
- package/build/src/tools/analyze_performance.d.ts +40 -0
- package/build/src/tools/analyze_performance.js +112 -0
- package/build/src/tools/analyze_performance.js.map +1 -0
- package/build/src/tools/breakpoints.d.ts +80 -0
- package/build/src/tools/breakpoints.js +167 -0
- package/build/src/tools/breakpoints.js.map +1 -0
- package/build/src/tools/clear_console.d.ts +11 -0
- package/build/src/tools/clear_console.js +32 -0
- package/build/src/tools/clear_console.js.map +1 -0
- package/build/src/tools/click.d.ts +20 -0
- package/build/src/tools/click.js +88 -0
- package/build/src/tools/click.js.map +1 -0
- package/build/src/tools/debug_element.d.ts +36 -0
- package/build/src/tools/debug_element.js +66 -0
- package/build/src/tools/debug_element.js.map +1 -0
- package/build/src/tools/debugger.d.ts +44 -0
- package/build/src/tools/debugger.js +117 -0
- package/build/src/tools/debugger.js.map +1 -0
- package/build/src/tools/delete_cookie.d.ts +18 -0
- package/build/src/tools/delete_cookie.js +33 -0
- package/build/src/tools/delete_cookie.js.map +1 -0
- package/build/src/tools/drag.d.ts +40 -0
- package/build/src/tools/drag.js +202 -0
- package/build/src/tools/drag.js.map +1 -0
- package/build/src/tools/evaluate_script.d.ts +24 -0
- package/build/src/tools/evaluate_script.js +172 -0
- package/build/src/tools/evaluate_script.js.map +1 -0
- package/build/src/tools/fill.d.ts +22 -0
- package/build/src/tools/fill.js +104 -0
- package/build/src/tools/fill.js.map +1 -0
- package/build/src/tools/fill_form.d.ts +34 -0
- package/build/src/tools/fill_form.js +110 -0
- package/build/src/tools/fill_form.js.map +1 -0
- package/build/src/tools/gc_heap.d.ts +16 -0
- package/build/src/tools/gc_heap.js +66 -0
- package/build/src/tools/gc_heap.js.map +1 -0
- package/build/src/tools/get_capability_snapshot.d.ts +17 -0
- package/build/src/tools/get_capability_snapshot.js +50 -0
- package/build/src/tools/get_capability_snapshot.js.map +1 -0
- package/build/src/tools/get_console_message.d.ts +18 -0
- package/build/src/tools/get_console_message.js +92 -0
- package/build/src/tools/get_console_message.js.map +1 -0
- package/build/src/tools/get_cookies.d.ts +20 -0
- package/build/src/tools/get_cookies.js +59 -0
- package/build/src/tools/get_cookies.js.map +1 -0
- package/build/src/tools/get_event_listeners.d.ts +29 -0
- package/build/src/tools/get_event_listeners.js +129 -0
- package/build/src/tools/get_event_listeners.js.map +1 -0
- package/build/src/tools/get_network_request.d.ts +22 -0
- package/build/src/tools/get_network_request.js +121 -0
- package/build/src/tools/get_network_request.js.map +1 -0
- package/build/src/tools/get_performance_metrics.d.ts +27 -0
- package/build/src/tools/get_performance_metrics.js +185 -0
- package/build/src/tools/get_performance_metrics.js.map +1 -0
- package/build/src/tools/get_resource_tree.d.ts +18 -0
- package/build/src/tools/get_resource_tree.js +82 -0
- package/build/src/tools/get_resource_tree.js.map +1 -0
- package/build/src/tools/handle_dialog.d.ts +39 -0
- package/build/src/tools/handle_dialog.js +182 -0
- package/build/src/tools/handle_dialog.js.map +1 -0
- package/build/src/tools/highlight_node.d.ts +41 -0
- package/build/src/tools/highlight_node.js +95 -0
- package/build/src/tools/highlight_node.js.map +1 -0
- package/build/src/tools/hover.d.ts +20 -0
- package/build/src/tools/hover.js +89 -0
- package/build/src/tools/hover.js.map +1 -0
- package/build/src/tools/intercept.d.ts +81 -0
- package/build/src/tools/intercept.js +161 -0
- package/build/src/tools/intercept.js.map +1 -0
- package/build/src/tools/list_console_messages.d.ts +20 -0
- package/build/src/tools/list_console_messages.js +105 -0
- package/build/src/tools/list_console_messages.js.map +1 -0
- package/build/src/tools/list_indexeddb.d.ts +16 -0
- package/build/src/tools/list_indexeddb.js +55 -0
- package/build/src/tools/list_indexeddb.js.map +1 -0
- package/build/src/tools/list_network_requests.d.ts +25 -0
- package/build/src/tools/list_network_requests.js +108 -0
- package/build/src/tools/list_network_requests.js.map +1 -0
- package/build/src/tools/list_pages.d.ts +17 -0
- package/build/src/tools/list_pages.js +113 -0
- package/build/src/tools/list_pages.js.map +1 -0
- package/build/src/tools/navigate_page.d.ts +18 -0
- package/build/src/tools/navigate_page.js +73 -0
- package/build/src/tools/navigate_page.js.map +1 -0
- package/build/src/tools/network_runtime.d.ts +51 -0
- package/build/src/tools/network_runtime.js +101 -0
- package/build/src/tools/network_runtime.js.map +1 -0
- package/build/src/tools/press_key.d.ts +32 -0
- package/build/src/tools/press_key.js +108 -0
- package/build/src/tools/press_key.js.map +1 -0
- package/build/src/tools/query_dom_node.d.ts +22 -0
- package/build/src/tools/query_dom_node.js +103 -0
- package/build/src/tools/query_dom_node.js.map +1 -0
- package/build/src/tools/record_cpu_profile.d.ts +38 -0
- package/build/src/tools/record_cpu_profile.js +174 -0
- package/build/src/tools/record_cpu_profile.js.map +1 -0
- package/build/src/tools/record_memory_tracking.d.ts +32 -0
- package/build/src/tools/record_memory_tracking.js +103 -0
- package/build/src/tools/record_memory_tracking.js.map +1 -0
- package/build/src/tools/record_timeline.d.ts +20 -0
- package/build/src/tools/record_timeline.js +110 -0
- package/build/src/tools/record_timeline.js.map +1 -0
- package/build/src/tools/reload_page.d.ts +18 -0
- package/build/src/tools/reload_page.js +59 -0
- package/build/src/tools/reload_page.js.map +1 -0
- package/build/src/tools/select_page.d.ts +18 -0
- package/build/src/tools/select_page.js +54 -0
- package/build/src/tools/select_page.js.map +1 -0
- package/build/src/tools/set_extra_http_headers.d.ts +16 -0
- package/build/src/tools/set_extra_http_headers.js +55 -0
- package/build/src/tools/set_extra_http_headers.js.map +1 -0
- package/build/src/tools/set_init_script.d.ts +16 -0
- package/build/src/tools/set_init_script.js +43 -0
- package/build/src/tools/set_init_script.js.map +1 -0
- package/build/src/tools/set_outer_html.d.ts +18 -0
- package/build/src/tools/set_outer_html.js +52 -0
- package/build/src/tools/set_outer_html.js.map +1 -0
- package/build/src/tools/set_user_agent.d.ts +40 -0
- package/build/src/tools/set_user_agent.js +83 -0
- package/build/src/tools/set_user_agent.js.map +1 -0
- package/build/src/tools/summarize_console_errors.d.ts +40 -0
- package/build/src/tools/summarize_console_errors.js +131 -0
- package/build/src/tools/summarize_console_errors.js.map +1 -0
- package/build/src/tools/take_memory_snapshot.d.ts +18 -0
- package/build/src/tools/take_memory_snapshot.js +88 -0
- package/build/src/tools/take_memory_snapshot.js.map +1 -0
- package/build/src/tools/take_node_screenshot.d.ts +29 -0
- package/build/src/tools/take_node_screenshot.js +57 -0
- package/build/src/tools/take_node_screenshot.js.map +1 -0
- package/build/src/tools/take_screenshot.d.ts +51 -0
- package/build/src/tools/take_screenshot.js +108 -0
- package/build/src/tools/take_screenshot.js.map +1 -0
- package/build/src/tools/take_snapshot.d.ts +22 -0
- package/build/src/tools/take_snapshot.js +142 -0
- package/build/src/tools/take_snapshot.js.map +1 -0
- package/build/src/tools/type_text.d.ts +34 -0
- package/build/src/tools/type_text.js +203 -0
- package/build/src/tools/type_text.js.map +1 -0
- package/build/src/tools/wait_for.d.ts +24 -0
- package/build/src/tools/wait_for.js +93 -0
- package/build/src/tools/wait_for.js.map +1 -0
- package/build/src/tools/wip_send.d.ts +22 -0
- package/build/src/tools/wip_send.js +81 -0
- package/build/src/tools/wip_send.js.map +1 -0
- package/build/src/wip-client/iwdp-http.d.ts +17 -0
- package/build/src/wip-client/iwdp-http.js +98 -0
- package/build/src/wip-client/iwdp-http.js.map +1 -0
- package/build/src/wip-client/ws-session.d.ts +41 -0
- package/build/src/wip-client/ws-session.js +290 -0
- package/build/src/wip-client/ws-session.js.map +1 -0
- package/docs/spec.md +689 -0
- package/package.json +77 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `get_event_listeners` (batch-13 Must) — list event listeners bound to a DOM
|
|
3
|
+
* node via WIP `DOM.getEventListenersForNode`.
|
|
4
|
+
*
|
|
5
|
+
* Probe-confirmed 2026-05-17 (capability matrix v2): the method exists and
|
|
6
|
+
* returns `-32000 Missing node for given nodeId` when called without a valid
|
|
7
|
+
* id, so chain through DOM.getDocument → querySelector first.
|
|
8
|
+
*
|
|
9
|
+
* Returns one row per listener with type / useCapture / passive / sourceURL +
|
|
10
|
+
* line. Distinguishes inline (set via attribute) vs addEventListener.
|
|
11
|
+
*/
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
import { PageSession } from '../page-session.js';
|
|
14
|
+
export const getEventListenersTool = {
|
|
15
|
+
name: 'get_event_listeners',
|
|
16
|
+
description: [
|
|
17
|
+
'List event listeners bound to a DOM node (matched by CSS selector) via WIP `DOM.getEventListenersForNode` (✅ probe 2026-05-17).',
|
|
18
|
+
'Useful to debug "which handler fires on click", catch stale listeners, audit passive/useCapture flags, and find the source script:line of the handler.',
|
|
19
|
+
'Chain: DOM.getDocument → DOM.querySelector → DOM.getEventListenersForNode. Returns first match only (use `query_dom_node` first if you need to disambiguate).',
|
|
20
|
+
].join(' '),
|
|
21
|
+
inputSchema: {
|
|
22
|
+
selector: z.string().min(1).describe('CSS selector matching exactly one node (first match used).'),
|
|
23
|
+
includeAncestors: z
|
|
24
|
+
.boolean()
|
|
25
|
+
.optional()
|
|
26
|
+
.describe('Walk up parentNode chain and aggregate listeners (default false → target node only). Useful for capture-phase / delegated listeners.'),
|
|
27
|
+
},
|
|
28
|
+
handler: async ({ selector, includeAncestors = false }) => {
|
|
29
|
+
let ps;
|
|
30
|
+
try {
|
|
31
|
+
ps = await PageSession.get();
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
return errorResult(`Unable to attach: ${describe(e)}`);
|
|
35
|
+
}
|
|
36
|
+
let rootId;
|
|
37
|
+
try {
|
|
38
|
+
const doc = await ps.session.send('DOM.getDocument', { depth: 0 }, 10_000);
|
|
39
|
+
rootId = doc.root.nodeId;
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
return errorResult(`DOM.getDocument failed: ${describe(e)}`);
|
|
43
|
+
}
|
|
44
|
+
let nodeId;
|
|
45
|
+
try {
|
|
46
|
+
const r = await ps.session.send('DOM.querySelector', { nodeId: rootId, selector }, 10_000);
|
|
47
|
+
if (r.nodeId === 0)
|
|
48
|
+
return textResult(`# get_event_listeners — 0 nodes match \`${selector}\``);
|
|
49
|
+
nodeId = r.nodeId;
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
return errorResult(`DOM.querySelector failed: ${describe(e)}`);
|
|
53
|
+
}
|
|
54
|
+
const queryNodes = [nodeId];
|
|
55
|
+
if (includeAncestors) {
|
|
56
|
+
// Use Runtime.evaluate to enumerate ancestor nodeIds via the inspector remote object trick.
|
|
57
|
+
// WIP doesn't expose DOM.getParent directly; we walk through getOuterHTML chain via element bridge.
|
|
58
|
+
// Cheaper: iterate up to body via Runtime call returning a list of ancestor selectors → re-query each.
|
|
59
|
+
try {
|
|
60
|
+
const r = await ps.session.send('Runtime.evaluate', {
|
|
61
|
+
expression: `(() => {
|
|
62
|
+
const el = document.querySelector(${JSON.stringify(selector)});
|
|
63
|
+
if (!el) return [];
|
|
64
|
+
const out = [];
|
|
65
|
+
let n = el.parentElement;
|
|
66
|
+
while (n && n !== document.body) {
|
|
67
|
+
let s = n.tagName.toLowerCase();
|
|
68
|
+
if (n.id) s += '#' + CSS.escape(n.id);
|
|
69
|
+
else if (n.className && typeof n.className === 'string') s += '.' + n.className.trim().split(/\\s+/).slice(0, 2).join('.');
|
|
70
|
+
out.push(s);
|
|
71
|
+
n = n.parentElement;
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
})()`,
|
|
75
|
+
returnByValue: true,
|
|
76
|
+
}, 10_000);
|
|
77
|
+
const ancestors = r.result?.value ?? [];
|
|
78
|
+
for (const sel of ancestors) {
|
|
79
|
+
try {
|
|
80
|
+
const q = await ps.session.send('DOM.querySelector', { nodeId: rootId, selector: sel }, 5_000);
|
|
81
|
+
if (q.nodeId && q.nodeId !== 0)
|
|
82
|
+
queryNodes.push(q.nodeId);
|
|
83
|
+
}
|
|
84
|
+
catch { /* skip ancestor we can't resolve */ }
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
return errorResult(`ancestor enumeration failed: ${describe(e)}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const allListeners = [];
|
|
92
|
+
for (let i = 0; i < queryNodes.length; i++) {
|
|
93
|
+
const nid = queryNodes[i];
|
|
94
|
+
try {
|
|
95
|
+
const r = await ps.session.send('DOM.getEventListenersForNode', { nodeId: nid }, 10_000);
|
|
96
|
+
const list = r.listeners ?? [];
|
|
97
|
+
const label = i === 0 ? `target (${selector})` : `ancestor[${i}]`;
|
|
98
|
+
for (const l of list)
|
|
99
|
+
allListeners.push({ ownerNodeId: nid, ownerLabel: label, listener: l });
|
|
100
|
+
}
|
|
101
|
+
catch (e) {
|
|
102
|
+
// Carry on; some ancestors may legitimately fail.
|
|
103
|
+
if (i === 0)
|
|
104
|
+
return errorResult(`DOM.getEventListenersForNode failed: ${describe(e)}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (allListeners.length === 0) {
|
|
108
|
+
return textResult(`# get_event_listeners — \`${selector}\`\n\nNo listeners found on target${includeAncestors ? ' or ancestors' : ''}.`);
|
|
109
|
+
}
|
|
110
|
+
const lines = [
|
|
111
|
+
`# get_event_listeners — \`${selector}\``,
|
|
112
|
+
'',
|
|
113
|
+
`Listeners: ${allListeners.length}${includeAncestors ? ` (across ${queryNodes.length} nodes)` : ''}`,
|
|
114
|
+
'',
|
|
115
|
+
'| owner | type | capture | passive | once | inline | source |',
|
|
116
|
+
'|---|---|---|---|---|---|---|',
|
|
117
|
+
];
|
|
118
|
+
for (const { ownerLabel, listener: l } of allListeners) {
|
|
119
|
+
const loc = l.location ?? { scriptId: l.scriptId, lineNumber: l.lineNumber, columnNumber: l.columnNumber };
|
|
120
|
+
const src = loc?.scriptId ? `script ${loc.scriptId}:${loc.lineNumber ?? '?'}:${loc.columnNumber ?? '?'}` : '(unknown)';
|
|
121
|
+
lines.push(`| ${ownerLabel} | ${l.type ?? '?'} | ${l.useCapture ? 'Y' : ''} | ${l.passive ? 'Y' : ''} | ${l.once ? 'Y' : ''} | ${l.isAttribute ? 'Y' : ''} | ${src} |`);
|
|
122
|
+
}
|
|
123
|
+
return textResult(lines.join('\n'));
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
function textResult(text) { return { content: [{ type: 'text', text }] }; }
|
|
127
|
+
function errorResult(text) { return { content: [{ type: 'text', text }], isError: true }; }
|
|
128
|
+
function describe(e) { return e instanceof Error ? e.message : String(e); }
|
|
129
|
+
//# sourceMappingURL=get_event_listeners.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get_event_listeners.js","sourceRoot":"","sources":["../../../src/tools/get_event_listeners.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const getNetworkRequestTool: {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
inputSchema: {
|
|
6
|
+
requestId: z.ZodOptional<z.ZodString>;
|
|
7
|
+
index: z.ZodOptional<z.ZodNumber>;
|
|
8
|
+
withBody: z.ZodOptional<z.ZodBoolean>;
|
|
9
|
+
bodyMaxLen: z.ZodOptional<z.ZodNumber>;
|
|
10
|
+
};
|
|
11
|
+
handler: ({ requestId, index, withBody, bodyMaxLen, }: {
|
|
12
|
+
requestId?: string;
|
|
13
|
+
index?: number;
|
|
14
|
+
withBody?: boolean;
|
|
15
|
+
bodyMaxLen?: number;
|
|
16
|
+
}) => Promise<{
|
|
17
|
+
content: {
|
|
18
|
+
type: "text";
|
|
19
|
+
text: string;
|
|
20
|
+
}[];
|
|
21
|
+
}>;
|
|
22
|
+
};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { PageSession } from '../page-session.js';
|
|
3
|
+
export const getNetworkRequestTool = {
|
|
4
|
+
name: 'get_network_request',
|
|
5
|
+
description: [
|
|
6
|
+
'Return the full detail of a single network request from the rolling buffer (filled by `Network.requestWillBeSent` / `responseReceived` / `loadingFinished` / `loadingFailed`).',
|
|
7
|
+
'Lookup by `requestId` (preferred — exact match) or `index` (0-based against current buffer ordering; negative counts from end).',
|
|
8
|
+
'Returns lifecycle state, request line, request/response headers, and optionally the response body via `Network.getResponseBody` when `withBody=true`.',
|
|
9
|
+
'NOTE: WIP `Network.getResponseBody` only returns bodies for requests that completed AND were not evicted from WebKit\'s resource buffer — large or binary bodies may fail with `-32000 No data found`.',
|
|
10
|
+
].join(' '),
|
|
11
|
+
inputSchema: {
|
|
12
|
+
requestId: z.string().optional().describe('Exact requestId returned by `list_network_requests` (e.g. `loader-id.123`).'),
|
|
13
|
+
index: z.number().int().optional().describe('0-based buffer index. Negative counts from the end. Mutually exclusive with requestId.'),
|
|
14
|
+
withBody: z.boolean().optional().describe('Also fetch response body via `Network.getResponseBody`. Default false.'),
|
|
15
|
+
bodyMaxLen: z.number().int().min(100).max(200_000).optional().describe('Response body truncation cap (default 20000).'),
|
|
16
|
+
},
|
|
17
|
+
handler: async ({ requestId, index, withBody = false, bodyMaxLen = 20_000, }) => {
|
|
18
|
+
let ps;
|
|
19
|
+
try {
|
|
20
|
+
ps = await PageSession.get();
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
return errorResult(`Unable to attach to a WKWebView page: ${describe(e)}`);
|
|
24
|
+
}
|
|
25
|
+
const buf = ps.networkBuffer;
|
|
26
|
+
if (buf.length === 0) {
|
|
27
|
+
return errorResult('Network buffer is empty. Trigger page activity and call again.');
|
|
28
|
+
}
|
|
29
|
+
if (requestId === undefined && index === undefined) {
|
|
30
|
+
return errorResult('Provide either `requestId` or `index`.');
|
|
31
|
+
}
|
|
32
|
+
if (requestId !== undefined && index !== undefined) {
|
|
33
|
+
return errorResult('Provide only one of `requestId` / `index`.');
|
|
34
|
+
}
|
|
35
|
+
let entry;
|
|
36
|
+
if (requestId !== undefined) {
|
|
37
|
+
entry = ps.networkById.get(requestId);
|
|
38
|
+
if (!entry) {
|
|
39
|
+
return errorResult(`requestId ${JSON.stringify(requestId)} not in buffer (${buf.length} entries). Use \`list_network_requests\` to enumerate.`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
let i = index;
|
|
44
|
+
if (i < 0)
|
|
45
|
+
i = buf.length + i;
|
|
46
|
+
if (i < 0 || i >= buf.length) {
|
|
47
|
+
return errorResult(`Index ${index} out of range (buffer has ${buf.length} entries).`);
|
|
48
|
+
}
|
|
49
|
+
entry = buf[i];
|
|
50
|
+
}
|
|
51
|
+
const lines = [];
|
|
52
|
+
lines.push(`# network[${entry.requestId}] · ${entry.state} · ${entry.method ?? '?'} ${entry.url}`);
|
|
53
|
+
lines.push('');
|
|
54
|
+
lines.push(`Status: ${entry.status ?? '(no status)'} ${entry.statusText ?? ''}`);
|
|
55
|
+
lines.push(`MIME type: ${entry.mimeType ?? '(unknown)'}`);
|
|
56
|
+
lines.push(`Resource type: ${entry.type ?? '(unknown)'}${entry.initiatorType ? ` · initiator=${entry.initiatorType}` : ''}`);
|
|
57
|
+
if (entry.startedAt != null)
|
|
58
|
+
lines.push(`Started at (proxy clock): ${entry.startedAt}`);
|
|
59
|
+
if (entry.endedAt != null)
|
|
60
|
+
lines.push(`Ended at (proxy clock): ${entry.endedAt}`);
|
|
61
|
+
if (entry.encodedDataLength != null)
|
|
62
|
+
lines.push(`Encoded data length: ${entry.encodedDataLength}`);
|
|
63
|
+
if (entry.errorText)
|
|
64
|
+
lines.push(`Error: ${entry.errorText}`);
|
|
65
|
+
if (entry.requestHeaders && Object.keys(entry.requestHeaders).length > 0) {
|
|
66
|
+
lines.push('');
|
|
67
|
+
lines.push('## Request headers');
|
|
68
|
+
for (const [k, v] of Object.entries(entry.requestHeaders)) {
|
|
69
|
+
lines.push(`- ${k}: ${truncate(String(v), 500)}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (entry.postData) {
|
|
73
|
+
lines.push('');
|
|
74
|
+
lines.push('## Request body (postData)');
|
|
75
|
+
lines.push('```');
|
|
76
|
+
lines.push(truncate(entry.postData, 2_000));
|
|
77
|
+
lines.push('```');
|
|
78
|
+
}
|
|
79
|
+
if (entry.responseHeaders && Object.keys(entry.responseHeaders).length > 0) {
|
|
80
|
+
lines.push('');
|
|
81
|
+
lines.push('## Response headers');
|
|
82
|
+
for (const [k, v] of Object.entries(entry.responseHeaders)) {
|
|
83
|
+
lines.push(`- ${k}: ${truncate(String(v), 500)}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (withBody) {
|
|
87
|
+
if (entry.state === 'pending') {
|
|
88
|
+
lines.push('');
|
|
89
|
+
lines.push('⚠ Response body unavailable: request still pending.');
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
try {
|
|
93
|
+
const r = await ps.session.send('Network.getResponseBody', { requestId: entry.requestId }, 10_000);
|
|
94
|
+
lines.push('');
|
|
95
|
+
lines.push(`## Response body${r.base64Encoded ? ' (base64)' : ''}`);
|
|
96
|
+
lines.push('```');
|
|
97
|
+
lines.push(truncate(r.body ?? '', bodyMaxLen));
|
|
98
|
+
lines.push('```');
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
lines.push('');
|
|
102
|
+
lines.push(`⚠ Network.getResponseBody failed: ${describe(e)}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return textResult(lines.join('\n'));
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
function truncate(s, max) {
|
|
110
|
+
return s.length > max ? s.slice(0, max) + `\n… (truncated, full length ${s.length})` : s;
|
|
111
|
+
}
|
|
112
|
+
function textResult(text) {
|
|
113
|
+
return { content: [{ type: 'text', text }] };
|
|
114
|
+
}
|
|
115
|
+
function errorResult(text) {
|
|
116
|
+
return { content: [{ type: 'text', text }], isError: true };
|
|
117
|
+
}
|
|
118
|
+
function describe(e) {
|
|
119
|
+
return e instanceof Error ? e.message : String(e);
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=get_network_request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get_network_request.js","sourceRoot":"","sources":["../../../src/tools/get_network_request.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* WIP has no `Tracing.*` / `Performance.getMetrics` domain, so chrome-devtools-mcp's
|
|
4
|
+
* `performance_start_trace` / `performance_analyze_insight` are unimplementable.
|
|
5
|
+
* However the JavaScript `PerformanceObserver` + `performance.getEntriesByType` APIs
|
|
6
|
+
* are available inside the WebView. This tool reads them via `Runtime.evaluate`
|
|
7
|
+
* and returns structured metrics — a JS-side approximation that covers the
|
|
8
|
+
* majority of the chrome-devtools-mcp Performance use cases (navigation timing,
|
|
9
|
+
* paint timing, LCP, CLS, slow resources).
|
|
10
|
+
*/
|
|
11
|
+
export declare const getPerformanceMetricsTool: {
|
|
12
|
+
name: string;
|
|
13
|
+
description: string;
|
|
14
|
+
inputSchema: {
|
|
15
|
+
slowResourceMs: z.ZodOptional<z.ZodNumber>;
|
|
16
|
+
resourceLimit: z.ZodOptional<z.ZodNumber>;
|
|
17
|
+
};
|
|
18
|
+
handler: ({ slowResourceMs, resourceLimit, }: {
|
|
19
|
+
slowResourceMs?: number;
|
|
20
|
+
resourceLimit?: number;
|
|
21
|
+
}) => Promise<{
|
|
22
|
+
content: {
|
|
23
|
+
type: "text";
|
|
24
|
+
text: string;
|
|
25
|
+
}[];
|
|
26
|
+
}>;
|
|
27
|
+
};
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { PageSession } from '../page-session.js';
|
|
3
|
+
/**
|
|
4
|
+
* WIP has no `Tracing.*` / `Performance.getMetrics` domain, so chrome-devtools-mcp's
|
|
5
|
+
* `performance_start_trace` / `performance_analyze_insight` are unimplementable.
|
|
6
|
+
* However the JavaScript `PerformanceObserver` + `performance.getEntriesByType` APIs
|
|
7
|
+
* are available inside the WebView. This tool reads them via `Runtime.evaluate`
|
|
8
|
+
* and returns structured metrics — a JS-side approximation that covers the
|
|
9
|
+
* majority of the chrome-devtools-mcp Performance use cases (navigation timing,
|
|
10
|
+
* paint timing, LCP, CLS, slow resources).
|
|
11
|
+
*/
|
|
12
|
+
export const getPerformanceMetricsTool = {
|
|
13
|
+
name: 'get_performance_metrics',
|
|
14
|
+
description: [
|
|
15
|
+
'Read JavaScript-side performance metrics from the inspected iOS WebView page.',
|
|
16
|
+
'NOTE: WIP has no `Tracing.*` or `Performance.getMetrics` domain (chrome-devtools-mcp\'s `performance_*` tools are unimplementable on iOS). This tool wraps `performance.getEntriesByType` for: navigation timing, paint (FP/FCP), Largest Contentful Paint, Cumulative Layout Shift, and slow resources.',
|
|
17
|
+
'All values come from W3C Performance APIs — they reflect the current page state, not a freshly recorded trace. To capture metrics after an interaction, reload + interact + call again.',
|
|
18
|
+
].join(' '),
|
|
19
|
+
inputSchema: {
|
|
20
|
+
slowResourceMs: z
|
|
21
|
+
.number()
|
|
22
|
+
.int()
|
|
23
|
+
.min(0)
|
|
24
|
+
.max(60_000)
|
|
25
|
+
.optional()
|
|
26
|
+
.describe('Resource entries with `duration` ≥ this many ms are flagged as slow (default 500). Set 0 to include all.'),
|
|
27
|
+
resourceLimit: z
|
|
28
|
+
.number()
|
|
29
|
+
.int()
|
|
30
|
+
.min(1)
|
|
31
|
+
.max(500)
|
|
32
|
+
.optional()
|
|
33
|
+
.describe('Cap slow-resource entries returned (default 30).'),
|
|
34
|
+
},
|
|
35
|
+
handler: async ({ slowResourceMs = 500, resourceLimit = 30, }) => {
|
|
36
|
+
let ps;
|
|
37
|
+
try {
|
|
38
|
+
ps = await PageSession.get();
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
return errorResult(`Unable to attach to a WKWebView page: ${describe(e)}`);
|
|
42
|
+
}
|
|
43
|
+
const expression = `
|
|
44
|
+
(() => {
|
|
45
|
+
const out = { navigation: null, paint: [], lcp: null, cls: null, layoutShifts: 0, slowResources: [], counts: {} };
|
|
46
|
+
try {
|
|
47
|
+
const nav = performance.getEntriesByType('navigation')[0];
|
|
48
|
+
if (nav) {
|
|
49
|
+
out.navigation = {
|
|
50
|
+
type: nav.type,
|
|
51
|
+
startTime: nav.startTime,
|
|
52
|
+
fetchStart: nav.fetchStart,
|
|
53
|
+
domainLookup: { start: nav.domainLookupStart, end: nav.domainLookupEnd, ms: nav.domainLookupEnd - nav.domainLookupStart },
|
|
54
|
+
connect: { start: nav.connectStart, end: nav.connectEnd, ms: nav.connectEnd - nav.connectStart },
|
|
55
|
+
tls: nav.secureConnectionStart > 0 ? { start: nav.secureConnectionStart, end: nav.connectEnd, ms: nav.connectEnd - nav.secureConnectionStart } : null,
|
|
56
|
+
request: { start: nav.requestStart, ms: nav.responseStart - nav.requestStart },
|
|
57
|
+
response: { start: nav.responseStart, end: nav.responseEnd, ms: nav.responseEnd - nav.responseStart },
|
|
58
|
+
dom: { interactive: nav.domInteractive, contentLoaded: nav.domContentLoadedEventEnd, complete: nav.domComplete },
|
|
59
|
+
loadEvent: { start: nav.loadEventStart, end: nav.loadEventEnd, ms: nav.loadEventEnd - nav.loadEventStart },
|
|
60
|
+
transferSize: nav.transferSize,
|
|
61
|
+
encodedBodySize: nav.encodedBodySize,
|
|
62
|
+
decodedBodySize: nav.decodedBodySize,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
} catch (e) { out.navigation = { error: String(e) }; }
|
|
66
|
+
try {
|
|
67
|
+
out.paint = performance.getEntriesByType('paint').map(p => ({ name: p.name, startTime: p.startTime }));
|
|
68
|
+
} catch (e) {}
|
|
69
|
+
try {
|
|
70
|
+
const lcps = performance.getEntriesByType('largest-contentful-paint');
|
|
71
|
+
if (lcps.length) {
|
|
72
|
+
const last = lcps[lcps.length - 1];
|
|
73
|
+
out.lcp = { startTime: last.startTime, renderTime: last.renderTime, size: last.size, url: last.url, element: last.element && last.element.tagName };
|
|
74
|
+
}
|
|
75
|
+
} catch (e) {}
|
|
76
|
+
try {
|
|
77
|
+
const shifts = performance.getEntriesByType('layout-shift') || [];
|
|
78
|
+
let sum = 0; for (const s of shifts) if (!s.hadRecentInput) sum += s.value;
|
|
79
|
+
out.cls = sum; out.layoutShifts = shifts.length;
|
|
80
|
+
} catch (e) {}
|
|
81
|
+
try {
|
|
82
|
+
const res = performance.getEntriesByType('resource');
|
|
83
|
+
out.counts.resources = res.length;
|
|
84
|
+
const slow = res.filter(r => r.duration >= ${slowResourceMs}).sort((a, b) => b.duration - a.duration).slice(0, ${resourceLimit});
|
|
85
|
+
out.slowResources = slow.map(r => ({
|
|
86
|
+
name: r.name, initiator: r.initiatorType, duration: r.duration, startTime: r.startTime,
|
|
87
|
+
transferSize: r.transferSize, encodedBodySize: r.encodedBodySize, nextHopProtocol: r.nextHopProtocol,
|
|
88
|
+
}));
|
|
89
|
+
} catch (e) {}
|
|
90
|
+
try { out.counts.measures = performance.getEntriesByType('measure').length; } catch (e) {}
|
|
91
|
+
try { out.counts.marks = performance.getEntriesByType('mark').length; } catch (e) {}
|
|
92
|
+
return out;
|
|
93
|
+
})()
|
|
94
|
+
`;
|
|
95
|
+
let result;
|
|
96
|
+
try {
|
|
97
|
+
result = await ps.session.send('Runtime.evaluate', { expression, returnByValue: true, awaitPromise: false }, 15_000);
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
return errorResult(`Runtime.evaluate (get_performance_metrics) failed: ${describe(e)}`);
|
|
101
|
+
}
|
|
102
|
+
const v = result?.result?.value;
|
|
103
|
+
if (!v || typeof v !== 'object') {
|
|
104
|
+
return errorResult(`# get_performance_metrics: unexpected return\n\n${JSON.stringify(result?.result)}`);
|
|
105
|
+
}
|
|
106
|
+
const lines = [`# get_performance_metrics`, ''];
|
|
107
|
+
const nav = v.navigation;
|
|
108
|
+
if (nav && !nav.error) {
|
|
109
|
+
lines.push('## navigation timing');
|
|
110
|
+
lines.push(`- type: ${nav.type}`);
|
|
111
|
+
const fmt = (g, label) => g ? `- ${label}: ${g.ms.toFixed(1)} ms` : null;
|
|
112
|
+
const segs = [
|
|
113
|
+
fmt(nav.domainLookup, 'DNS'),
|
|
114
|
+
fmt(nav.connect, 'TCP connect'),
|
|
115
|
+
fmt(nav.tls, 'TLS'),
|
|
116
|
+
fmt(nav.request, 'request (TTFB)'),
|
|
117
|
+
fmt(nav.response, 'response download'),
|
|
118
|
+
fmt(nav.loadEvent, 'load event'),
|
|
119
|
+
].filter(Boolean);
|
|
120
|
+
lines.push(...segs);
|
|
121
|
+
const dom = nav.dom;
|
|
122
|
+
lines.push(`- DOM interactive: ${dom.interactive.toFixed(1)} ms · contentLoaded: ${dom.contentLoaded.toFixed(1)} ms · complete: ${dom.complete.toFixed(1)} ms`);
|
|
123
|
+
lines.push(`- transfer: encoded ${nav.encodedBodySize} B / decoded ${nav.decodedBodySize} B / transfer ${nav.transferSize} B`);
|
|
124
|
+
}
|
|
125
|
+
else if (nav && nav.error) {
|
|
126
|
+
lines.push('## navigation timing');
|
|
127
|
+
lines.push(`⚠ ${nav.error}`);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
lines.push('## navigation timing');
|
|
131
|
+
lines.push('(no navigation entry — page may not have a full navigation, e.g. SPA route change)');
|
|
132
|
+
}
|
|
133
|
+
const paint = v.paint;
|
|
134
|
+
if (paint?.length) {
|
|
135
|
+
lines.push('');
|
|
136
|
+
lines.push('## paint');
|
|
137
|
+
paint.forEach(p => lines.push(`- ${p.name}: ${p.startTime.toFixed(1)} ms`));
|
|
138
|
+
}
|
|
139
|
+
const lcp = v.lcp;
|
|
140
|
+
if (lcp) {
|
|
141
|
+
lines.push('');
|
|
142
|
+
lines.push('## Largest Contentful Paint');
|
|
143
|
+
lines.push(`- startTime: ${lcp.startTime.toFixed(1)} ms${lcp.renderTime ? ` (render ${lcp.renderTime.toFixed(1)} ms)` : ''}`);
|
|
144
|
+
if (lcp.element)
|
|
145
|
+
lines.push(`- element: <${lcp.element}>`);
|
|
146
|
+
if (lcp.url)
|
|
147
|
+
lines.push(`- url: ${lcp.url}`);
|
|
148
|
+
if (lcp.size != null)
|
|
149
|
+
lines.push(`- size (px²): ${lcp.size}`);
|
|
150
|
+
}
|
|
151
|
+
if (v.cls != null) {
|
|
152
|
+
lines.push('');
|
|
153
|
+
lines.push(`## Cumulative Layout Shift: ${v.cls.toFixed(4)} (${v.layoutShifts} shift entries)`);
|
|
154
|
+
}
|
|
155
|
+
const counts = v.counts;
|
|
156
|
+
lines.push('');
|
|
157
|
+
lines.push(`## counts: ${counts.resources ?? 0} resources · ${counts.marks ?? 0} marks · ${counts.measures ?? 0} measures`);
|
|
158
|
+
const slow = v.slowResources;
|
|
159
|
+
if (slow?.length) {
|
|
160
|
+
lines.push('');
|
|
161
|
+
lines.push(`## slow resources (≥ ${slowResourceMs}ms, top ${slow.length})`);
|
|
162
|
+
lines.push('| duration | initiator | size | url |');
|
|
163
|
+
lines.push('|---|---|---|---|');
|
|
164
|
+
for (const r of slow) {
|
|
165
|
+
lines.push(`| ${r.duration.toFixed(0)} ms | ${r.initiator ?? '?'} | ${r.transferSize ?? '?'} B | ${r.name.slice(0, 80)} |`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
lines.push(`(no resources with duration ≥ ${slowResourceMs}ms)`);
|
|
170
|
+
}
|
|
171
|
+
lines.push('');
|
|
172
|
+
lines.push('⚠ JS-side approximation — no CPU sampling, no flame-graph, no rendering pipeline breakdown (would need `Tracing.*` which WIP lacks). For CPU profiles consider `take_memory_snapshot` (heap) or run a Safari Web Inspector Timeline session via the macOS UI.');
|
|
173
|
+
return textResult(lines.join('\n'));
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
function textResult(text) {
|
|
177
|
+
return { content: [{ type: 'text', text }] };
|
|
178
|
+
}
|
|
179
|
+
function errorResult(text) {
|
|
180
|
+
return { content: [{ type: 'text', text }], isError: true };
|
|
181
|
+
}
|
|
182
|
+
function describe(e) {
|
|
183
|
+
return e instanceof Error ? e.message : String(e);
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=get_performance_metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get_performance_metrics.js","sourceRoot":"","sources":["../../../src/tools/get_performance_metrics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const getResourceTreeTool: {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
inputSchema: {
|
|
6
|
+
resourceUrlSubstring: z.ZodOptional<z.ZodString>;
|
|
7
|
+
maxResourcesPerFrame: z.ZodOptional<z.ZodNumber>;
|
|
8
|
+
};
|
|
9
|
+
handler: ({ resourceUrlSubstring, maxResourcesPerFrame, }: {
|
|
10
|
+
resourceUrlSubstring?: string;
|
|
11
|
+
maxResourcesPerFrame?: number;
|
|
12
|
+
}) => Promise<{
|
|
13
|
+
content: {
|
|
14
|
+
type: "text";
|
|
15
|
+
text: string;
|
|
16
|
+
}[];
|
|
17
|
+
}>;
|
|
18
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { PageSession } from '../page-session.js';
|
|
3
|
+
export const getResourceTreeTool = {
|
|
4
|
+
name: 'get_resource_tree',
|
|
5
|
+
description: [
|
|
6
|
+
'Return the frame + resource tree of the inspected iOS WebView page via WIP `Page.getResourceTree`.',
|
|
7
|
+
'Useful for multi-frame pages (iframes) — see exactly which frame loaded which resources, their URLs, mime types, sizes, and load failures.',
|
|
8
|
+
'Probe-confirmed (2026-05-16): `Page.getResourceTree` is one of the rare `Page.*` methods present on WIP. Returns the full frame hierarchy in one call.',
|
|
9
|
+
].join(' '),
|
|
10
|
+
inputSchema: {
|
|
11
|
+
resourceUrlSubstring: z
|
|
12
|
+
.string()
|
|
13
|
+
.optional()
|
|
14
|
+
.describe('Case-insensitive substring filter on resource URLs (default: include all).'),
|
|
15
|
+
maxResourcesPerFrame: z
|
|
16
|
+
.number()
|
|
17
|
+
.int()
|
|
18
|
+
.min(1)
|
|
19
|
+
.max(500)
|
|
20
|
+
.optional()
|
|
21
|
+
.describe('Cap resources rendered per frame (default 50).'),
|
|
22
|
+
},
|
|
23
|
+
handler: async ({ resourceUrlSubstring, maxResourcesPerFrame = 50, }) => {
|
|
24
|
+
let ps;
|
|
25
|
+
try {
|
|
26
|
+
ps = await PageSession.get();
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
return errorResult(`Unable to attach to a WKWebView page: ${describe(e)}`);
|
|
30
|
+
}
|
|
31
|
+
let result;
|
|
32
|
+
try {
|
|
33
|
+
result = await ps.session.send('Page.getResourceTree', undefined, 10_000);
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
return errorResult(`Page.getResourceTree failed: ${describe(e)}`);
|
|
37
|
+
}
|
|
38
|
+
const lines = [];
|
|
39
|
+
let totalFrames = 0;
|
|
40
|
+
let totalResources = 0;
|
|
41
|
+
const needle = resourceUrlSubstring?.toLowerCase();
|
|
42
|
+
const renderFrame = (node, depth) => {
|
|
43
|
+
totalFrames++;
|
|
44
|
+
const indent = ' '.repeat(depth);
|
|
45
|
+
const f = node.frame;
|
|
46
|
+
lines.push(`${indent}- frame \`${f.id}\`${f.name ? ` (name=${f.name})` : ''} · ${f.mimeType ?? '?'}`);
|
|
47
|
+
lines.push(`${indent} URL: ${f.url ?? '(no url)'}`);
|
|
48
|
+
if (f.securityOrigin)
|
|
49
|
+
lines.push(`${indent} origin: ${f.securityOrigin}`);
|
|
50
|
+
let resources = node.resources ?? [];
|
|
51
|
+
if (needle)
|
|
52
|
+
resources = resources.filter(r => r.url.toLowerCase().includes(needle));
|
|
53
|
+
const shown = resources.slice(0, maxResourcesPerFrame);
|
|
54
|
+
totalResources += resources.length;
|
|
55
|
+
if (shown.length > 0) {
|
|
56
|
+
lines.push(`${indent} resources (${shown.length}${resources.length > shown.length ? `/${resources.length} shown` : ''}):`);
|
|
57
|
+
for (const r of shown) {
|
|
58
|
+
const tag = r.failed ? '✗ failed' : '✓';
|
|
59
|
+
lines.push(`${indent} ${tag} ${r.type}${r.mimeType ? '/' + r.mimeType : ''}${r.contentSize != null ? ` · ${r.contentSize}B` : ''} · ${r.url}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
for (const child of node.childFrames ?? [])
|
|
63
|
+
renderFrame(child, depth + 1);
|
|
64
|
+
};
|
|
65
|
+
lines.push(`# get_resource_tree`);
|
|
66
|
+
lines.push('');
|
|
67
|
+
renderFrame(result.frameTree, 0);
|
|
68
|
+
lines.unshift(`Total frames: ${totalFrames} · resources${needle ? ` (filtered "${resourceUrlSubstring}")` : ''}: ${totalResources}`);
|
|
69
|
+
lines.unshift('');
|
|
70
|
+
return textResult(lines.join('\n'));
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
function textResult(text) {
|
|
74
|
+
return { content: [{ type: 'text', text }] };
|
|
75
|
+
}
|
|
76
|
+
function errorResult(text) {
|
|
77
|
+
return { content: [{ type: 'text', text }], isError: true };
|
|
78
|
+
}
|
|
79
|
+
function describe(e) {
|
|
80
|
+
return e instanceof Error ? e.message : String(e);
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=get_resource_tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get_resource_tree.js","sourceRoot":"","sources":["../../../src/tools/get_resource_tree.ts"],"names":[],"mappings":"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"}
|