@mmerterden/multi-agent-toolkit-mcp 3.14.0 → 3.15.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/CHANGELOG.md CHANGED
@@ -15,10 +15,199 @@ Releases before this file exists are recorded in the git tags and commit history
15
15
 
16
16
  ---
17
17
 
18
- ## Unreleased
18
+ ## [3.15.0] - 2026-09-25
19
+
20
+ ### Changed
21
+
22
+ - **Requires Node.js 22.13 or later** (`engines`, README, CI matrix 22 and 24).
23
+ The context index uses `node:sqlite`, which is unflagged from 22.13, and
24
+ Node 20 is past end of life. The context module is now imported on first use,
25
+ so on a Node without `node:sqlite` the server still starts and only
26
+ `context_*` and crawl indexing answer with the reason.
27
+ - **`web_goto` applies `user_agent`.** It was accepted and ignored. It is now
28
+ set on the browser context, so requests and `navigator.userAgent` agree; a
29
+ different value starts a fresh context (cookies, storage and tabs of the old
30
+ one are discarded), and omitting it keeps the current one.
31
+ - **`web_crawl` identifies itself** with a `multi-agent-toolkit-mcp/<version>`
32
+ User-Agent on every request it makes, as its description already said.
33
+ - **Research results share one shape.** `research_search` over Perplexity now
34
+ returns the same title/url/snippet blocks as Brave, and `limit` is capped at
35
+ 20, the most Brave returns per request.
36
+ - **`additionalProperties: false` is enforced** at the call boundary for the
37
+ schemas that declare it (the `security_*` tools, `design_scenario_inventory`,
38
+ `design_component_variants`): an undeclared argument is an error instead of
39
+ being ignored. Declared object fields are checked at every depth, so a
40
+ misspelt field inside an array item or a nested object is refused too.
41
+ - **`design_scenario_inventory` counts a `*Outcome` / `*Scenario` / `*MockCase`
42
+ type only with debug evidence.** The suffix alone also matches production
43
+ service results, whose cases no debug switch can reach. A type is a target
44
+ when it is declared under `#if DEBUG` or in an Android debug/mock source set,
45
+ referenced only from debug/mock code, or read from a runtime key (launch
46
+ argument, UserDefaults, SharedPreferences, intent extra). Test targets are
47
+ neutral. Every decision is returned: `acceptedSelectors[]` with the rule that
48
+ admitted it (also on each target as `evidence.basis`), `rejectedSelectors[]`
49
+ with the production references that disqualified it.
50
+
51
+ ### Added
52
+
53
+ - **`design_component_variants`** (tool 118): resolves design nodes to their
54
+ component set and variants from Figma data the caller already fetched - a
55
+ REST `/v1/files/:key/nodes` response or MCP `get_metadata` XML per file, plus
56
+ the library's `component_sets` listing to locate a set in another file. Walks
57
+ instance -> main component -> set -> variants and returns, per variant, its
58
+ properties, frame, a geometry-only `figma_spec`, the render to fetch and the
59
+ Code Connect name from a supplied mapping. Audited states are matched to
60
+ variants by how much of the state's wording a variant name covers, so a
61
+ one-word state such as `Error` matches `State=Error, Size=L`; ambiguous or
62
+ distant matches are listed, never assigned. A node id is looked up in the
63
+ file that referenced it first, and `node_ids` accepts `fileKey/nodeId` to pick
64
+ one of several sources that use the same id. Code Connect URLs with a
65
+ percent-encoded `node-id` are read.
66
+ `needs[]` and `rendersNeeded[]` name what is still to fetch. Comparing the
67
+ live component region against its matched variant removes fixture row-count
68
+ differences from the geometry findings.
69
+ - **`design_visual_compare` `component`**: the component a capture region
70
+ belongs to; stamped onto every finding that names none, so `design_report`
71
+ renders the main component link and one thumbnail per variant. A variant
72
+ without a render shows a "not rendered" placeholder instead of a broken image.
73
+ - **`design_scenario_inventory` `targets_file` / `targets[]`**: supply the
74
+ target set from an external catalog (a bare array, or `{ version: 1,
75
+ platform?, description?, targets }`, each target in the shape the tool
76
+ returns). Source scanning is skipped; `plan`, `groups`, `relaunchCount`, the
77
+ coverage gate, `extra_targets` and `ignore_targets` work unchanged. Unknown
78
+ fields, a driver missing the field its type needs, and duplicate ids are
79
+ refused. The 400-target cap applies to source scanning only: a catalog, config
80
+ extras and extra launch args are kept whole, and `truncated` is set only when
81
+ a scan found more targets than the cap, not exactly as many.
82
+ - **`design_report` roll-up mode** (`modules[]`): one row per module with
83
+ coverage, gate, deviations and a link to its report (rendered into
84
+ `<out_dir>/<module>/` unless `href` is given). Each module runs through the
85
+ coverage gate; any module that fails it, or declares no coverage, fails the
86
+ roll-up, and the result names the failed modules.
87
+ - **`MCP_TOOLKIT_URL_POLICY=strict`** (opt-in): the web tools refuse non-http(s)
88
+ URLs and hosts that are or resolve to loopback, unspecified (`0.0.0.0/8`),
89
+ link-local, private (RFC1918, CGNAT `100.64.0.0/10`, IPv6 ULA `fc00::/7`,
90
+ deprecated IPv6 site-local `fec0::/10`), IETF protocol (`192.0.0.0/24`), benchmarking (`198.18.0.0/15`), multicast,
91
+ reserved (`240.0.0.0/4`) or cloud metadata addresses. An IPv6 address that
92
+ carries an IPv4 one (mapped, compatible, translated, NAT64 `64:ff9b::/96`,
93
+ 6to4, Teredo) is judged by that IPv4 address, since a translator or relay
94
+ delivers it there; the local-use NAT64 prefix `64:ff9b:1::/48` is refused
95
+ outright. The check applies to every request the browser
96
+ makes: a browser-context route aborts refused navigations, subresources,
97
+ fetches, popups and WebSockets, and the browser runs behind a local egress
98
+ proxy that checks each redirect hop and connects to the address it checked.
99
+ The address a navigation lands on is checked too, `web_crawl` neither reads
100
+ nor indexes a page that redirected to a refused address, and the reading
101
+ tools refuse a page whose address is refused. Service workers are blocked in
102
+ this mode, and WebRTC is kept off direct UDP, which neither the route nor
103
+ the proxy sees (Chromium's WebRTC IP handling policy is
104
+ `disable_non_proxied_udp`, Firefox has `media.peerconnection.enabled` off,
105
+ WebKit pages get no `RTCPeerConnection`). The proxy attaches its error
106
+ handlers before judging a request, validates the CONNECT port, answers a
107
+ failing check instead of rejecting, opens nothing for a client that has
108
+ already gone, and closes each side of a tunnel when the other closes, so a
109
+ client that resets mid-check cannot take the server down or leak a socket.
110
+ A CONNECT tunnel dials the host the check judged (brackets stripped, through
111
+ the pinned address), not the raw authority. An upstream that does not accept
112
+ the connection within `MCP_TOOLKIT_PROXY_CONNECT_TIMEOUT_MS` (default 15000)
113
+ is answered with 504, for plain requests, tunnels and upgrades alike, and a
114
+ response whose upstream goes away mid-body is closed toward the browser
115
+ instead of being left open as if more were coming.
116
+ Unset, nothing changes.
117
+ - **`MCP_TOOLKIT_URL_ALLOW`**: comma-separated host names, IPs and CIDRs the
118
+ strict policy lets through (for an intranet wiki, a staging range, a local
119
+ fixture server). It never widens the scheme check; a malformed entry is
120
+ reported and ignored.
121
+ - **`MCP_TOOLKIT_INDEX_DENY`**: paths `context_index` will not index and
122
+ `context_get` / `context_search` will not return. Under the strict policy
123
+ `~/.ssh`, `~/.aws`, `~/.gnupg`, `~/Library/Keychains`, `~/.netrc`,
124
+ `~/.git-credentials`, `~/.config/gh`, `~/.docker`, `~/.kube`, `~/.npmrc`,
125
+ `~/.config/gcloud`, `~/.azure`, `~/.pypirc`, `~/.cargo/credentials` and
126
+ `~/.cargo/credentials.toml` are denied by default. The variable adds to that
127
+ list, so naming one extra path cannot drop the credential stores; a value
128
+ that starts with `!` replaces the defaults, and one that leaves nothing
129
+ denied (a lone `!`) is reported on stderr, naming the strict defaults it
130
+ drops. On macOS the comparison ignores letter case, as the
131
+ default volume does, so `~/.SSH/id_rsa` is denied too.
132
+
133
+ ### Fixed
134
+
135
+ - **`design_visual_compare` with `live_region` measured rows against the full
136
+ screen height.** Full-width rows were sampled at `y / screenHeight` of the
137
+ cropped region, so they read another row's edges and produced inset findings
138
+ on a conformant component; the region's own height is used now. Without a
139
+ region, a top crop is subtracted from the live height the same way.
140
+ - **Config `extra_targets` carry a `cost`** derived from their driver, like
141
+ scanned targets, instead of none (which `byCost` counted under `undefined`).
142
+ - **Test fixtures and comments use neutral product names** only.
143
+ - **The research key follows the provider.** `RESEARCH_PROVIDER` was not
144
+ validated, and any value other than exactly `perplexity` picked the Brave key
145
+ while any value other than exactly `brave` sent the request to Perplexity,
146
+ so `Brave` or a typo sent the Brave key to api.perplexity.ai. The value is
147
+ now trimmed, lowercased and checked; an unknown provider is an error and no
148
+ request is made.
149
+ - **Offloaded results are owner-only**: the offload directory is `0700` and
150
+ each file `0600`. `web_storage_state` is no longer offloaded at all, since
151
+ its payload is session cookies and localStorage.
152
+ - **An empty or dash-led bundle id or package name is refused.** An empty
153
+ `bundle_id` turned `ios_reset_permissions` into `simctl privacy <d> reset
154
+ all`, which resets every app on the simulator. A slash is refused too:
155
+ `ios_set_locale` passes the bundle id to `defaults write`, which reads a value
156
+ with a slash as a plist path. An Android `activity` may still be written as
157
+ `package/activity`, and is validated on its own.
158
+ - **`media_frames` can re-run into the same `out_dir`**: ffmpeg gets `-y`, and
159
+ frames left by an earlier run are removed first instead of being counted.
160
+ - **`web_crawl` honours `max_depth: 0` and `delay_ms: 0`**, which `Number(x) ||
161
+ default` turned into the defaults.
162
+ - **`android_list_packages` with `filter` reports an adb failure** instead of
163
+ filtering the error text into an empty success.
164
+ - **Recorders**: a recorder binary that cannot be spawned is reported by the
165
+ start call instead of crashing the server with an unhandled `error` event.
166
+ - **The server exits when the host closes stdin.** Recorders stop at once,
167
+ calls in flight get up to five seconds to answer, and then the SIGTERM path
168
+ runs: LSP servers, spawned commands and the browser are closed and the
169
+ process exits. An open browser or LSP server kept it alive before.
170
+ - **Long-running commands are bounded**: `spawnCollect` runs the command in its
171
+ own process group, signals the whole group on a timeout or an abort, follows
172
+ SIGTERM with SIGKILL after a grace period, and returns shortly after the
173
+ shell exits even if a grandchild still holds the output pipe. That holds for
174
+ a clean exit too: a command that leaves a background job running reports its
175
+ own exit code, and `timedOut` is set only when the timer fired while the
176
+ command was still running. Whatever the command left running in its group
177
+ is sent SIGTERM once the result is returned, then SIGKILL after the grace
178
+ period, so a background job does not outlive the call. Output is decoded as UTF-8 per stream, so a
179
+ multibyte character split across two reads is no longer garbled. The App
180
+ Store audit runs every command through one helper with a timeout and an
181
+ output cap.
182
+ - **design-check source scans pass `--` to ripgrep** before the search path,
183
+ so a path that starts with a dash is searched instead of being read as an
184
+ option.
185
+ - **The context index** keeps one database handle per server instead of one
186
+ per call, and indexes a file in a single transaction, so a failure partway
187
+ no longer leaves a partial copy that later calls report as unchanged. Its
188
+ directory is narrowed to `0700` on every open, including one that already
189
+ existed with wider permissions.
190
+
191
+ ### Removed
192
+
193
+ - The unused `TOOL_DESCRIPTOR` export in `tools/ios-app-store-audit`; its
194
+ tests now check the description the server actually serves.
19
195
 
20
196
  ---
21
197
 
198
+ ## [3.14.0] - 2026-09-21
199
+
200
+ ### Added
201
+
202
+ - **`security` family: `security_cvss_score` and `security_dep_inventory`.**
203
+ security_cvss_score turns a CVSS 3.1 base vector into a score and band by the
204
+ FIRST arithmetic, so a finding's number cannot drift from its vector.
205
+ security_dep_inventory normalizes a lockfile (npm, yarn, pnpm, CocoaPods, pip,
206
+ Go, Cargo, RubyGems) into {ecosystem, name, version}. Both are pure JS and
207
+ contact nothing - matching an inventory against known CVEs stays a separate,
208
+ network-bearing step, so the stdio-only egress surface is unchanged. Gated at
209
+ serve time by `MCP_TOOLKIT_CAPS=security`. 117 tools total.
210
+
22
211
  ## 3.13.1 - 2026-09-21
23
212
 
24
213
  Fixes to the web and context families, each held by a gate proven to fail
@@ -751,8 +940,6 @@ The tests pin both shapes; the first real Android run is that half's measurement
751
940
  It could not be tested where it was: `index.js` connects its transport at
752
941
  import time, so nothing in it is reachable from a test.
753
942
 
754
- ## Unreleased
755
-
756
943
  ## 3.1.0
757
944
 
758
945
  One new tool and the offload path behind it. Minor rather than patch because the
@@ -1025,7 +1212,7 @@ TestFlight pre-submission validation: ask Apple before Apple asks you.
1025
1212
  because the app never reaches the mock state those riders need. Assignment
1026
1213
  scores an exact screen match above a substring one, then a relaunch with a
1027
1214
  launch argument above one without, then canonical order. Substring pairing
1028
- ("Apis Form" ↔ "APIS") still works; it just no longer outranks an exact match.
1215
+ ("Order Form" ↔ "ORDER") still works; it just no longer outranks an exact match.
1029
1216
  - New `plan-determinism.test.mjs` permutes `buildPlan`'s input across 40 seeds
1030
1217
  and asserts the plan is byte-identical. A pass-count is not proof of order
1031
1218
  independence: this property test caught residual rider-ordering drift on its
@@ -1153,7 +1340,7 @@ down to the `path` array.
1153
1340
  **Fixture-count noise is demoted, not reported as defects** (`docs/design-check-gaps.md`
1154
1341
  section 1, the item that dominated a real 109-target audit). A live capture is
1155
1342
  compared against a screen frame, and a screen frame carries whatever the mock
1156
- fixture produced: 5 passenger rows in the design against 3 in the app makes every
1343
+ fixture produced: 5 item rows in the design against 3 in the app makes every
1157
1344
  container height and every downstream position differ for a reason that is not a
1158
1345
  defect.
1159
1346
 
@@ -1320,19 +1507,6 @@ paths and requires an error on each. Gate 9 requires every tool advertising an
1320
1507
  outputSchema to actually return `structuredContent`, and to keep its text
1321
1508
  content beside it. 14 gates, all green.
1322
1509
 
1323
- ## [3.14.0] - 2026-09-21
1324
-
1325
- ### Added
1326
-
1327
- - **`security` family: `security_cvss_score` and `security_dep_inventory`.**
1328
- security_cvss_score turns a CVSS 3.1 base vector into a score and band by the
1329
- FIRST arithmetic, so a finding's number cannot drift from its vector.
1330
- security_dep_inventory normalizes a lockfile (npm, yarn, pnpm, CocoaPods, pip,
1331
- Go, Cargo, RubyGems) into {ecosystem, name, version}. Both are pure JS and
1332
- contact nothing - matching an inventory against known CVEs stays a separate,
1333
- network-bearing step, so the stdio-only egress surface is unchanged. Gated at
1334
- serve time by `MCP_TOOLKIT_CAPS=security`. 117 tools total.
1335
-
1336
1510
  ## [3.0.0] - 2026-08-22
1337
1511
 
1338
1512
  ### Changed
package/README.md CHANGED
@@ -7,13 +7,13 @@
7
7
 
8
8
  🇹🇷 Türkçe: [README.tr.md](./README.tr.md)
9
9
 
10
- **117 tools** for iOS Simulator, Android Emulator, and headless web control. MCP server that lets your AI coding assistant see, interact with, and audit your mobile apps - plus drive browsers, run an 18-rule App Store compliance audit, and orchestrate multi-step batch flows.
10
+ **118 tools** for iOS Simulator, Android Emulator, and headless web control. MCP server that lets your AI coding assistant see, interact with, and audit your mobile apps - plus drive browsers, run an 18-rule App Store compliance audit, and orchestrate multi-step batch flows.
11
11
 
12
12
  Distributed on the **public npm registry** - `npx @mmerterden/multi-agent-toolkit-mcp` resolves with no auth, no token, no `~/.npmrc` setup.
13
13
 
14
14
  **Verified on Claude Code, Copilot CLI and Codex CLI** - the three hosts the release gates actually exercise. Being a standard stdio MCP server it also runs in Cursor, Antigravity, VS Code Copilot Chat, Claude Desktop and any other MCP client; config snippets for those are below, but nothing here checks them.
15
15
 
16
- That distinction is worth keeping straight. This line once called five hosts "the multi-agent-pipeline's full-orchestration targets", which stopped being true in pipeline v10.7.0 when the Cursor / Antigravity / Codex / Copilot Chat adapters were deleted. Codex CLI returned as a first-class target in pipeline v13.0.0 on capability - it now has skills, parallel sub-agents, hooks and MCP - and it is on the verified list only because a gate exercises it, not because it is supported elsewhere. Claiming hosts nobody exercises is not free either: 2.20.0 and 2.21.0 shipped an illegal `outputSchema` on the first tool, so Claude Code rejected the whole `tools/list` and served zero of the 78 - in the primary host, for two releases, with every gate in this repo green.
16
+ The verified list is the set of hosts a release gate starts and queries: a host that no gate runs is not claimed as supported, because a schema that one client tolerates can make another reject the whole `tools/list`.
17
17
 
18
18
  **14 categories:**
19
19
  - **Device Control** (59 tools) - screenshot, tap, swipe, type, navigate, dark mode, locale, orientation, location, permissions, push notifications, real start/stop screen recording
@@ -22,7 +22,7 @@ That distinction is worth keeping straight. This line once called five hosts "th
22
22
  - **Accessibility Audit** (3 tools) - `ios_accessibility_audit` / `android_accessibility_audit` read the live tree for missing labels, controls a screen reader cannot name, small tap targets, missing identifiers and a reading order that does not follow the visual layout. `ios_accessibility_audit_deep` runs Apple's own XCUIAccessibilityAudit through your XCUITest for the things a tree cannot show: contrast, Dynamic Type, clipped text. All three report `measurable:false` with a reason rather than a clean result when they could not look
23
23
  - **Store Compliance** (5 tools) - App Store / Play Store readiness; **18-rule deep `ios_app_store_audit`** cross-references Apple ITMS error codes + App Store Review Guidelines (privacy manifest, required-reason API, Info.plist, code signing, entitlements, embedded SDK, IPv6, debug-tool leak, ...)
24
24
  - **Web Automation** (18 tools) - Playwright-powered: goto, click, type, press a key, select an option, eval JS, wait for a selector, extract text, screenshot, plus an accessibility snapshot whose `ref` handles the other tools accept in place of a CSS selector, console and network logs captured since the last navigation, tab and storage state, readable article extraction, same-origin link mapping and a bounded crawl. Chromium / WebKit / Firefox engines. **Requires `playwright` peer dependency.**
25
- - **Design Audit** (6 tools) - mock-mode vs Figma conformance: scenario inventory, mock detection, mock launch, live UI geometry, pixel/geometry/typography compare, and the HTML/PDF report with its coverage gate
25
+ - **Design Audit** (7 tools) - mock-mode vs Figma conformance: scenario inventory, mock detection, mock launch, live UI geometry, component-variant resolution, pixel/geometry/typography compare, and the HTML/PDF report with its coverage gate and module roll-up
26
26
  - **Code Intelligence** (8 tools) - compiler-grade answers about Swift and Kotlin source, over the language server each platform already ships: definition, references, hover, document and workspace symbols, diagnostics without a full build, plus `code_index_status` for whether this machine can answer at all. Cross-file answers need a background index, so they report whether it had settled instead of returning an empty list that reads as "unused"
27
27
  - **Wallet Passes** (4 tools) - build, sign, validate and inspect Apple Wallet passes. All five styles, offline and deterministic, and a literal passphrase is deliberately not an accepted input: the caller names an environment variable or a keychain entry. The validator grades by consequence, because the interesting failures are the silent ones - one unknown `PKPassengerCapability` value raises nothing and quietly drops an enhanced pass back to the old layout
28
28
  - **Context Index** (3 tools) - a large result is not only written to a file, it is chunked and indexed in SQLite FTS5, so `context_search` ranks passages with bm25() and answers in roughly 50-100 tokens which part is about what. `context_get` opens one passage by id; the file path is still there for everything. Grep tells you which lines contain a string; ranking tells you which part is about the subject. No dependency: `node:sqlite` ships with Node
@@ -163,7 +163,7 @@ Add to `.vscode/mcp.json`:
163
163
 
164
164
  ### Requirements
165
165
 
166
- - **Node.js 18+**
166
+ - **Node.js 22.13+** (the context tools use `node:sqlite`, unflagged from 22.13; on an older Node the rest of the server still starts and `context_*` answers with that reason)
167
167
  - **iOS tools**: macOS + Xcode (provides `xcrun simctl`)
168
168
  - **Android tools**: Android SDK Platform-Tools (provides `adb`)
169
169
  - **Web tools** (optional): `playwright` - install once:
@@ -174,6 +174,16 @@ Add to `.vscode/mcp.json`:
174
174
 
175
175
  > If Xcode is not installed, iOS tools return a friendly message instead of crashing. Same for Android and Web tools - use what you have.
176
176
 
177
+ ### Restricting what the server can reach
178
+
179
+ Off by default; unset, nothing below changes behaviour.
180
+
181
+ - **`MCP_TOOLKIT_URL_POLICY=strict`** - the web tools refuse any URL that is not `http(s)`, and any host that is or resolves to a loopback (`127.0.0.0/8`, `::1`, `localhost`), unspecified (`0.0.0.0/8`, `::`), link-local (`169.254.0.0/16`, `fe80::/10`), private (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, CGNAT `100.64.0.0/10`, IPv6 ULA `fc00::/7`, deprecated IPv6 site-local `fec0::/10`), IETF protocol (`192.0.0.0/24`), benchmarking (`198.18.0.0/15`), multicast or reserved (`224.0.0.0/4`, `240.0.0.0/4`, `ff00::/8`, local-use NAT64 `64:ff9b:1::/48`) or cloud metadata address (`metadata.google.internal`, `fd00:ec2::254`, `100.100.100.200`). An IPv6 address that carries an IPv4 one (IPv4-mapped, IPv4-compatible, IPv4-translated, NAT64 `64:ff9b::/96`, 6to4 `2002::/16`, Teredo `2001::/32`) is judged by the IPv4 address it carries. A host that does not resolve is refused. The check covers every request the browser makes, not only the URL given to `web_goto`: a browser-context route aborts refused navigations, subresources, fetches, popups and WebSockets, and the browser is launched behind a local proxy (127.0.0.1 only) that checks each hop of a redirect chain and connects to the address it checked; an upstream that does not accept the connection within `MCP_TOOLKIT_PROXY_CONNECT_TIMEOUT_MS` (default 15000) is answered with 504. The URL a navigation lands on is checked as well, `web_crawl` skips and does not index a page that redirected to a refused address, and the reading tools (`web_get_text`, `web_extract`, `web_snapshot`, `web_screenshot`, `web_eval` and the rest) refuse to read a page whose address is refused. Service workers are blocked and the HTTP cache is off in this mode, because both would bypass the route. WebRTC is kept off direct UDP, which neither the route nor the proxy sees: Chromium is launched with `--force-webrtc-ip-handling-policy=disable_non_proxied_udp`, Firefox with `media.peerconnection.enabled=false`, and WebKit pages get no `RTCPeerConnection`. The proxy's coverage of loopback targets is verified on Chromium. Any value other than `strict` or `off` is warned about on stderr and treated as `strict`.
182
+ - **`MCP_TOOLKIT_URL_ALLOW`** - comma-separated exceptions to the strict policy: host names (matched exactly, case-insensitively), IP addresses and CIDRs, e.g. `wiki.corp.example,10.20.0.0/16,127.0.0.1`. A listed host, a literal IP inside a listed range, or a host whose refused answers all fall inside a listed range is let through. It never allows a non-`http(s)` scheme, a malformed entry is reported on stderr and ignored, and it has no effect without `strict`.
183
+ - **`MCP_TOOLKIT_INDEX_DENY`** - comma-separated paths (`~/` expands) that `context_index` refuses to index and that `context_get` / `context_search` refuse to return, symlinks resolved (on macOS the comparison ignores letter case, as the default APFS volume does, so `~/.SSH/id_rsa` is `~/.ssh/id_rsa`). Under `strict` the default list is `~/.ssh`, `~/.aws`, `~/.gnupg`, `~/Library/Keychains`, `~/.netrc`, `~/.git-credentials`, `~/.config/gh`, `~/.docker`, `~/.kube`, `~/.npmrc`, `~/.config/gcloud`, `~/.azure`, `~/.pypirc`, `~/.cargo/credentials`, `~/.cargo/credentials.toml`. Set, the variable adds its paths to those defaults and applies with or without the strict policy. A value that starts with `!` replaces the defaults instead (`!~/work,~/notes` denies only those two; a lone `!` denies nothing, and the server says so on stderr at startup).
184
+
185
+ Offloaded results under `~/.claude/logs/multi-agent-toolkit/` are written owner-only (directory `0700`, files `0600`), and the context index directory is narrowed to `0700` every time it is opened, including one that already existed with wider permissions. `web_storage_state` is never offloaded: its cookies and localStorage come back inline.
186
+
177
187
  ### Agent DSL Example
178
188
 
179
189
  Run a scripted login flow in one MCP call:
@@ -274,18 +284,19 @@ Returns per-step status so the agent can self-correct on failure.
274
284
  | `android_list_crashes` | Dump the adb crash log buffer, tail-bounded |
275
285
  | `android_set_orientation` | Rotate to portrait/landscape (pins user_rotation, disables auto-rotate) |
276
286
 
277
- ### Design Tools (6)
287
+ ### Design Tools (7)
278
288
 
279
289
  Mock-mode vs Figma design audit. Generic and platform-agnostic - the heavy orchestration (Figma fetch, variant matching, screen navigation, report assembly) is expected to live in the caller; these expose the mechanical primitives.
280
290
 
281
291
  | Tool | Description |
282
292
  |------|-------------|
283
293
  | `design_mock_detect` | Detect whether a project supports a mock/stub mode (`true` / `false` / `debug-only`) via naming conventions, `#if DEBUG` DI, MockData fixtures, and well-known runtime switch keys (extendable). Returns activation + variant hints + evidence. |
284
- | `design_scenario_inventory` | Enumerate every state driver the mock build exposes - relaunch flags, `*Scenario` / `*Outcome` enum cases, reference-prefix variants (`hasPrefix("F6DI")` branches inside per-screen mock repositories, typically the largest group), flow-wide scenario codes, MockData fixtures, custom-scheme deep links - each with file+line evidence. Prices every target (`relaunch` vs `in-app`) and batches them into a run `plan`, so one relaunch serves every in-app state on that screen. Gives an audit a countable target set instead of "walk the UI until it feels done". |
294
+ | `design_scenario_inventory` | Enumerate every state driver the mock build exposes - relaunch flags, `*Scenario` / `*Outcome` enum cases (counted only with debug evidence: declared under `#if DEBUG` or in an Android debug/mock source set, referenced only from debug/mock code, or read from a runtime key; a production type sharing the suffix is reported in `rejectedSelectors` instead), reference-prefix variants (`hasPrefix("R1EX")` branches inside per-screen mock repositories, typically the largest group), flow-wide scenario codes, MockData fixtures, custom-scheme deep links - each with file+line evidence. Prices every target (`relaunch` vs `in-app`) and batches them into a run `plan`, so one relaunch serves every in-app state on that screen. `targets_file` / `targets[]` supply the target set from an external catalog instead of scanning; plan, groups, relaunch count and the coverage gate work unchanged. Gives an audit a countable target set instead of "walk the UI until it feels done". |
285
295
  | `design_mock_launch` | Launch an installed app in mock mode (iOS UserDefaults launch arg / Android intent extra). |
286
296
  | `design_ui_geometry` | Flat element bounding boxes of the current screen + screen size, for px-level spacing measurement. |
297
+ | `design_component_variants` | Resolve a design node to its component set and list the variants (`State=Error`, `Rows=3`), from Figma data the caller already fetched (REST `nodes` response or MCP `get_metadata` XML, plus the library's `component_sets` listing; the server never contacts Figma). Returns per-variant geometry spec, frame, render request and Code Connect name, matches audited states to variants by name, and lists the nodes and renders still to fetch. Comparing the live component region against its own variant removes the fixture row-count dimension from the geometry findings. |
287
298
  | `design_visual_compare` | Compare a Figma render vs a live screenshot without failing on size mismatch: normalizes scale, crops chrome, reports perceptual diff %, spacing/size/position (px), color (ΔE), and typography. Writes figma/live/diff/overlay/side-by-side PNGs. |
288
- | `design_report` | Render a design-audit report object to self-contained HTML (base64 images, CSS-positioned annotations) + optional PDF. Enforces a coverage gate: every target must be audited or skipped with an explicit reason, so a partial audit cannot render as a clean report. Wording comes from a label pack (English default, Turkish built in). |
299
+ | `design_report` | Render a design-audit report object to self-contained HTML (base64 images, CSS-positioned annotations) + optional PDF. Enforces a coverage gate: every target must be audited or skipped with an explicit reason, so a partial audit cannot render as a clean report. Wording comes from a label pack (English default, Turkish built in). Roll-up mode (`modules[]`) renders one row per module - coverage, gate, deviations, link to the module report - and fails when any module fails its own gate. |
289
300
 
290
301
  ### Code Intelligence Tools (8)
291
302
 
@@ -362,6 +373,66 @@ that grade exists because those are the ones nobody finds:
362
373
  Run against a real signed production boarding pass, the validator reported zero
363
374
  errors and found both of the last two.
364
375
 
376
+ ### Web Tools (18)
377
+
378
+ Headless browser control through Playwright, an optional peer dependency. One browser and one context are reused across calls.
379
+
380
+ | Tool | Description |
381
+ |------|-------------|
382
+ | `web_goto` | Open a URL. Takes `browser` (chromium / webkit / firefox), `wait_until`, `timeout_ms`, `viewport`, `locale` and `user_agent` |
383
+ | `web_screenshot` | Screenshot of the current page, inline PNG or written to `path` |
384
+ | `web_click` | Click by CSS selector, text, or a `ref` from `web_snapshot` |
385
+ | `web_type` | Type into an input matched by selector or `ref` |
386
+ | `web_eval` | Run JavaScript in the page and return the result as JSON |
387
+ | `web_wait_for` | Wait for a selector to reach a state |
388
+ | `web_get_text` | textContent of the first match of a selector or `ref` |
389
+ | `web_close` | Close the browser context and release resources |
390
+ | `web_snapshot` | Accessibility snapshot with a stable `[ref=eN]` per node, for the action tools |
391
+ | `web_console` | Console messages since the last `web_goto` |
392
+ | `web_network` | Requests since the last `web_goto`: method, status, type, URL |
393
+ | `web_tabs` | List the open pages and switch the active one |
394
+ | `web_storage_state` | Read cookies and localStorage, or restore a saved state |
395
+ | `web_extract` | The page's article content as Markdown (or text) |
396
+ | `web_map` | Same-origin links on the current page, deduplicated |
397
+ | `web_crawl` | Bounded same-origin crawl, robots.txt respected, each page indexed for `context_search` |
398
+ | `web_press_key` | Press a key, optionally on a focused element |
399
+ | `web_select_option` | Choose a `<select>` option by value or label |
400
+
401
+ ### Context Index Tools (3)
402
+
403
+ | Tool | Description |
404
+ |------|-------------|
405
+ | `context_index` | Index a text file into the SQLite FTS5 index; an unchanged file is a no-op |
406
+ | `context_search` | Ranked passages (bm25) with a short snippet and a chunk id per hit |
407
+ | `context_get` | One passage in full by id, with its file and line range |
408
+
409
+ ### Research Tools (2)
410
+
411
+ | Tool | Description |
412
+ |------|-------------|
413
+ | `research_search` | Web search through Brave or Perplexity, normalized to title / url / snippet. Key from `BRAVE_API_KEY` or `PERPLEXITY_API_KEY`, never an argument |
414
+ | `research_ask` | A cited answer from Perplexity Sonar. Key from `PERPLEXITY_API_KEY` |
415
+
416
+ ### Media Tools (1)
417
+
418
+ | Tool | Description |
419
+ |------|-------------|
420
+ | `media_frames` | Key frames from a video as PNGs, near-duplicates dropped. Requires ffmpeg |
421
+
422
+ ### Agent Tools (2)
423
+
424
+ | Tool | Description |
425
+ |------|-------------|
426
+ | `agent_run_steps` | Run a batch of ios / android / web / design steps in one call, with per-step status and a verdict |
427
+ | `agent_query_output` | Search the saved full output of an earlier call that was too large to return inline |
428
+
429
+ ### Security Tools (2)
430
+
431
+ | Tool | Description |
432
+ |------|-------------|
433
+ | `security_cvss_score` | CVSS 3.1 base score and band from a base vector, offline |
434
+ | `security_dep_inventory` | A lockfile normalized to `{ecosystem, name, version}`, offline |
435
+
365
436
  ### Use Cases
366
437
 
367
438
  - **Visual bug hunting** - Screenshot every screen, AI analyzes for layout issues
package/README.tr.md CHANGED
@@ -7,13 +7,13 @@
7
7
 
8
8
  🇬🇧 English: [README.md](./README.md)
9
9
 
10
- iOS Simulator, Android Emulator ve headless web kontrolü için **115 araç**. AI kodlama asistanının mobil uygulamalarını görmesini, onlarla etkileşime girmesini ve denetlemesini sağlayan bir MCP sunucusu - ayrıca tarayıcıları sürer, 18-kurallık bir App Store uyumluluk denetimi çalıştırır ve çok-adımlı batch akışlarını orkestre eder.
10
+ iOS Simulator, Android Emulator ve headless web kontrolü için **118 araç**. AI kodlama asistanının mobil uygulamalarını görmesini, onlarla etkileşime girmesini ve denetlemesini sağlayan bir MCP sunucusu - ayrıca tarayıcıları sürer, 18-kurallık bir App Store uyumluluk denetimi çalıştırır ve çok-adımlı batch akışlarını orkestre eder.
11
11
 
12
12
  **Public npm registry** üzerinden dağıtılır - `npx @mmerterden/multi-agent-toolkit-mcp`, auth'suz, token'sız, `~/.npmrc` ayarı gerekmeden çözülür.
13
13
 
14
14
  **Claude Code, Copilot CLI ve Codex CLI üzerinde doğrulanmıştır** - release kapılarının fiilen çalıştırdığı üç host. Standart bir stdio MCP sunucusu olduğu için Cursor, Antigravity, VS Code Copilot Chat, Claude Desktop ve diğer herhangi bir MCP client'ında da çalışır; bunlar için config parçacıkları aşağıda, ama burada hiçbir şey onları kontrol etmiyor.
15
15
 
16
- Bu ayrımı net tutmakta fayda var. Bu satır bir zamanlar beş host'u "multi-agent-pipeline'ın tam-orkestrasyon hedefleri" olarak adlandırıyordu, bu da pipeline v10.7.0'da Cursor / Antigravity / Codex / Copilot Chat adaptörleri silindiğinde doğru olmaktan çıktı. Codex CLI, pipeline v13.0.0'da yetenek üzerinden birinci-sınıf bir hedef olarak geri döndü - artık skill'leri, paralel sub-agent'ları, hook'ları ve MCP'si var - ve doğrulanmış listede sadece bir kapı onu çalıştırdığı için yer alıyor, başka bir yerde desteklendiği için değil. Kimsenin çalıştırmadığı host'ları iddia etmek de bedavaya gelmiyor: 2.20.0 ve 2.21.0, ilk araçta yasa dışı bir `outputSchema` gönderdi, bu yüzden Claude Code tüm `tools/list`'i reddetti ve 78'in sıfırını sundu - birincil host'ta, iki release boyunca, bu repo'daki her kapı yeşilken.
16
+ Doğrulanmış liste, bir release kapısının başlatıp sorguladığı host'lardan oluşur: hiçbir kapının çalıştırmadığı bir host desteklenen olarak iddia edilmez, çünkü bir client'ın tolere ettiği bir şema başka bir client'ın tüm `tools/list`'i reddetmesine yol açabilir.
17
17
 
18
18
  **14 kategori:**
19
19
  - **Device Control** (59 araç) - screenshot, tap, swipe, type, navigate, dark mode, locale, orientation, location, permissions, push notifications, gerçek start/stop ekran kaydı
@@ -22,7 +22,7 @@ Bu ayrımı net tutmakta fayda var. Bu satır bir zamanlar beş host'u "multi-ag
22
22
  - **Accessibility Audit** (3 araç) - `ios_accessibility_audit` / `android_accessibility_audit` canlı ağacı okur: eksik label, ekran okuyucunun adlandıramadığı kontrol, küçük tap target, eksik identifier ve görsel düzeni izlemeyen okuma sırası. `ios_accessibility_audit_deep` ise ağacın gösteremeyeceği şeyler için Apple'ın kendi XCUIAccessibilityAudit'ini XCUITest'iniz üzerinden çalıştırır: kontrast, Dynamic Type, kırpılmış metin. Üçü de bakamadıklarında temiz bir sonuç değil, gerekçesiyle `measurable:false` döner
23
23
  - **Store Compliance** (5 araç) - App Store / Play Store hazırlığı; **18-kurallık derin `ios_app_store_audit`**, Apple ITMS hata kodları + App Store Review Guidelines'a çapraz referans verir (privacy manifest, required-reason API, Info.plist, code signing, entitlements, gömülü SDK, IPv6, debug-tool sızıntısı, ...)
24
24
  - **Web Automation** (18 araç) - Playwright-destekli: goto, click, type, tuş basma, seçenek seçme, JS eval, selector bekleme, metin çıkarma, screenshot; ayrıca diğer araçların CSS selector yerine kabul ettiği `ref` tutamaklarını üreten erişilebilirlik snapshot'ı, son navigasyondan beri toplanan console ve network kayıtları, sekme ve storage durumu, okunabilir makale çıkarımı, aynı-origin link haritası ve sınırlı bir crawl. Chromium / WebKit / Firefox motorları. **`playwright` peer dependency'si gerektirir.**
25
- - **Design Audit** (6 araç) - mock-mode vs Figma uygunluğu: scenario envanteri, mock tespiti, mock launch, canlı UI geometrisi, piksel/geometri/tipografi karşılaştırması, ve coverage kapısıyla birlikte HTML/PDF rapor
25
+ - **Design Audit** (7 araç) - mock-mode vs Figma uygunluğu: scenario envanteri, mock tespiti, mock launch, canlı UI geometrisi, component varyant çözümleme, piksel/geometri/tipografi karşılaştırması, ve coverage kapısı ile modül özetiyle birlikte HTML/PDF rapor
26
26
  - **Code Intelligence** (8 araç) - Swift ve Kotlin kaynağı hakkında derleyici seviyesinde cevaplar, her platformun zaten getirdiği dil sunucusu üzerinden: tanım, referanslar, hover, dosya ve proje geneli semboller, tam build olmadan tanılamalar, ve bu makinenin soruyu cevaplayıp cevaplayamayacağını söyleyen `code_index_status`. Çapraz dosya cevapları arka plan index'ine bağlı olduğu için, "kullanılmıyor" diye okunan boş bir liste yerine index'in oturup oturmadığını raporlar
27
27
  - **Wallet Passes** (4 araç) - Apple Wallet pass'i üret, imzala, doğrula ve incele. Beş stilin hepsi, çevrimdışı ve deterministik; düz metin parola bilerek kabul edilen bir girdi değil: çağıran taraf bir ortam değişkeninin adını ya da bir keychain kaydını verir. Doğrulayıcı bulguları sonucuna göre derecelendirir, çünkü asıl önemli hatalar sessiz olanlar - tanınmayan tek bir `PKPassengerCapability` değeri hiçbir uyarı üretmez ve gelişmiş pass'i sessizce eski düzene düşürür
28
28
  - **Context Index** (3 araç) - büyük bir sonuç yalnızca dosyaya yazılmaz, parçalanıp SQLite FTS5'e indekslenir; `context_search` bm25() ile sıralar ve hangi parçanın neyle ilgili olduğunu yaklaşık 50-100 token'da söyler. `context_get` tek bir parçayı id ile açar, dosya yolu ise her şey için orada durur. Grep hangi satırların bir dizgiyi içerdiğini söyler; sıralama hangi parçanın o konuyla ilgili olduğunu. Bağımlılık yok: `node:sqlite` Node ile geliyor
@@ -163,7 +163,7 @@ paketine scope'la) ve tekrar dene.
163
163
 
164
164
  ### Gereksinimler
165
165
 
166
- - **Node.js 18+**
166
+ - **Node.js 22.13+** (context araçları `node:sqlite` kullanır, 22.13'ten itibaren bayraksız; daha eski bir Node'da sunucunun geri kalanı yine açılır ve `context_*` bu gerekçeyle cevap verir)
167
167
  - **iOS araçları**: macOS + Xcode (`xcrun simctl`'i sağlar)
168
168
  - **Android araçları**: Android SDK Platform-Tools (`adb`'yi sağlar)
169
169
  - **Web araçları** (opsiyonel): `playwright` - bir kere kur:
@@ -174,6 +174,16 @@ paketine scope'la) ve tekrar dene.
174
174
 
175
175
  > Xcode kurulu değilse, iOS araçları crash etmek yerine anlaşılır bir mesaj döner. Android ve Web araçları için de aynı - elindekini kullan.
176
176
 
177
+ ### Sunucunun erişimini kısıtlamak
178
+
179
+ Varsayılan olarak kapalı; ayarlanmadığında aşağıdakilerin hiçbiri davranışı değiştirmez.
180
+
181
+ - **`MCP_TOOLKIT_URL_POLICY=strict`** - web araçları `http(s)` olmayan her URL'yi ve loopback (`127.0.0.0/8`, `::1`, `localhost`), belirtilmemiş (`0.0.0.0/8`, `::`), link-local (`169.254.0.0/16`, `fe80::/10`), özel ağ (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, CGNAT `100.64.0.0/10`, IPv6 ULA `fc00::/7`, kullanımdan kaldırılmış IPv6 site-local `fec0::/10`), IETF protokol (`192.0.0.0/24`), benchmark (`198.18.0.0/15`), multicast ya da ayrılmış (`224.0.0.0/4`, `240.0.0.0/4`, `ff00::/8`, yerel kullanım NAT64 `64:ff9b:1::/48`) ya da bulut metadata adresi (`metadata.google.internal`, `fd00:ec2::254`, `100.100.100.200`) olan veya bunlara çözümlenen her host'u reddeder. İçinde IPv4 adresi taşıyan bir IPv6 adresi (IPv4-mapped, IPv4-compatible, IPv4-translated, NAT64 `64:ff9b::/96`, 6to4 `2002::/16`, Teredo `2001::/32`) taşıdığı IPv4 adresine göre değerlendirilir. Çözümlenemeyen host reddedilir. Kontrol yalnızca `web_goto`'ya verilen URL'yi değil, tarayıcının yaptığı her isteği kapsar: tarayıcı bağlamındaki bir route reddedilen navigasyonları, alt kaynakları, fetch'leri, popup'ları ve WebSocket'leri keser; tarayıcı ayrıca yerel bir proxy'nin (yalnızca 127.0.0.1) arkasında başlatılır, bu proxy bir yönlendirme zincirinin her adımını kontrol eder ve kontrol ettiği adrese bağlanır; bağlantıyı `MCP_TOOLKIT_PROXY_CONNECT_TIMEOUT_MS` (varsayılan 15000) içinde kabul etmeyen bir upstream 504 ile yanıtlanır. Navigasyonun vardığı URL de kontrol edilir, `web_crawl` reddedilen bir adrese yönlenen sayfayı atlar ve indekslemez, okuma araçları (`web_get_text`, `web_extract`, `web_snapshot`, `web_screenshot`, `web_eval` ve diğerleri) adresi reddedilen bir sayfayı okumaz. Bu modda service worker'lar engellenir ve HTTP önbelleği kapalıdır, çünkü ikisi de route'u atlar. WebRTC, ne route'un ne de proxy'nin gördüğü doğrudan UDP'den uzak tutulur: Chromium `--force-webrtc-ip-handling-policy=disable_non_proxied_udp` ile, Firefox `media.peerconnection.enabled=false` ile başlatılır, WebKit sayfalarında `RTCPeerConnection` bulunmaz. Proxy'nin loopback hedeflerini kapsadığı Chromium üzerinde doğrulanmıştır. `strict` ya da `off` dışındaki her değer stderr'de uyarılır ve `strict` sayılır.
182
+ - **`MCP_TOOLKIT_URL_ALLOW`** - strict politikaya virgülle ayrılmış istisnalar: host adları (birebir, büyük/küçük harf duyarsız eşleşir), IP adresleri ve CIDR'ler, ör. `wiki.corp.example,10.20.0.0/16,127.0.0.1`. Listelenen bir host, listelenen bir aralıktaki IP ya da reddedilen tüm cevapları listelenen bir aralığa düşen bir host geçirilir. `http(s)` dışı bir şemaya asla izin vermez, hatalı bir girdi stderr'de bildirilip yok sayılır ve `strict` olmadan etkisi yoktur.
183
+ - **`MCP_TOOLKIT_INDEX_DENY`** - `context_index`'in indekslemeyi reddettiği, `context_get` / `context_search`'ün döndürmeyi reddettiği, virgülle ayrılmış yollar (`~/` açılır, symlink'ler çözülür; macOS'ta karşılaştırma, varsayılan APFS birimi gibi büyük/küçük harfe bakmaz, yani `~/.SSH/id_rsa` ile `~/.ssh/id_rsa` aynıdır). `strict` altında varsayılan liste `~/.ssh`, `~/.aws`, `~/.gnupg`, `~/Library/Keychains`, `~/.netrc`, `~/.git-credentials`, `~/.config/gh`, `~/.docker`, `~/.kube`, `~/.npmrc`, `~/.config/gcloud`, `~/.azure`, `~/.pypirc`, `~/.cargo/credentials`, `~/.cargo/credentials.toml` olur. Değişken ayarlandığında yolları bu varsayılanlara eklenir ve strict politikadan bağımsız uygulanır. `!` ile başlayan bir değer ise varsayılanların yerine geçer (`!~/work,~/notes` yalnızca bu ikisini reddeder; tek başına `!` hiçbir şeyi reddetmez ve sunucu bunu açılışta stderr'e yazar).
184
+
185
+ `~/.claude/logs/multi-agent-toolkit/` altına offload edilen sonuçlar yalnızca sahibine açık yazılır (dizin `0700`, dosyalar `0600`); context indeks dizini de her açılışta, daha geniş izinlerle önceden var olmuş olsa bile, `0700`'e daraltılır. `web_storage_state` hiç offload edilmez: cookie'leri ve localStorage'ı satır içinde döner.
186
+
177
187
  ### Agent DSL Örneği
178
188
 
179
189
  Tek bir MCP çağrısında scriptlenmiş bir login akışı çalıştır:
@@ -274,18 +284,103 @@ Agent'ın hata durumunda kendini düzeltebilmesi için adım-başına durum dön
274
284
  | `android_list_crashes` | adb crash log buffer'ını dök, tail-sınırlı |
275
285
  | `android_set_orientation` | Portrait/landscape'e döndür (user_rotation'ı sabitler, auto-rotate'i kapatır) |
276
286
 
277
- ### Design Araçları (6)
287
+ ### Design Araçları (7)
278
288
 
279
289
  Mock-mode vs Figma tasarım denetimi. Jenerik ve platform-bağımsız - ağır orkestrasyonun (Figma çekme, varyant eşleme, ekran navigasyonu, rapor derleme) çağıranda yaşaması beklenir; bunlar mekanik ilkel işlemleri açığa çıkarır.
280
290
 
281
291
  | Araç | Açıklama |
282
292
  |------|-------------|
283
293
  | `design_mock_detect` | Bir projenin mock/stub modunu desteklediğini (`true` / `false` / `debug-only`) isimlendirme konvansiyonları, `#if DEBUG` DI, MockData fixture'ları ve bilinen runtime switch key'leri (genişletilebilir) üzerinden tespit et. Aktivasyon + varyant ipuçları + kanıt döner. |
284
- | `design_scenario_inventory` | Mock build'in açığa çıkardığı her state sürücüsünü enumerate et - relaunch flag'leri, `*Scenario` / `*Outcome` enum case'leri, reference-prefix varyantları (ekran-başına mock repository'ler içindeki `hasPrefix("F6DI")` dalları, genelde en büyük grup), akış-geneli senaryo kodları, MockData fixture'ları, custom-scheme deep link'ler - her biri dosya+satır kanıtıyla. Her hedefi (`relaunch` vs `in-app`) fiyatlandırır ve bir çalıştırma `plan`ına gruplar, böylece bir relaunch o ekrandaki her in-app state'e hizmet eder. Bir denetime "UI'da bitmiş hissedene kadar gez" yerine sayılabilir bir hedef seti verir. |
294
+ | `design_scenario_inventory` | Mock build'in açığa çıkardığı her state sürücüsünü enumerate et - relaunch flag'leri, `*Scenario` / `*Outcome` enum case'leri (yalnızca debug kanıtıyla sayılır: `#if DEBUG` altında ya da Android debug/mock source set'inde tanımlı, yalnızca debug/mock koddan referanslanan veya runtime key'den okunan; aynı son eki taşıyan production tipi `rejectedSelectors` içinde raporlanır), reference-prefix varyantları (ekran-başına mock repository'ler içindeki `hasPrefix("R1EX")` dalları, genelde en büyük grup), akış-geneli senaryo kodları, MockData fixture'ları, custom-scheme deep link'ler - her biri dosya+satır kanıtıyla. Her hedefi (`relaunch` vs `in-app`) fiyatlandırır ve bir çalıştırma `plan`ına gruplar, böylece bir relaunch o ekrandaki her in-app state'e hizmet eder. `targets_file` / `targets[]` hedef setini tarama yerine harici bir katalogdan verir; plan, gruplar, relaunch sayısı ve coverage kapısı aynı şekilde çalışır. Bir denetime "UI'da bitmiş hissedene kadar gez" yerine sayılabilir bir hedef seti verir. |
285
295
  | `design_mock_launch` | Kurulu bir uygulamayı mock modda başlat (iOS UserDefaults launch arg / Android intent extra). |
286
296
  | `design_ui_geometry` | Piksel-seviyesi boşluk ölçümü için mevcut ekranın düz element bounding box'ları + ekran boyutu. |
297
+ | `design_component_variants` | Bir tasarım node'unu component set'ine çözümle ve varyantlarını (`State=Error`, `Rows=3`) listele; veri çağıranın zaten çektiği Figma verisidir (REST `nodes` yanıtı ya da MCP `get_metadata` XML'i, artı kütüphanenin `component_sets` listesi; sunucu Figma'ya hiç bağlanmaz). Varyant başına geometri spec'i, frame, render isteği ve Code Connect adı döner, denetlenen state'leri isimle varyantlara eşler, hâlâ çekilmesi gereken node ve render'ları listeler. Canlı component bölgesini kendi varyantıyla karşılaştırmak fixture satır sayısı farkını geometri bulgularından çıkarır. |
287
298
  | `design_visual_compare` | Bir Figma render'ını canlı bir screenshot ile boyut uyuşmazlığında başarısız olmadan karşılaştır: ölçeği normalize eder, chrome'u kırpar, algısal diff %'sini, boşluk/boyut/pozisyonu (px), rengi (ΔE) ve tipografiyi raporlar. figma/live/diff/overlay/side-by-side PNG'leri yazar. |
288
- | `design_report` | Bir tasarım-denetim rapor nesnesini kendi kendine yeten HTML'e (base64 görseller, CSS-konumlandırılmış annotasyonlar) + opsiyonel PDF'e render et. Bir coverage kapısı zorlar: her hedef denetlenmeli ya da açık bir gerekçeyle atlanmalı, böylece kısmi bir denetim temiz bir rapor olarak render edilemez. Metin bir label pack'ten gelir (varsayılan İngilizce, Türkçe dahili olarak yerleşik). |
299
+ | `design_report` | Bir tasarım-denetim rapor nesnesini kendi kendine yeten HTML'e (base64 görseller, CSS-konumlandırılmış annotasyonlar) + opsiyonel PDF'e render et. Bir coverage kapısı zorlar: her hedef denetlenmeli ya da açık bir gerekçeyle atlanmalı, böylece kısmi bir denetim temiz bir rapor olarak render edilemez. Metin bir label pack'ten gelir (varsayılan İngilizce, Türkçe dahili olarak yerleşik). Özet modu (`modules[]`) modül başına bir satır render eder - kapsam, kapı, sapmalar, modül raporuna link - ve herhangi bir modül kendi kapısını geçemezse başarısız olur. |
300
+
301
+ ### Code Intelligence Araçları (8)
302
+
303
+ Swift ve Kotlin kaynağı hakkında, her platformun zaten getirdiği dil sunucusu üzerinden derleyici seviyesinde cevaplar. Kotlin tarafı JetBrains `kotlin-lsp` (Alpha) kullanır ve bu repo'daki hiçbir kapı onu çalıştırmaz.
304
+
305
+ | Araç | Açıklama |
306
+ |------|----------|
307
+ | `code_definition` | Bir sembolün tanımlandığı yer; 1-tabanlı satır+sütun ya da `symbol` adı alır |
308
+ | `code_references` | Workspace genelinde her referans; index'in oturup oturmadığını raporlar |
309
+ | `code_hover` | Bir konumdaki tip, imza ve doc comment |
310
+ | `code_document_symbols` | Tek bir dosyanın sembol ağacı |
311
+ | `code_workspace_symbols` | Workspace genelinde isimle sembol arama |
312
+ | `code_diagnostics` | Tam build olmadan tek dosyanın derleyici tanılamaları |
313
+ | `code_index_status` | Dil başına: sunucu kurulu mu, hangi build sistemi bulundu, diskte index var mı |
314
+ | `code_server_reset` | Havuzdaki dil sunucularını durdurur |
315
+
316
+ ### Wallet Pass Araçları (4)
317
+
318
+ | Araç | Açıklama |
319
+ |------|----------|
320
+ | `pass_validate` | pass.json, `.pass` dizini ya da `.pkpass`'i Apple kurallarına göre denetler, bulguları sonucuna göre derecelendirir |
321
+ | `pass_build` | `.pkpass` üretir, imzalar ve arşivler; önce doğrular |
322
+ | `pass_inspect` | Bir `.pkpass`'in içeriğini raporlar: stil, semantik etiketler, görseller, manifest bütünlüğü, imza zinciri |
323
+ | `pass_certificates` | İmza materyalini raporlar; anahtar materyalini okumaz |
324
+
325
+ ### Web Araçları (18)
326
+
327
+ Opsiyonel peer dependency olan Playwright üzerinden headless tarayıcı kontrolü. Çağrılar arasında tek tarayıcı ve tek context kullanılır.
328
+
329
+ | Araç | Açıklama |
330
+ |------|----------|
331
+ | `web_goto` | Bir URL açar. `browser` (chromium / webkit / firefox), `wait_until`, `timeout_ms`, `viewport`, `locale` ve `user_agent` alır |
332
+ | `web_screenshot` | Mevcut sayfanın screenshot'ı, satır içi PNG ya da `path`'e yazılmış |
333
+ | `web_click` | CSS selector, metin ya da `web_snapshot`'tan bir `ref` ile tıklar |
334
+ | `web_type` | Selector ya da `ref` ile eşleşen input'a yazar |
335
+ | `web_eval` | Sayfada JavaScript çalıştırır, sonucu JSON döner |
336
+ | `web_wait_for` | Bir selector'ın belirli bir duruma gelmesini bekler |
337
+ | `web_get_text` | Selector ya da `ref`'in ilk eşleşmesinin textContent'i |
338
+ | `web_close` | Tarayıcı context'ini kapatır |
339
+ | `web_snapshot` | Her düğümde sabit bir `[ref=eN]` olan erişilebilirlik snapshot'ı |
340
+ | `web_console` | Son `web_goto`'dan beri console mesajları |
341
+ | `web_network` | Son `web_goto`'dan beri istekler: method, status, tip, URL |
342
+ | `web_tabs` | Açık sayfaları listeler, aktif olanı değiştirir |
343
+ | `web_storage_state` | Cookie ve localStorage'ı okur ya da kayıtlı bir durumu geri yükler |
344
+ | `web_extract` | Sayfanın makale içeriği Markdown (ya da metin) olarak |
345
+ | `web_map` | Mevcut sayfadaki aynı-origin linkler, tekilleştirilmiş |
346
+ | `web_crawl` | Sınırlı aynı-origin crawl, robots.txt'ye uyar, her sayfa `context_search` için indekslenir |
347
+ | `web_press_key` | Bir tuşa basar, isteğe bağlı olarak bir elemana odaklanarak |
348
+ | `web_select_option` | Bir `<select>` seçeneğini değer ya da etiketle seçer |
349
+
350
+ ### Context Index Araçları (3)
351
+
352
+ | Araç | Açıklama |
353
+ |------|----------|
354
+ | `context_index` | Bir metin dosyasını SQLite FTS5 index'ine ekler; değişmemiş dosya no-op |
355
+ | `context_search` | bm25 ile sıralanmış parçalar, her sonuçta kısa snippet ve chunk id |
356
+ | `context_get` | Bir parçanın tamamı, dosyası ve satır aralığıyla |
357
+
358
+ ### Research Araçları (2)
359
+
360
+ | Araç | Açıklama |
361
+ |------|----------|
362
+ | `research_search` | Brave ya da Perplexity üzerinden web araması, title / url / snippet'e normalize. Anahtar `BRAVE_API_KEY` ya da `PERPLEXITY_API_KEY`'den, asla argüman olarak değil |
363
+ | `research_ask` | Perplexity Sonar'dan atıflı cevap. Anahtar `PERPLEXITY_API_KEY`'den |
364
+
365
+ ### Media Araçları (1)
366
+
367
+ | Araç | Açıklama |
368
+ |------|----------|
369
+ | `media_frames` | Bir videodan anahtar kareler PNG olarak, benzerleri elenmiş. ffmpeg gerektirir |
370
+
371
+ ### Agent Araçları (2)
372
+
373
+ | Araç | Açıklama |
374
+ |------|----------|
375
+ | `agent_run_steps` | ios / android / web / design adımlarından oluşan bir batch'i tek çağrıda çalıştırır, adım başına durum ve verdict döner |
376
+ | `agent_query_output` | Satır içi dönemeyecek kadar büyük önceki bir çağrının kaydedilmiş tam çıktısını arar |
377
+
378
+ ### Security Araçları (2)
379
+
380
+ | Araç | Açıklama |
381
+ |------|----------|
382
+ | `security_cvss_score` | Bir temel vektörden CVSS 3.1 skoru ve bandı, çevrimdışı |
383
+ | `security_dep_inventory` | Bir lockfile'ı `{ecosystem, name, version}` listesine normalize eder, çevrimdışı |
289
384
 
290
385
  ### Kullanım Senaryoları
291
386