cdp-toolkit 1.4.0 → 1.7.0

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/src/manifest.ts CHANGED
@@ -25,13 +25,13 @@ export interface ToolSpec {
25
25
  export const MANIFEST: ToolSpec[] = [
26
26
  {
27
27
  "name": "list_pages",
28
- "description": "Enumerate browser page targets via the CDP browser endpoint (GET /json/list). By default returns only page-type tabs; set 'all' to also include workers and background pages. Each entry carries the targetId used as a target selector elsewhere, plus an 'origin' field recording where the tab came from: 'agent' means this toolkit created it (the entry then also carries the creating 'label' and 'createdAt'), and this stays true after the creating agent releases its lease or dies, which is what makes a stray agent tab findable later. 'unknown' means there is no creation record. It never says 'human': the toolkit cannot prove a person opened a tab, so 'unknown' is the honest word for a tab it did not create, one opened before the toolkit ran, or one whose record could not be written. A tab whose record exists but could not be read reports origin 'unknown' plus 'originUnreadable', so a broken record is never mistaken for no record.",
28
+ "description": "Enumerate browser page targets via the CDP browser endpoint (GET /json/list). By default returns only page-type tabs; set 'all' to also include workers and background pages. Each entry carries the targetId used as a target selector elsewhere, plus an 'origin' field recording where the tab came from: 'agent' means this toolkit created it (the entry then also carries the creating 'label' and 'createdAt'), and this stays true after the creating agent releases its lease or dies, which is what makes a stray agent tab findable later. 'unknown' means there is no creation record. It never says 'human': the toolkit cannot prove a person opened a tab, so 'unknown' is the honest word for a tab it did not create, one opened before the toolkit ran, or one whose record could not be written. A tab whose record exists but could not be read reports origin 'unknown' plus 'originUnreadable', so a broken record is never mistaken for no record. Under CDP_REQUIRE_LEASE this call also reaps: a tab this toolkit created whose lease is stale because the owning process died or the TTL elapsed is closed, and the closed tabs are reported in an additive 'reaped' array ({targetId,label,reason}) that is present only when something was actually closed. A tab with no lease is never reaped, so tabs opened by a caller that never uses leases are untouched.",
29
29
  "inputSchema": {
30
30
  "type": "object",
31
31
  "properties": {
32
32
  "lease": {
33
33
  "type": "string",
34
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
34
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
35
35
  },
36
36
  "all": {
37
37
  "type": "boolean",
@@ -50,7 +50,7 @@ export const MANIFEST: ToolSpec[] = [
50
50
  "properties": {
51
51
  "lease": {
52
52
  "type": "string",
53
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
53
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
54
54
  },
55
55
  "url": {
56
56
  "type": "string",
@@ -58,7 +58,7 @@ export const MANIFEST: ToolSpec[] = [
58
58
  },
59
59
  "claim": {
60
60
  "type": "boolean",
61
- "description": "Claim the new tab atomically as part of creating it and return a lease token alongside {targetId,url}. Default false, which is byte-identical to the pre-1.2 behavior."
61
+ "description": "Claim the new tab atomically as part of creating it and return a lease token alongside {targetId,url}. Default false, which is byte-identical to the pre-1.2 behavior. Under CDP_REQUIRE_LEASE the new tab is claimed and a lease returned even without claim:true, because a tab nobody holds is a tab nobody may drive; passing claim:true additionally makes the lease an explicit one, which requires its token on every later call even from this same process."
62
62
  },
63
63
  "label": {
64
64
  "type": "string",
@@ -81,7 +81,7 @@ export const MANIFEST: ToolSpec[] = [
81
81
  "properties": {
82
82
  "lease": {
83
83
  "type": "string",
84
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
84
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
85
85
  },
86
86
  "target": {
87
87
  "type": "string",
@@ -102,7 +102,7 @@ export const MANIFEST: ToolSpec[] = [
102
102
  "properties": {
103
103
  "lease": {
104
104
  "type": "string",
105
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
105
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
106
106
  },
107
107
  "target": {
108
108
  "type": "string",
@@ -123,7 +123,7 @@ export const MANIFEST: ToolSpec[] = [
123
123
  "properties": {
124
124
  "lease": {
125
125
  "type": "string",
126
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
126
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
127
127
  },
128
128
  "target": {
129
129
  "type": "string",
@@ -165,7 +165,7 @@ export const MANIFEST: ToolSpec[] = [
165
165
  "properties": {
166
166
  "lease": {
167
167
  "type": "string",
168
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
168
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
169
169
  },
170
170
  "target": {
171
171
  "type": "string",
@@ -198,7 +198,7 @@ export const MANIFEST: ToolSpec[] = [
198
198
  "properties": {
199
199
  "lease": {
200
200
  "type": "string",
201
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
201
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
202
202
  },
203
203
  "target": {
204
204
  "type": "string",
@@ -235,7 +235,7 @@ export const MANIFEST: ToolSpec[] = [
235
235
  "properties": {
236
236
  "lease": {
237
237
  "type": "string",
238
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs."
238
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
239
239
  },
240
240
  "target": {
241
241
  "type": "string",
@@ -266,7 +266,7 @@ export const MANIFEST: ToolSpec[] = [
266
266
  "properties": {
267
267
  "lease": {
268
268
  "type": "string",
269
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs."
269
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
270
270
  },
271
271
  "target": {
272
272
  "type": "string",
@@ -322,7 +322,7 @@ export const MANIFEST: ToolSpec[] = [
322
322
  "properties": {
323
323
  "lease": {
324
324
  "type": "string",
325
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs."
325
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
326
326
  },
327
327
  "target": {
328
328
  "type": "string",
@@ -357,7 +357,7 @@ export const MANIFEST: ToolSpec[] = [
357
357
  "properties": {
358
358
  "lease": {
359
359
  "type": "string",
360
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
360
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
361
361
  },
362
362
  "target": {
363
363
  "type": "string",
@@ -380,7 +380,7 @@ export const MANIFEST: ToolSpec[] = [
380
380
  "properties": {
381
381
  "lease": {
382
382
  "type": "string",
383
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
383
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
384
384
  },
385
385
  "target": {
386
386
  "type": "string",
@@ -420,7 +420,7 @@ export const MANIFEST: ToolSpec[] = [
420
420
  "properties": {
421
421
  "lease": {
422
422
  "type": "string",
423
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
423
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
424
424
  },
425
425
  "target": {
426
426
  "type": "string",
@@ -447,7 +447,7 @@ export const MANIFEST: ToolSpec[] = [
447
447
  "properties": {
448
448
  "lease": {
449
449
  "type": "string",
450
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
450
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
451
451
  },
452
452
  "target": {
453
453
  "type": "string",
@@ -499,7 +499,7 @@ export const MANIFEST: ToolSpec[] = [
499
499
  "properties": {
500
500
  "lease": {
501
501
  "type": "string",
502
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
502
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
503
503
  },
504
504
  "target": {
505
505
  "type": "string",
@@ -532,7 +532,7 @@ export const MANIFEST: ToolSpec[] = [
532
532
  "properties": {
533
533
  "lease": {
534
534
  "type": "string",
535
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
535
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
536
536
  },
537
537
  "target": {
538
538
  "type": "string",
@@ -578,7 +578,7 @@ export const MANIFEST: ToolSpec[] = [
578
578
  "properties": {
579
579
  "lease": {
580
580
  "type": "string",
581
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
581
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
582
582
  },
583
583
  "target": {
584
584
  "type": "string",
@@ -611,7 +611,7 @@ export const MANIFEST: ToolSpec[] = [
611
611
  "properties": {
612
612
  "lease": {
613
613
  "type": "string",
614
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
614
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
615
615
  },
616
616
  "target": {
617
617
  "type": "string",
@@ -643,7 +643,7 @@ export const MANIFEST: ToolSpec[] = [
643
643
  "properties": {
644
644
  "lease": {
645
645
  "type": "string",
646
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
646
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
647
647
  },
648
648
  "target": {
649
649
  "type": "string",
@@ -682,7 +682,7 @@ export const MANIFEST: ToolSpec[] = [
682
682
  "properties": {
683
683
  "lease": {
684
684
  "type": "string",
685
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
685
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
686
686
  },
687
687
  "target": {
688
688
  "type": "string",
@@ -733,7 +733,7 @@ export const MANIFEST: ToolSpec[] = [
733
733
  "properties": {
734
734
  "lease": {
735
735
  "type": "string",
736
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
736
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
737
737
  },
738
738
  "target": {
739
739
  "type": "string",
@@ -833,7 +833,7 @@ export const MANIFEST: ToolSpec[] = [
833
833
  "properties": {
834
834
  "lease": {
835
835
  "type": "string",
836
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
836
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
837
837
  },
838
838
  "target": {
839
839
  "type": "string",
@@ -871,7 +871,7 @@ export const MANIFEST: ToolSpec[] = [
871
871
  "properties": {
872
872
  "lease": {
873
873
  "type": "string",
874
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
874
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
875
875
  },
876
876
  "target": {
877
877
  "type": "string",
@@ -908,7 +908,7 @@ export const MANIFEST: ToolSpec[] = [
908
908
  "properties": {
909
909
  "lease": {
910
910
  "type": "string",
911
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
911
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
912
912
  },
913
913
  "target": {
914
914
  "type": "string",
@@ -935,7 +935,7 @@ export const MANIFEST: ToolSpec[] = [
935
935
  "properties": {
936
936
  "lease": {
937
937
  "type": "string",
938
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
938
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
939
939
  },
940
940
  "target": {
941
941
  "type": "string",
@@ -958,7 +958,7 @@ export const MANIFEST: ToolSpec[] = [
958
958
  "properties": {
959
959
  "lease": {
960
960
  "type": "string",
961
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
961
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
962
962
  },
963
963
  "target": {
964
964
  "type": "string",
@@ -989,7 +989,7 @@ export const MANIFEST: ToolSpec[] = [
989
989
  "properties": {
990
990
  "lease": {
991
991
  "type": "string",
992
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
992
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
993
993
  },
994
994
  "target": {
995
995
  "type": "string",
@@ -1024,7 +1024,7 @@ export const MANIFEST: ToolSpec[] = [
1024
1024
  "properties": {
1025
1025
  "lease": {
1026
1026
  "type": "string",
1027
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
1027
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
1028
1028
  },
1029
1029
  "target": {
1030
1030
  "type": "string",
@@ -1050,7 +1050,7 @@ export const MANIFEST: ToolSpec[] = [
1050
1050
  "properties": {
1051
1051
  "lease": {
1052
1052
  "type": "string",
1053
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
1053
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
1054
1054
  },
1055
1055
  "target": {
1056
1056
  "type": "string",
@@ -1069,7 +1069,7 @@ export const MANIFEST: ToolSpec[] = [
1069
1069
  "properties": {
1070
1070
  "lease": {
1071
1071
  "type": "string",
1072
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
1072
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
1073
1073
  },
1074
1074
  "tracePath": {
1075
1075
  "type": "string",
@@ -1088,7 +1088,7 @@ export const MANIFEST: ToolSpec[] = [
1088
1088
  "properties": {
1089
1089
  "lease": {
1090
1090
  "type": "string",
1091
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
1091
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
1092
1092
  },
1093
1093
  "target": {
1094
1094
  "type": "string",
@@ -1118,6 +1118,76 @@ export const MANIFEST: ToolSpec[] = [
1118
1118
  "additionalProperties": false
1119
1119
  }
1120
1120
  },
1121
+ {
1122
+ "name": "start_screen_recording",
1123
+ "description": "Start recording the target tab to video over raw CDP (Page.startScreencast), holding one persistent connection open and spooling every Page.screencastFrame to disk. Chrome emits a frame ON REPAINT, not on a clock, so the stream is variable-rate: each frame is timestamped into a ledger and stop_screen_recording turns those timestamps into per-frame display durations, which is what makes a still page hold one long frame instead of the video racing or freezing. Every frame is acked immediately (an unacked frame stalls the stream). ffmpeg is probed here, not at stop, so a missing encoder fails before a recording is captured and thrown away. Must be paired with stop_screen_recording WITHIN THE SAME PROCESS (the frames are events on this connection and cannot be re-attached from another process, so the pair works under the MCP server, not the one-process-per-call CLI). Throws if a recording is already in progress for the target; recordings on DIFFERENT targets run concurrently. Chrome only: WebDriver BiDi has no screencast primitive, so both tools are absent under --browser firefox.",
1124
+ "inputSchema": {
1125
+ "type": "object",
1126
+ "properties": {
1127
+ "lease": {
1128
+ "type": "string",
1129
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
1130
+ },
1131
+ "target": {
1132
+ "type": "string",
1133
+ "description": "Target page selector: 'active' (default) | 'index:N' | 'url:<substr>' | 'title:<substr>' | '<targetId>'."
1134
+ },
1135
+ "format": {
1136
+ "type": "string",
1137
+ "enum": [
1138
+ "jpeg",
1139
+ "png"
1140
+ ],
1141
+ "description": "Frame image format. Defaults to jpeg (far smaller per repaint); png is lossless. quality applies to jpeg only."
1142
+ },
1143
+ "quality": {
1144
+ "type": "number",
1145
+ "description": "JPEG frame quality 0-100. Ignored for png. Omitted by default, which leaves Chrome's own default in place."
1146
+ },
1147
+ "maxWidth": {
1148
+ "type": "number",
1149
+ "description": "Cap the streamed frame width in pixels. Also the way to pin frame size if the viewport might change mid-recording."
1150
+ },
1151
+ "maxHeight": {
1152
+ "type": "number",
1153
+ "description": "Cap the streamed frame height in pixels."
1154
+ },
1155
+ "everyNthFrame": {
1156
+ "type": "number",
1157
+ "description": "Capture only every Nth repaint (1 = every frame). Reduces spool size on a busy page; per-frame durations keep playback at wallclock speed either way."
1158
+ },
1159
+ "bringToFront": {
1160
+ "type": "boolean",
1161
+ "description": "Activate the tab (Page.bringToFront) before recording. Default false. A fully backgrounded or occluded tab may never repaint, and a recording of one captures 0 frames."
1162
+ }
1163
+ },
1164
+ "required": [],
1165
+ "additionalProperties": false
1166
+ }
1167
+ },
1168
+ {
1169
+ "name": "stop_screen_recording",
1170
+ "description": "Stop the recording started by start_screen_recording, assemble the spooled frames into an MP4 with ffmpeg using PER-FRAME durations from the ledger (frame N is held until frame N+1 painted; the last frame is held until this call), and return {path,bytes,durationMs,frameCount,encodedFrames,codec,encoder,width,height,droppedFrames,target}. Encoder ladder, probed once at start: hevc_videotoolbox then h264_videotoolbox then libx265 then libx264, with -tag:v hvc1 on HEVC so QuickTime plays it, +faststart, yuv420p, and even dimensions forced. With one recording in flight 'target' may be omitted; with several it is required, because guessing which to stop can lose another agent's recording. Throws if nothing is recording in this process, and throws rather than writing a silent empty video when 0 frames arrived. On an ffmpeg failure the spooled frames are KEPT and the spool path plus the exact command are named in the error. Encoded video tops out at 25 fps: ffmpeg's concat demuxer represents image timestamps on a 1/25s grid, so frames captured less than 40ms apart are coalesced deliberately (frameCount reports what was captured, encodedFrames what reached the video) instead of being dropped silently by ffmpeg. durationMs is the sum of the encoded durations; the file itself runs one 40ms step longer, because the concat demuxer needs the final frame repeated for its hold to count.",
1171
+ "inputSchema": {
1172
+ "type": "object",
1173
+ "properties": {
1174
+ "lease": {
1175
+ "type": "string",
1176
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
1177
+ },
1178
+ "target": {
1179
+ "type": "string",
1180
+ "description": "Which recording to stop: 'active' (default, valid only when exactly one recording is in flight) | 'index:N' | 'url:<substr>' | 'title:<substr>' | '<targetId>'."
1181
+ },
1182
+ "savePath": {
1183
+ "type": "string",
1184
+ "description": "Override the output file path. Default: /tmp/cdp-toolkit/screen-recording-<targetIdShort>-<stamp>.mp4."
1185
+ }
1186
+ },
1187
+ "required": [],
1188
+ "additionalProperties": false
1189
+ }
1190
+ },
1121
1191
  {
1122
1192
  "name": "take_heapsnapshot",
1123
1193
  "description": "Capture a V8 heap snapshot of the selected page target over raw CDP (HeapProfiler.takeHeapSnapshot, accumulating addHeapSnapshotChunk events) and write it as a .heapsnapshot JSON file loadable by the DevTools Memory panel; returns {path,bytes,chunks,target} only and does not parse/summarize the snapshot. Writes under /tmp/cdp-toolkit (CDP_ARTIFACT_DIR) unless savePath is given.",
@@ -1126,7 +1196,7 @@ export const MANIFEST: ToolSpec[] = [
1126
1196
  "properties": {
1127
1197
  "lease": {
1128
1198
  "type": "string",
1129
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
1199
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
1130
1200
  },
1131
1201
  "target": {
1132
1202
  "type": "string",
@@ -1149,7 +1219,7 @@ export const MANIFEST: ToolSpec[] = [
1149
1219
  "properties": {
1150
1220
  "lease": {
1151
1221
  "type": "string",
1152
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
1222
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
1153
1223
  },
1154
1224
  "url": {
1155
1225
  "type": "string",
@@ -1193,7 +1263,7 @@ export const MANIFEST: ToolSpec[] = [
1193
1263
  "properties": {
1194
1264
  "lease": {
1195
1265
  "type": "string",
1196
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
1266
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
1197
1267
  },
1198
1268
  "target": {
1199
1269
  "type": "string",
@@ -1263,7 +1333,7 @@ export const MANIFEST: ToolSpec[] = [
1263
1333
  "properties": {
1264
1334
  "lease": {
1265
1335
  "type": "string",
1266
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
1336
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
1267
1337
  },
1268
1338
  "target": {
1269
1339
  "type": "string",
@@ -1282,7 +1352,7 @@ export const MANIFEST: ToolSpec[] = [
1282
1352
  "properties": {
1283
1353
  "lease": {
1284
1354
  "type": "string",
1285
- "description": "Opaque lease token from claim_page. Required only when the tab this call resolves to is leased by someone; omit it for unleased tabs, which behave exactly as before."
1355
+ "description": "Opaque lease token from claim_page. Omit it for a tab this process already holds: under CDP_REQUIRE_LEASE the gate acquires a lease automatically and one acquired that way passes for any later call from the same process. Required when the tab is held by ANOTHER process, and required for a tab claimed explicitly via claim_page or new_page{claim:true}, which always demands its own token. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all."
1286
1356
  },
1287
1357
  "target": {
1288
1358
  "type": "string",
@@ -1299,17 +1369,21 @@ export const MANIFEST: ToolSpec[] = [
1299
1369
  },
1300
1370
  {
1301
1371
  "name": "claim_page",
1302
- "description": "Take exclusive ownership of a browser tab and return an opaque lease token. With no targetId, opens a fresh tab (optionally at url) and claims it, so 'give me my own tab' is one call. Any later tool call against a leased tab must carry the matching token in its 'lease' argument or it is refused, naming the holder. The lease is reclaimable once its owning process dies, its ttlMs elapses without use, or its tab is closed. Refused from the CLI: a CLI invocation is one process per call, so its lease would be reclaimable immediately.",
1372
+ "description": "Take exclusive ownership of a browser tab and return an opaque lease token. Two modes. FRESH TAB: with no target and no targetId, opens a new tab (optionally at url) and claims it, so 'give me my own tab' is one call. TAKEOVER: with target, claims a tab that is already open — this is how you work in a tab the human already has open when they ask you to, instead of opening your own — resolving any target selector against the live page list and never creating anything. The answer's 'opened' flag says which happened (true only when this call created the tab), and that same creation record is what release_page consults, so a tab you took over is left open when you release it. Any later tool call against a leased tab must carry the matching token in its 'lease' argument or it is refused, naming the holder. The lease is reclaimable once its owning process dies, its ttlMs elapses without use, or its tab is closed. Refused from the CLI: a CLI invocation is one process per call, so its lease would be reclaimable immediately.",
1303
1373
  "inputSchema": {
1304
1374
  "type": "object",
1305
1375
  "properties": {
1376
+ "target": {
1377
+ "type": "string",
1378
+ "description": "Take over an already-open tab, e.g. one the human has open, when asked to: pass any target selector — active | index:N | url:<substr> | title:<substr> | <targetId>. Resolved against the live page list only, so it NEVER opens a tab: a selector that matches nothing is an error, not a new blank tab. The tab is left open on release because the toolkit did not create it. Refused if another live process holds it, including a lease the gate acquired for that process automatically under CDP_REQUIRE_LEASE: this takes over unleased (human) tabs and never steals one from a live agent. Mutually exclusive with targetId."
1379
+ },
1306
1380
  "targetId": {
1307
1381
  "type": "string",
1308
- "description": "Claim this already-open page target instead of opening a new tab. Must be an exact target id, not a selector."
1382
+ "description": "Claim this already-open page target instead of opening a new tab. Must be an exact target id, not a selector. Kept for back-compat: prefer 'target', which accepts an exact id too plus every other selector form. Mutually exclusive with target."
1309
1383
  },
1310
1384
  "url": {
1311
1385
  "type": "string",
1312
- "description": "When opening a fresh tab, navigate it here. Ignored when targetId is given."
1386
+ "description": "When opening a fresh tab, navigate it here. Ignored when target or targetId is given, since both of those claim a tab that is already open."
1313
1387
  },
1314
1388
  "label": {
1315
1389
  "type": "string",
@@ -1326,24 +1400,30 @@ export const MANIFEST: ToolSpec[] = [
1326
1400
  },
1327
1401
  {
1328
1402
  "name": "release_page",
1329
- "description": "Release a held lease, given its token. Idempotent: releasing an already-released, reclaimed, or expired lease reports released:false rather than erroring. Does not close the tab.",
1403
+ "description": "Give a lease back, and close the tab if this toolkit opened it. Takes exactly one of 'lease' (the token claim_page returned) or 'target' (a selector for a tab this process holds, which is how you release a lease the gate acquired for you automatically, since that path never hands you a token). A tab with a creation record from this toolkit is closed; a tab that was already open and merely claimed is released and left alone. Override either way with 'close'. Idempotent: an already-released, reclaimed, or expired lease reports released:false, and a release that did not happen never closes anything, because by then the tab may belong to another agent. Answers {released, closed, targetId}.",
1330
1404
  "inputSchema": {
1331
1405
  "type": "object",
1332
1406
  "properties": {
1333
1407
  "lease": {
1334
1408
  "type": "string",
1335
- "description": "The opaque token claim_page (or new_page with claim:true) returned."
1409
+ "description": "The opaque token claim_page (or new_page with claim:true) returned. Mutually exclusive with 'target'. Under CDP_REQUIRE_LEASE a lease the gate acquired for you automatically never produced a token in the first place, so give 'target' instead."
1410
+ },
1411
+ "target": {
1412
+ "type": "string",
1413
+ "description": "Target selector for a tab this process holds: active | index:N | url:<substr> | title:<substr> | <targetId>. Mutually exclusive with 'lease'. Refused if another process holds the tab."
1414
+ },
1415
+ "close": {
1416
+ "type": "boolean",
1417
+ "description": "Force the close decision instead of letting the creation ledger decide. true closes even a tab this toolkit did not open; false keeps an agent-created tab open. Omit for the default, which closes only tabs this toolkit created."
1336
1418
  }
1337
1419
  },
1338
- "required": [
1339
- "lease"
1340
- ],
1420
+ "required": [],
1341
1421
  "additionalProperties": false
1342
1422
  }
1343
1423
  },
1344
1424
  {
1345
1425
  "name": "list_leases",
1346
- "description": "Enumerate every active lease for diagnosis: backend, target id, agent label, pid, createdAt, lastUsedAt, ttlMs, whether the owning process is still alive, and whether the lease is reclaimable and why. Requires no token. Never returns the lease nonce, so this cannot be used to forge a token. A row for a lease file that could not be read or parsed instead carries `unreadable` (the errno, or \"unparseable\"), with label, pid, and the timestamp fields as zero placeholders and stale always false, since stale is what marks a lease free to take and an unreadable one must never read that way.",
1426
+ "description": "Enumerate every active lease for diagnosis: backend, target id, agent label, pid, createdAt, lastUsedAt, ttlMs, whether the owning process is still alive, and whether the lease is reclaimable and why. Requires no token. Never returns the lease nonce, so this cannot be used to forge a token. A row for a lease file that could not be read or parsed instead carries `unreadable` (the errno, or \"unparseable\"), with label, pid, and the timestamp fields as zero placeholders and stale always false, since stale is what marks a lease free to take and an unreadable one must never read that way. Under CDP_REQUIRE_LEASE this call reaps abandoned agent tabs exactly as list_pages does, reporting them in an additive 'reaped' array and omitting their rows from the listing.",
1347
1427
  "inputSchema": {
1348
1428
  "type": "object",
1349
1429
  "properties": {},
package/src/mcp.ts CHANGED
@@ -21,9 +21,9 @@ import { MANIFEST } from "./manifest.ts";
21
21
  import { resolveBrowserKind, stripBrowserFlag, getOrCreateFirefoxSession, disposeFirefoxSession } from "./backend.ts";
22
22
  import { toolAvailability } from "./capabilities.ts";
23
23
  import { FIREFOX_TOOLS } from "./firefox-tools.ts";
24
- import { leaseFromArgs, withLeaseScope } from "./leases.ts";
24
+ import { leaseFromArgs, markLongLivedProcess, withLeaseScope } from "./leases.ts";
25
25
 
26
- const VERSION = "1.4.0";
26
+ const VERSION = "1.7.0";
27
27
 
28
28
  // --browser is read once at startup (MCP has no per-call notion of backend): explicit flag,
29
29
  // else CDP_BROWSER env var, else "chrome" (zero behavior change for existing users/configs).
@@ -100,6 +100,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
100
100
  });
101
101
 
102
102
  auditCoverage();
103
+ // This process is the long-lived MCP server, which is what makes strict mode
104
+ // (CDP_REQUIRE_LEASE) safe to honor here and unsafe in cli.ts. See requireLease.
105
+ markLongLivedProcess();
103
106
  await server.connect(new StdioServerTransport());
104
107
  console.error(`[cdp-toolkit] MCP server v${VERSION} ready, browser=${BROWSER}, ${AVAILABILITY.available.length} tools, CDP_BASE=${BASE}`);
105
108