docs · docs/20-control-plane/MCP_TOOL_CATALOG.md · synced 2026-09-10

MCP tool catalog

every MCP tool, the Local API method behind it, its danger level

Purpose: the concrete list of MCP tools, each mapping to a Local API method. This is the agent-facing surface. Danger column drives required policy mode.

Danger: 🟢 read/safe · 🟡 mutating/normal · 🔴 dangerous (power/danger mode + audit).

Profiles

Tool Maps to Danger
vflin_profile_list profile.list 🟢
vflin_profile_get profile.get 🟢
vflin_profile_create profile.create 🟡
vflin_profile_start profile.start 🟡
vflin_profile_stop profile.stop 🟡
vflin_profile_delete profile.delete (hard=🔴) 🟡/🔴

Fingerprint

| vflin_fingerprint_generate | fingerprint.generate | 🟢 | | vflin_fingerprint_validate | fingerprint.validate | 🟢 | | vflin_fingerprint_presets | fingerprint.catalog.list | 🟢 | | vflin_fingerprint_generate_from_host | fingerprint.generateFromHost | 🟢 | | vflin_node_characterize | node.characterize | 🟢 |

Proxy

| vflin_proxy_list | proxy.list | 🟢 | | vflin_proxy_test | proxy.test | 🟢 | | vflin_proxy_bind | proxy.bind | 🟡 |

Automation

| vflin_automation_run | automation.run | 🟡 | | vflin_automation_status | automation.status | 🟢 | | vflin_automation_cancel | automation.cancel | 🟡 | | vflin_automation_group_schedule | automation.group.schedule | 🟡 |

Sync

| vflin_sync_status | sync.status | 🟢 | | vflin_sync_push / vflin_sync_pull | sync.push/pull | 🟡 |

Core & system

| vflin_core_list | core.list | 🟢 | | vflin_core_diagnose | core.diagnose | 🟢 | | vflin_system_health | system.health | 🟢 | | vflin_log_tail | log.tail | 🟢 |

Dangerous (🔴 — power/danger mode, always audited)

Tool Maps to Why dangerous
vflin_vault_read vault.get exposes secrets
vflin_cookies_export vault.export(scope=cookies) exfiltratable session material
vflin_profile_hard_delete profile.delete{hard} irreversible
vflin_profile_mass_update batched profile.* wide blast radius
vflin_browser_eval core CDP Runtime.evaluate arbitrary in-page code
vflin_migration_import importer ingests untrusted external data
vflin_profile_cdp_attach profile.cdp.attach hands a live profile’s CDP to code the daemon does not see — one client, through a revocable door (A89, ADR-0038)

CDP through the daemon (A89, ADR-0038 Accepted)

A profile’s core speaks CDP over a pipe only the daemon holds — by default nothing on disk, no port. An agent that needs raw CDP on a running profile calls vflin_profile_cdp_attach (danger: VFLIN_MCP_MODE=trusted, fail-closed) and gets {wsEndpoint, expiresAt, brokered} — a loopback ws:// for ONE client, revoked by vflin_profile_cdp_detach, by its TTL (default 15 min) or by the profile’s stop; vflin_profile_cdp_sessions (normal) is the green read that says what is open. A profile the operator set to cdpTransport: port answers its own public endpoint with brokered:false. Measured: a second client on a door is refused at once; after detach the endpoint refuses the dial.

Rules

  • 🔴 tools refuse unless session policy mode ≥ required; refusal explains how to elevate.
  • Every 🟡/🔴 call writes an Action Log entry (tool, args-summary, mode, result).
  • New tools are added here only when a backing Local API method exists.

Open questions

Whether vflin_browser_eval ships at all in v1, or stays behind a build flag → SECURITY_POLICY.md / OPEN_QUESTIONS.md.

Sessions (Feature c — ADR-0034)

No hand-written session tools exist, and none should: tools/list is built entirely from the generated SURFACE table, so all five session operations surface automatically as vflin_profile_session_{list,get,set,clear} and vflin_session_recipe_list, carrying the contract’s own mode and danger level. MCP is the one surface that structurally cannot drift from the contract.

Danger gating, as enforced today:

Tool Danger Needs
vflin_session_recipe_list, vflin_profile_session_list, vflin_profile_session_get 🟢 read-only
vflin_profile_session_set, vflin_profile_session_clear 🔴 VFLIN_MCP_MODE=trusted; refused before any daemon call

One thing an agent author must know: vflin_profile_start is 🟡, but starting a profile whose automated login has not run yet would submit stored credentials and a 2FA code to a third party. The daemon therefore computes the required mode from the profile’s bindings, not from the route, and refuses with SESSION_LOGIN_MODE_REQUIRED below danger. Cookie injection is unaffected — restoring a profile’s own saved state stays a normal-mode start.

And the honest limit of that protection: the MCP session mode is process-wide, so a server started with VFLIN_MCP_MODE=trusted sends x-vflin-mode: danger on every call — including the 🟡 start. The gate therefore never fires for a trusted agent. That is consistent with mode being session-scoped (SECURITY_POLICY §1), and such an agent could call vflin_profile_session_set anyway, so it grants nothing new — but do not read the gate as “a trusted agent still cannot trip a credential login”. It protects the DEFAULT (read-only / normal) agent, which is the one an untrusted prompt is most likely to be driving.