@ait-co/devtools 0.1.85 → 0.1.86
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/dist/mcp/cli.js +46 -26
- package/dist/mcp/cli.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +12 -4
- package/dist/mcp/server.js.map +1 -1
- package/dist/panel/index.js +2 -2
- package/package.json +1 -1
package/dist/mcp/cli.js
CHANGED
|
@@ -3761,7 +3761,7 @@ const DEBUG_TOOL_DEFINITIONS = [
|
|
|
3761
3761
|
},
|
|
3762
3762
|
{
|
|
3763
3763
|
name: "build_attach_url",
|
|
3764
|
-
description: "The tool result already shows the QR to the user directly (Claude Code renders MCP tool output to the user's screen; they press Ctrl+O to expand if it's collapsed). Do NOT re-print or re-render the QR in your reply — that just wastes output tokens. Simply tell the user to scan the QR shown in this tool's output with their phone camera. Builds a self-attaching deep-link for the active relay environment and returns a QR code. Scan the QR with the phone camera to open the mini-app and attach it to this debug session (QR is the single entry path — no USB cable or platform CLI needed). Call list_pages first to confirm the relay/tunnel is up. If the tunnel is not up, restart: `npx @ait-co/devtools devtools-mcp`.\n\nEnvironment-specific behaviour:\n • env 3 / relay-staging (start_debug mode=\"relay-staging\"): requires scheme_url — the intoss-private://…?_deploymentId=<uuid> URL from `ait deploy --scheme-only`. Splices debug=1 + relay URL into the scheme URL to produce a self-attach deep-link.\n • env 2 / relay-sandbox (start_debug mode=\"relay-sandbox\"): scheme_url is NOT used. Instead, reads AIT_TUNNEL_BASE_URL (the https://*.trycloudflare.com app tunnel from `tunnel:{cdp:true}`) and builds a launcher PWA deep-link (https://devtools.aitc.dev/launcher/?url=…&debug=1&relay=…). When projectRoot is given, the app name from <projectRoot>/package.json is automatically added as name= so the launcher partner bar shows it. Scan the QR with the phone to open the launcher, which frames the tunnel URL and attaches CDP.\n\nSet wait_for_attach=true to block until a page attaches (
|
|
3764
|
+
description: "The tool result already shows the QR to the user directly (Claude Code renders MCP tool output to the user's screen; they press Ctrl+O to expand if it's collapsed). Do NOT re-print or re-render the QR in your reply — that just wastes output tokens. Simply tell the user to scan the QR shown in this tool's output with their phone camera. Builds a self-attaching deep-link for the active relay environment and returns a QR code. Scan the QR with the phone camera to open the mini-app and attach it to this debug session (QR is the single entry path — no USB cable or platform CLI needed). Call list_pages first to confirm the relay/tunnel is up. If the tunnel is not up, restart: `npx @ait-co/devtools devtools-mcp`.\n\nEnvironment-specific behaviour:\n • env 3 / relay-staging (start_debug mode=\"relay-staging\"): requires scheme_url — the intoss-private://…?_deploymentId=<uuid> URL from `ait deploy --scheme-only`. Splices debug=1 + relay URL into the scheme URL to produce a self-attach deep-link.\n • env 2 / relay-sandbox (start_debug mode=\"relay-sandbox\"): scheme_url is NOT used. Instead, reads AIT_TUNNEL_BASE_URL (the https://*.trycloudflare.com app tunnel from `tunnel:{cdp:true}`) and builds a launcher PWA deep-link (https://devtools.aitc.dev/launcher/?url=…&debug=1&relay=…). When projectRoot is given, the app name from <projectRoot>/package.json is automatically added as name= so the launcher partner bar shows it. Scan the QR with the phone to open the launcher, which frames the tunnel URL and attaches CDP.\n\nSet wait_for_attach=true to block until a page attaches (default 60 s, adjustable via wait_timeout_seconds). On timeout, call build_attach_url again to resume polling. The server automatically opens the QR dashboard in the OS default browser when running on a local GUI machine — headless/remote environments fall back to the text QR in the tool output.\n\nTOTP auth: when AIT_DEBUG_TOTP_SECRET is set on the MCP server, the returned attachUrl automatically includes the current one-time code (at=<code>). The code is valid for ~3 minutes (the relay gate accepts ±6 TOTP steps = 180–210 s of backwards acceptance). The response includes a `totp` field with `expiresAt` (ISO timestamp, ~3 min from issuance). If the phone scan happens after expiresAt, the relay will reject the code — just call build_attach_url again to get a fresh URL. Without AIT_DEBUG_TOTP_SECRET, the attachUrl has no expiry.\n\nselfdebug (env 2 / relay-sandbox only): pass selfdebug=true to add &selfdebug=1 to the launcher deep-link. The launcher PWA then registers its own document as the CDP target instead of the framed mini-app. SINGLE-ATTACH MODEL: attaching the launcher self-target evicts any currently-attached mini-app target — use this mode exclusively for diagnosing the launcher document itself (DOM, safe-area, console). Not applicable in env 3/4 (relay-staging/relay-live) — passing selfdebug=true there returns an error.",
|
|
3765
3765
|
inputSchema: {
|
|
3766
3766
|
type: "object",
|
|
3767
3767
|
properties: {
|
|
@@ -3771,7 +3771,11 @@ const DEBUG_TOOL_DEFINITIONS = [
|
|
|
3771
3771
|
},
|
|
3772
3772
|
wait_for_attach: {
|
|
3773
3773
|
type: "boolean",
|
|
3774
|
-
description: "If true, block after returning the QR until a page attaches to the relay (polls listTargets ~1 s interval,
|
|
3774
|
+
description: "If true, block after returning the QR until a page attaches to the relay (polls listTargets ~1 s interval, default 60 s). On attach, the response includes the attached page list. On timeout, call build_attach_url again to resume polling."
|
|
3775
|
+
},
|
|
3776
|
+
wait_timeout_seconds: {
|
|
3777
|
+
type: "number",
|
|
3778
|
+
description: "Maximum seconds to wait when wait_for_attach=true (default 60, range 1–600). Values outside the range or invalid inputs (0, negative, NaN) fall back to the default silently. Only meaningful when wait_for_attach=true."
|
|
3775
3779
|
},
|
|
3776
3780
|
projectRoot: {
|
|
3777
3781
|
type: "string",
|
|
@@ -4775,7 +4779,7 @@ async function readMcpSdkVersion() {
|
|
|
4775
4779
|
* some test environments that skip the build step).
|
|
4776
4780
|
*/
|
|
4777
4781
|
function readDevtoolsVersion() {
|
|
4778
|
-
return "0.1.
|
|
4782
|
+
return "0.1.86";
|
|
4779
4783
|
}
|
|
4780
4784
|
/**
|
|
4781
4785
|
* Derives the next recommended action from a completed diagnostics snapshot.
|
|
@@ -4851,9 +4855,14 @@ async function getDiagnostics(input) {
|
|
|
4851
4855
|
reissueAttempts: tunnel.reissueAttempts ?? 0
|
|
4852
4856
|
};
|
|
4853
4857
|
let pages = null;
|
|
4854
|
-
if (connection !== void 0)
|
|
4855
|
-
|
|
4856
|
-
|
|
4858
|
+
if (connection !== void 0) {
|
|
4859
|
+
try {
|
|
4860
|
+
await connection.refreshTargets?.();
|
|
4861
|
+
} catch {}
|
|
4862
|
+
try {
|
|
4863
|
+
pages = listPages(connection, tunnel);
|
|
4864
|
+
} catch {}
|
|
4865
|
+
}
|
|
4857
4866
|
const limit = Math.min(Math.max(1, recentErrorsLimit), 50);
|
|
4858
4867
|
const recentErrors = collector.getRecentErrors(limit);
|
|
4859
4868
|
const authRejects = collector.getAuthRejects();
|
|
@@ -5271,7 +5280,7 @@ function waitForAttachWithEvents(connection, filterFn, timeoutMs, pollIntervalMs
|
|
|
5271
5280
|
* naturally via `enableDomains`). The tier only controls visibility.
|
|
5272
5281
|
*/
|
|
5273
5282
|
function createDebugServer(deps) {
|
|
5274
|
-
const { connection, router: routerDep, aitSource, getTunnelStatus, waitForAttachTimeoutMs =
|
|
5283
|
+
const { connection, router: routerDep, aitSource, getTunnelStatus, waitForAttachTimeoutMs = 6e4, qrHttpServer, getEnvironment: getEnvDep, getEnvironmentReason: getEnvReasonDep, diagnosticsCollector: collectorDep, totpSecret, onAttachUrlBuilt } = deps;
|
|
5275
5284
|
const getTotpSecret = deps.getTotpSecret ?? (() => totpSecret);
|
|
5276
5285
|
const router = routerDep ?? makeSingleConnectionRouter(connection);
|
|
5277
5286
|
const resolveEnvironment = getEnvDep ?? (() => deriveEnvironment(router.active.kind, getLiveIntent(), router.activeRelayOrigin));
|
|
@@ -5279,7 +5288,7 @@ function createDebugServer(deps) {
|
|
|
5279
5288
|
const collector = collectorDep ?? new InMemoryDiagnosticsCollector();
|
|
5280
5289
|
const server = new Server({
|
|
5281
5290
|
name: "ait-debug",
|
|
5282
|
-
version: "0.1.
|
|
5291
|
+
version: "0.1.86"
|
|
5283
5292
|
}, { capabilities: { tools: { listChanged: true } } });
|
|
5284
5293
|
server.setRequestHandler(ListToolsRequestSchema, () => {
|
|
5285
5294
|
const conn = router.active;
|
|
@@ -5353,6 +5362,13 @@ function createDebugServer(deps) {
|
|
|
5353
5362
|
if (name === "build_attach_url") {
|
|
5354
5363
|
const waitForAttach = request.params.arguments?.wait_for_attach === true;
|
|
5355
5364
|
const selfdebug = request.params.arguments?.selfdebug === true;
|
|
5365
|
+
const rawWaitTimeout = request.params.arguments?.wait_timeout_seconds;
|
|
5366
|
+
const callTimeoutMs = (() => {
|
|
5367
|
+
if (typeof rawWaitTimeout !== "number" || !Number.isFinite(rawWaitTimeout)) return waitForAttachTimeoutMs;
|
|
5368
|
+
const clamped = Math.max(1, Math.min(600, rawWaitTimeout));
|
|
5369
|
+
if (rawWaitTimeout <= 0) return waitForAttachTimeoutMs;
|
|
5370
|
+
return Math.round(clamped) * 1e3;
|
|
5371
|
+
})();
|
|
5356
5372
|
if (selfdebug && env !== "relay-mobile") return mcpError("build_attach_url: selfdebug=true는 env 2 / relay-sandbox 전용 기능입니다. 현재 환경(env 3/4)에서는 launcher가 없어 self-target 모드를 지원하지 않습니다. launcher self-target이 필요하다면 relay-sandbox 모드로 재시작하세요.");
|
|
5357
5373
|
if (env === "relay-mobile") {
|
|
5358
5374
|
const rawBuildProjectRoot = request.params.arguments?.projectRoot;
|
|
@@ -5423,13 +5439,13 @@ function createDebugServer(deps) {
|
|
|
5423
5439
|
}] };
|
|
5424
5440
|
let attachedPagesHl = [];
|
|
5425
5441
|
try {
|
|
5426
|
-
attachedPagesHl = await waitForAttachWithEvents(conn, isMatchingPage,
|
|
5442
|
+
attachedPagesHl = await waitForAttachWithEvents(conn, isMatchingPage, callTimeoutMs);
|
|
5427
5443
|
} catch {
|
|
5428
5444
|
attachedPagesHl = conn.listTargets();
|
|
5429
5445
|
return {
|
|
5430
5446
|
content: [{
|
|
5431
5447
|
type: "text",
|
|
5432
|
-
text: buildTimeoutError(headlessText,
|
|
5448
|
+
text: buildTimeoutError(headlessText, callTimeoutMs / 1e3, attachedPagesHl)
|
|
5433
5449
|
}],
|
|
5434
5450
|
isError: true
|
|
5435
5451
|
};
|
|
@@ -5460,13 +5476,13 @@ function createDebugServer(deps) {
|
|
|
5460
5476
|
}] };
|
|
5461
5477
|
let attachedPages = [];
|
|
5462
5478
|
try {
|
|
5463
|
-
attachedPages = await waitForAttachWithEvents(conn, isMatchingPage,
|
|
5479
|
+
attachedPages = await waitForAttachWithEvents(conn, isMatchingPage, callTimeoutMs);
|
|
5464
5480
|
} catch {
|
|
5465
5481
|
attachedPages = conn.listTargets();
|
|
5466
5482
|
return {
|
|
5467
5483
|
content: [{
|
|
5468
5484
|
type: "text",
|
|
5469
|
-
text: buildTimeoutError(shortText,
|
|
5485
|
+
text: buildTimeoutError(shortText, callTimeoutMs / 1e3, attachedPages)
|
|
5470
5486
|
}],
|
|
5471
5487
|
isError: true
|
|
5472
5488
|
};
|
|
@@ -5499,13 +5515,13 @@ function createDebugServer(deps) {
|
|
|
5499
5515
|
}] };
|
|
5500
5516
|
let attachedPagesFb = [];
|
|
5501
5517
|
try {
|
|
5502
|
-
attachedPagesFb = await waitForAttachWithEvents(conn, isMatchingPage,
|
|
5518
|
+
attachedPagesFb = await waitForAttachWithEvents(conn, isMatchingPage, callTimeoutMs);
|
|
5503
5519
|
} catch {
|
|
5504
5520
|
attachedPagesFb = conn.listTargets();
|
|
5505
5521
|
return {
|
|
5506
5522
|
content: [{
|
|
5507
5523
|
type: "text",
|
|
5508
|
-
text: buildTimeoutError(baseText,
|
|
5524
|
+
text: buildTimeoutError(baseText, callTimeoutMs / 1e3, attachedPagesFb)
|
|
5509
5525
|
}],
|
|
5510
5526
|
isError: true
|
|
5511
5527
|
};
|
|
@@ -5528,13 +5544,13 @@ function createDebugServer(deps) {
|
|
|
5528
5544
|
}] };
|
|
5529
5545
|
let attachedPages = [];
|
|
5530
5546
|
try {
|
|
5531
|
-
attachedPages = await waitForAttachWithEvents(conn, isMatchingPage,
|
|
5547
|
+
attachedPages = await waitForAttachWithEvents(conn, isMatchingPage, callTimeoutMs);
|
|
5532
5548
|
} catch {
|
|
5533
5549
|
attachedPages = conn.listTargets();
|
|
5534
5550
|
return {
|
|
5535
5551
|
content: [{
|
|
5536
5552
|
type: "text",
|
|
5537
|
-
text: buildTimeoutError(baseText,
|
|
5553
|
+
text: buildTimeoutError(baseText, callTimeoutMs / 1e3, attachedPages)
|
|
5538
5554
|
}],
|
|
5539
5555
|
isError: true
|
|
5540
5556
|
};
|
|
@@ -5594,13 +5610,13 @@ function createDebugServer(deps) {
|
|
|
5594
5610
|
}] };
|
|
5595
5611
|
let attachedPagesHl = [];
|
|
5596
5612
|
try {
|
|
5597
|
-
attachedPagesHl = await waitForAttachWithEvents(conn, isMatchingPage,
|
|
5613
|
+
attachedPagesHl = await waitForAttachWithEvents(conn, isMatchingPage, callTimeoutMs);
|
|
5598
5614
|
} catch {
|
|
5599
5615
|
attachedPagesHl = conn.listTargets();
|
|
5600
5616
|
return {
|
|
5601
5617
|
content: [{
|
|
5602
5618
|
type: "text",
|
|
5603
|
-
text: buildTimeoutError(headlessText,
|
|
5619
|
+
text: buildTimeoutError(headlessText, callTimeoutMs / 1e3, attachedPagesHl)
|
|
5604
5620
|
}],
|
|
5605
5621
|
isError: true
|
|
5606
5622
|
};
|
|
@@ -5631,13 +5647,13 @@ function createDebugServer(deps) {
|
|
|
5631
5647
|
}] };
|
|
5632
5648
|
let attachedPages = [];
|
|
5633
5649
|
try {
|
|
5634
|
-
attachedPages = await waitForAttachWithEvents(conn, isMatchingPage,
|
|
5650
|
+
attachedPages = await waitForAttachWithEvents(conn, isMatchingPage, callTimeoutMs);
|
|
5635
5651
|
} catch {
|
|
5636
5652
|
attachedPages = conn.listTargets();
|
|
5637
5653
|
return {
|
|
5638
5654
|
content: [{
|
|
5639
5655
|
type: "text",
|
|
5640
|
-
text: buildTimeoutError(shortText,
|
|
5656
|
+
text: buildTimeoutError(shortText, callTimeoutMs / 1e3, attachedPages)
|
|
5641
5657
|
}],
|
|
5642
5658
|
isError: true
|
|
5643
5659
|
};
|
|
@@ -5671,13 +5687,13 @@ ${browserResult.httpUrl}\n또는 PNG로 받기: ${browserResult.pngUrl}` + stder
|
|
|
5671
5687
|
}] };
|
|
5672
5688
|
let attachedPagesFb = [];
|
|
5673
5689
|
try {
|
|
5674
|
-
attachedPagesFb = await waitForAttachWithEvents(conn, isMatchingPage,
|
|
5690
|
+
attachedPagesFb = await waitForAttachWithEvents(conn, isMatchingPage, callTimeoutMs);
|
|
5675
5691
|
} catch {
|
|
5676
5692
|
attachedPagesFb = conn.listTargets();
|
|
5677
5693
|
return {
|
|
5678
5694
|
content: [{
|
|
5679
5695
|
type: "text",
|
|
5680
|
-
text: buildTimeoutError(baseText,
|
|
5696
|
+
text: buildTimeoutError(baseText, callTimeoutMs / 1e3, attachedPagesFb)
|
|
5681
5697
|
}],
|
|
5682
5698
|
isError: true
|
|
5683
5699
|
};
|
|
@@ -5700,13 +5716,13 @@ ${browserResult.httpUrl}\n또는 PNG로 받기: ${browserResult.pngUrl}` + stder
|
|
|
5700
5716
|
}] };
|
|
5701
5717
|
let attachedPages = [];
|
|
5702
5718
|
try {
|
|
5703
|
-
attachedPages = await waitForAttachWithEvents(conn, isMatchingPage,
|
|
5719
|
+
attachedPages = await waitForAttachWithEvents(conn, isMatchingPage, callTimeoutMs);
|
|
5704
5720
|
} catch {
|
|
5705
5721
|
attachedPages = conn.listTargets();
|
|
5706
5722
|
return {
|
|
5707
5723
|
content: [{
|
|
5708
5724
|
type: "text",
|
|
5709
|
-
text: buildTimeoutError(baseText,
|
|
5725
|
+
text: buildTimeoutError(baseText, callTimeoutMs / 1e3, attachedPages)
|
|
5710
5726
|
}],
|
|
5711
5727
|
isError: true
|
|
5712
5728
|
};
|
|
@@ -7111,7 +7127,11 @@ const DEV_TOOL_DEFINITIONS = [
|
|
|
7111
7127
|
},
|
|
7112
7128
|
wait_for_attach: {
|
|
7113
7129
|
type: "boolean",
|
|
7114
|
-
description: "If true, block until a page attaches."
|
|
7130
|
+
description: "If true, block until a page attaches (default 60 s)."
|
|
7131
|
+
},
|
|
7132
|
+
wait_timeout_seconds: {
|
|
7133
|
+
type: "number",
|
|
7134
|
+
description: "Maximum seconds to wait when wait_for_attach=true (default 60, range 1–600). Invalid inputs fall back to default."
|
|
7115
7135
|
}
|
|
7116
7136
|
},
|
|
7117
7137
|
required: ["scheme_url"]
|
|
@@ -7322,7 +7342,7 @@ function createDevServer(deps = {}) {
|
|
|
7322
7342
|
const aitSource = deps.aitSource ?? new HttpAitSource({ stateEndpoint });
|
|
7323
7343
|
const server = new Server({
|
|
7324
7344
|
name: "ait-devtools",
|
|
7325
|
-
version: "0.1.
|
|
7345
|
+
version: "0.1.86"
|
|
7326
7346
|
}, { capabilities: { tools: {} } });
|
|
7327
7347
|
server.setRequestHandler(ListToolsRequestSchema, () => ({ tools: DEV_TOOL_DEFINITIONS.map((tool) => ({ ...tool })) }));
|
|
7328
7348
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|