# SynaBun (npm · synabun)

Persistent memory MCP server for Claude Code, Codex and OpenCode, stored locally in SQLite

- Trust score: 72/100 (medium)
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-11-04

## Components

- npm · `synabun`: 72/100 (this document), [markdown](https://verifymcp.io/servers/danilokhury-synabun/synabun.md), [page](https://verifymcp.io/servers/danilokhury-synabun/synabun)

## Channel facts

- Registry: `npm`
- Package: `synabun`
- Version: `2.1.0`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-11-04.

- **Supply Chain Security**: 83/100
  - No malware found by supply-chain analysis.
  - CVE check failed: a known high-severity CVE affects sharp 0.34.5, reached via @huggingface/transformers > sharp. A fixed version is available.
  - Declares code that runs automatically (postinstall) and that we could not recognise. It may be perfectly ordinary, but we have not established what it does.
  - 103 of 344 dependencies flagged as unhealthy (2 deprecated).
- **Provenance & Transparency**: 100/100
  - Source repository is publicly reachable at the declared URL.
  - Cryptographically verified build provenance (signed, bound to danilokhury/Synabun).
  - Clear OSI-approved license (Apache-2.0).
  - Actively maintained (last published 0 days ago).
  - Publishes a security disclosure policy (SECURITY.md).
- **Schema Quality & AI Usability**: 59/100
  - AI-judged instruction clarity (good).
  - Context-footprint check failed: tool/resource definitions use about 28604 tokens (~210/item across 136 items; 136 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 0/100
  - Stability not yet verified: not enough scan history yet (needs a 30-day window).
- **Tool Coverage**: 96/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 87% of tool parameters carry a description.
- **Tool Safety**: 75/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - 0 of 2 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "browser_evaluate" implies "execute" and declares no destructiveHint at all, which the MCP spec reads as destructive by default.
  - An AI judge read all 137 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

**Unverified: 1 category.** A category scored 0 because we could not verify it: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.

## Install

### How do I install the SynaBun MCP server?

SynaBun runs locally as an npm package, launched with npx -y synabun. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add danilokhury-synabun -- npx -y synabun
```

### Cursor

```json
{
  "mcpServers": {
    "danilokhury-synabun": {
      "command": "npx",
      "args": [
        "-y",
        "synabun"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "danilokhury-synabun": {
      "command": "npx",
      "args": [
        "-y",
        "synabun"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add danilokhury-synabun -- npx -y synabun
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "danilokhury-synabun": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "synabun"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add danilokhury-synabun --command npx --arg -y --arg synabun
```

### Hermes

```yaml
mcp_servers:
  danilokhury-synabun:
    command: "npx"
    args: ["-y", "synabun"]
```

### Netclaw

```json
{
  "McpServers": {
    "danilokhury-synabun": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "synabun"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add danilokhury-synabun -t stdio -c npx -a -y synabun
```

### Other

```json
{
  "mcpServers": {
    "danilokhury-synabun": {
      "command": "npx",
      "args": [
        "-y",
        "synabun"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-10-31 (score 72, 0)

- [security regression] CVE-2026-118764 affects this package: high
- [security regression] CVE-2026-118773 affects this package: high

### 2026-10-30 (score 72, +15)

- [security improvement] Malware scan: unverified → pass

### 2026-10-29 (score 57)

First indexed and scored.

## MCP tools (136)

### `remember` (~417 tokens)

Store a piece of information in persistent memory. Use this when you learn something important, make a decision, discover a pattern, fix a hard bug, or want to preserve context for future sessions.

Input parameters:

- `category` (string, required): REQUIRED. Category name (top-level bucket) to file this memory under. Call the category tool with action "list" for valid names, or action "create" if nothing fits. Distinct from subcategory. An unre…
- `content` (string, required): The information to remember. Be specific and include context.
- `idempotency_key` (string): Retry key scoped to project and category. Same key/content returns the existing UUID.
- `importance` (number): Set this deliberately on every call: 1=trivial, 5=routine, 7=significant, 8+=critical. Use 8+ for hard-won bug fixes and architecture decisions. Omit only when the work is genuinely routine (defaults…
- `kind` (string): Memory kind; defaults to note.
- `project` (string, required): REQUIRED. Project this belongs to, lowercase kebab-case (e.g. "my-web-app", "synabun"). Use the project named in your session context — this is NOT reliably auto-detected over the HTTP transport, whe…
- `related_files` (array): File paths this memory relates to.
- `source` (string): How this was learned. user-told=user explicitly shared, self-discovered=found during work, auto-saved=session context.
- `source_ref` (string): Local session/event identifier or source reference.
- `subcategory` (string): Optional refinement: architecture, bug-fix, api-quirk, performance, config, deployment, etc.
- `tags` (array): Tags for categorization (e.g. ["redis", "cache", "pricing"])

### `recall` (~452 tokens)

Search your persistent memory for relevant information. Use this at the start of any task to check what you already know, or when you need context about past decisions, known issues, or architectural patterns. Prefer format="compact" for discovery; use memories action="get" for full originals.

Input parameters:

- `after` (string): Include records created at or after this ISO timestamp.
- `before` (string): Include records created at or before this ISO timestamp.
- `category` (string): Optional: filter by category name.
- `explain` (boolean): Include retrieval reasons in compact output.
- `format` (string): Optional compact, budgeted excerpts. Default preserves full legacy output.
- `include_sessions` (boolean): Override session chunk search. Auto-triggers on temporal queries or sparse results. Set true to force, false to disable.
- `limit` (number): Number of results. User configured: 5. OMIT this parameter to respect the user's setting. Only override if the user explicitly asks for a different count.
- `min_importance` (number): Minimum importance threshold.
- `min_score` (number): Minimum similarity score 0-1. User configured: 0.3. OMIT to use configured setting.
- `project` (string): Optional: filter by project. If omitted, searches all projects but boosts current project.
- `query` (string, required): What to search for, in natural language.
- `recency_boost` (boolean): Prioritize recent memories. User configured: OFF. OMIT to use configured setting. Shifts scoring to favor recency over semantic similarity (14-day half-life, 55% recency weight). Ideal for session-st…
- `rerank` (boolean): Judge the shortlist for relevance after retrieval and reorder it. Slower — worth it when the query is subtle and the top hits look interchangeable.
- `scope` (string): Project requires an explicit project or caller context; never widens the search.
- `tag_match` (string): Match any tag (default) or require every tag.
- `tags` (array): Optional: filter by tags (any match).
- `token_budget` (integer): Total estimated output tokens for compact format; default 1500.

### `forget` (~70 tokens)

Move a specific memory to trash by ID. The memory can be restored from the Neural Interface trash panel or via the restore tool. Use this to clean up outdated, incorrect, or superseded information.

Input parameters:

- `memory_id` (string, required): The memory ID to move to trash. Use the full UUID from recall results.

### `restore` (~43 tokens)

Restore a trashed memory by ID. Use this to undo a forget operation.

Input parameters:

- `memory_id` (string, required): The memory ID to restore from trash. Use the full UUID.

### `reflect` (~267 tokens)

Update or annotate an existing memory. Use this when you discover additional context, when a decision changes, or when you want to adjust importance based on new information.

Input parameters:

- `add_tags` (array): Add tags without replacing existing ones.
- `category` (string): Change the category name.
- `content` (string): Updated content. If provided, the embedding vector is regenerated.
- `expected_revision` (integer): Reject if the memory changed since this revision.
- `importance` (number): Updated importance score.
- `memory_id` (string, required): The ID of the memory to update. MUST be the full UUID format (e.g., 8f7cab3b-644e-4cea-8662-de0ca695bdf2), not a shortened version. Use recall to get the full UUID.
- `project` (string): Change the project this memory belongs to (e.g. "my-web-app", "synabun").
- `related_files` (array): Updated related file paths.
- `related_memory_ids` (array): Link to related memories.
- `subcategory` (string): Updated subcategory.
- `supersedes` (string): Explicitly mark another memory in this project as superseded by this one.
- `tags` (array): Replace all tags with these.

### `memories` (~326 tokens)

Browse recent memories, get statistics, or fetch one memory in FULL by id. Use action "get" with an id to pull a large/consolidated memory untruncated (list actions truncate content to 150 chars). Use to see what you remember about a project, review recent learnings, or check memory health.

Input parameters:

- `action` (string, required): recent=latest memories, stats=counts and health, by-category=filter by type, by-project=filter by project, get=FULL untruncated content of one memory by id (no vector search), triage=forget candidate…
- `category` (string): Category to filter by (for by-category action).
- `expected_revision` (integer): Required current revision for undo.
- `feedback` (string): Feedback signal; never treated as proof of correctness.
- `id` (string): Memory id (required for action "get"). Returns that memory's full content untruncated — use to fetch a consolidated/large memory directly.
- `ids` (array): UUIDs for get-batch; maximum 50.
- `limit` (number): Number of results (default 10).
- `operation` (string): Maintenance operation; default status.
- `project` (string): Filter by project (for by-project action).
- `relation_id` (string): Relationship to undo.
- `revision` (integer): Revision to restore for undo.
- `token_budget` (integer): Estimated token budget for context; default 1500.

### `category` (~227 tokens)

Manage memory categories. Actions: create, update, delete, list. Categories persist across sessions.

Input parameters:

- `action` (string, required): Action to perform: create, update, delete, or list categories.
- `color` (string): Color hex code, e.g. "#3b82f6". Empty string "" to remove.
- `description` (string): Category description (required for create, optional for update).
- `format` (string): Output format for list action: flat, tree (default), or parents-only.
- `is_parent` (boolean): Make this a parent/cluster category (create only).
- `name` (string): Category name (required for create/update/delete).
- `new_name` (string): Rename category to this (update only).
- `parent` (string): Parent category name. Empty string "" to remove parent.
- `reassign_children_to` (string): Reassign child categories to this parent when deleting a parent. Empty string "" for top-level (delete only).
- `reassign_to` (string): Reassign memories to this category before deleting (delete only).

### `sync` (~152 tokens)

Check for stale memories whose related files have changed. Compares stored file checksums against current hashes. Returns compact output (ID + changed files only, no content). IMPORTANT: Always pass "categories" to scope the scan — calling without categories scans ALL memories and may produce output too large to return inline. For large memory sets, call iteratively per category rather than globally. Default limit is 50; increase only when using a narrow category filter.

Input parameters:

- `categories` (array): Optional: filter results to memories in these categories only.
- `limit` (number): Max stale memories to return (default 50). Keep low to avoid output overflow.
- `project` (string): Optional: only check memories for this project.

### `loop` (~241 tokens)

Autonomous loop control. Start a repeating task loop, check status, update progress journal, or stop it. The Stop hook drives iteration. Call "update" after each iteration with a brief summary to maintain context across compactions.

Input parameters:

- `action` (string, required): start: begin autonomous loop. stop: end loop. status: check current loop state. update: write iteration journal/progress.
- `context` (string): Extra context injected each iteration.
- `iterations` (number): Max iterations (1-50, default 10).
- `max_minutes` (number): Time cap in minutes (1-480, default 60).
- `progress` (string): Rolling progress summary replacing the previous one. Used with action "update".
- `session_id` (string): Claude Code session ID. Auto-detected if omitted.
- `summary` (string): Brief summary of what this iteration accomplished (1-2 sentences, for journal). Used with action "update".
- `task` (string): What to do each iteration (required for start).
- `template` (string): Load a saved template by name or id. Template values are used as defaults; explicit params override.

### `tool_groups` (~231 tokens)

Always-available router for SynaBun's tool groups. When a task needs a SynaBun tool this runtime does not list, call action="get", then action="add" with the group that has it, and continue once the host refreshes its tools. On Codex and Claude Code every SynaBun tool is already reachable on demand, so there it only moves the focus and needs no reload. Do not report a SynaBun capability unavailable before trying this. A change affects only this runtime, never other sessions or the default for new ones.

Input parameters:

- `action` (string, required): get = this runtime's groups, what they do on this host, and the catalog. add = load more groups for this runtime. set = replace this runtime's groups.
- `groups` (array): Group ids for add and set, from the catalog that get returns, e.g. ["gsc"] or ["browser_whatsapp"]; "all" is every group. The memory tools, loop, tool_groups and choice are always there; agents, skil…

### `choice` (~85 tokens)

Ask the user blocking multiple-choice questions through MCP form elicitation. Use this for SynaBun choices in Codex Default mode. If the result reports supported=false, ask the same numbered choices once in plain text and wait; do not call another question tool.

Input parameters:

- `questions` (array, required): One to three blocking multiple-choice questions. Each question must have two to four mutually exclusive options.

### `browser_batch` (~119 tokens)

Run up to 10 known browser steps sequentially on one owned tab. Uses existing guarded tools, stops on the first failure, and returns one final snapshot by default. Never retry the whole batch after a partial failure. Steps run exactly as written: no Jev assistance inside a batch. A batch that navigated may end with one advisory "assessment" of the final page.

Input parameters:

- `sessionId` (string)
- `snapshot` (string): Final observation; default full.
- `steps` (array, required)
- `tabId` (string)

### `browser_navigate` (~284 tokens)

Navigate the browser to a URL (auto-creates a session if needed). By default the response includes an AI snapshot of the new page with [ref=eN] element refs — act on them directly with browser_click/fill/type, no separate snapshot call needed. A "Jev assessment:" line may follow (usable, loading, authentication_required, verification_required, consent_blocker, error, empty): it is advice about the page, never an action. On a sign-in or verification wall, stop and hand over to a human.

Input parameters:

- `intent` (string): What you expect this page to let you do or show (e.g. "read my open invoices"). Adds a "goal satisfied" estimate to the page assessment. Advisory only.
- `returnSnapshot` (object): Legacy inline snapshot (tree modes). Prefer the "snapshot" param, which returns ref-based AI snapshots.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session or creates a new one.
- `snapshot` (string): Inline AI snapshot of the new page (default "full", with [ref=eN] refs for actions). "none" = terse response.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `url` (string, required): The URL to navigate to.

### `browser_go_back` (~64 tokens)

Go back to the previous page in browser history.

Input parameters:

- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_go_forward` (~64 tokens)

Go forward to the next page in browser history.

Input parameters:

- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_reload` (~68 tokens)

Reload the current page. Useful after making changes or when content is stale.

Input parameters:

- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_click` (~356 tokens)

Click an element. Pass ref (e.g. "e12") from browser_snapshot — exact, no guessing. Selector is the fallback (CSS, text="...", :has-text(...), role=...; never :contains()). By default the response includes an AI snapshot diff of what changed, so you usually do NOT need a follow-up browser_snapshot.

Input parameters:

- `nthMatch` (integer): If the selector matches multiple elements, target the Nth (0-indexed).
- `ref` (string): Element ref from browser_snapshot, e.g. "e12". Preferred over selector — exact match, no guessing.
- `returnSnapshot` (object): Legacy inline snapshot (tree modes). Prefer the "snapshot" param, which returns ref-based AI snapshots.
- `selector` (string): Playwright selector for the element to click (CSS, text="...", :has-text("..."), role=..., [data-testid="..."]). Fallback when you have no ref. NEVER use :contains().
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `snapshot` (string): Inline AI snapshot after the click. Default "diff" = only the changed region vs your last snapshot. "none" = terse response.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `textHint` (string): What you meant to click, in words (e.g. "Account settings"). If the selector matches nothing the server first tries an exact role+name match; failing that, the visible candidates are ranked against t…

### `browser_fill` (~237 tokens)

Clear an input/textarea and fill it with new text. Pass ref from browser_snapshot (preferred) or a selector. For contenteditable editors prefer browser_type.

Input parameters:

- `nthMatch` (integer): If the selector matches multiple elements, fill the Nth (0-indexed).
- `ref` (string): Element ref from browser_snapshot, e.g. "e12". Preferred over selector — exact match, no guessing.
- `selector` (string): Playwright selector for the input/textarea to fill (CSS, text="...", :has-text("..."), role=..., [data-testid="..."]). Fallback when you have no ref. NEVER use :contains().
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `textHint` (string): Auto-heal: if the selector matches 0 elements, server retries with role=*[name~="<textHint>"].
- `value` (string, required): The text value to fill. Clears existing content first.

### `browser_type` (~293 tokens)

Type text (simulates keystrokes; appends). Target by ref from browser_snapshot (preferred), selector, or omit both to type into the focused element. Prefer over browser_fill for contenteditable/rich-text editors.

Input parameters:

- `mode` (string): "sequential" = per-key events. "insert" = bulk insertText, fast, safe for modal composers. "paragraphs" = Escape+Enter between paragraphs (never on modals — Escape closes them). See browser_cheatshee…
- `nthMatch` (integer): If the selector matches multiple elements, type into the Nth (0-indexed).
- `ref` (string): Element ref from browser_snapshot, e.g. "e12". Preferred over selector — exact match, no guessing.
- `selector` (string): Playwright selector for the element to type into. If both ref and selector are omitted, types into the focused element.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `text` (string, required): The text to type character by character (appends to existing content).
- `textHint` (string): Auto-heal: if the selector matches 0 elements, server retries with role=*[name~="<textHint>"].

### `browser_hover` (~218 tokens)

Hover over an element (reveals dropdowns, tooltips, hover-triggered content). Pass ref from browser_snapshot (preferred) or a selector.

Input parameters:

- `nthMatch` (integer): If the selector matches multiple elements, hover over the Nth (0-indexed).
- `ref` (string): Element ref from browser_snapshot, e.g. "e12". Preferred over selector — exact match, no guessing.
- `selector` (string): Playwright selector for the element to hover over (CSS, text="...", :has-text("..."), role=..., [data-testid="..."]). Fallback when you have no ref. NEVER use :contains().
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `textHint` (string): Auto-heal: if the selector matches 0 elements, server retries with role=*[name~="<textHint>"].

### `browser_select` (~235 tokens)

Select an option from a <select> dropdown by ref or selector, and option value.

Input parameters:

- `nthMatch` (integer): If the selector matches multiple elements, select from the Nth one (0-indexed).
- `ref` (string): Element ref from browser_snapshot, e.g. "e12". Preferred over selector — exact match, no guessing.
- `selector` (string): Playwright selector for the <select> element (CSS, text="...", :has-text("..."), role=..., [data-testid="..."]). Fallback when you have no ref. NEVER use :contains().
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `textHint` (string): What the dropdown is for, in words (e.g. "Country"). If the selector matches nothing, the server tries an exact role+name match and the visible candidates are ranked against this phrase. Advisory.
- `value` (string, required): The option value to select.

### `browser_press` (~106 tokens)

Press a keyboard key or key combination. Supports modifiers like Control+A, Shift+Enter, etc.

Input parameters:

- `key` (string, required): Key or key combo to press (e.g. "Enter", "Tab", "Control+A", "Escape", "ArrowDown").
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_scroll` (~212 tokens)

Scroll the page or a scrollable container (by ref or selector). Essential for infinite-scroll feeds — but for harvesting feed data, prefer the browser_extract_* tools with their scrolls param, which scroll+extract+dedupe in one call.

Input parameters:

- `direction` (string, required): Direction to scroll.
- `distance` (number): Pixels to scroll (default: 500).
- `ref` (string): Scroll within the container with this ref from browser_snapshot.
- `returnSnapshot` (object): Legacy inline snapshot (tree modes). Prefer the "snapshot" param, which returns ref-based AI snapshots.
- `selector` (string): Scroll within a specific scrollable element instead of the window.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `snapshot` (string): Optionally include an AI snapshot after scrolling ("diff" = only what changed).
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_upload` (~260 tokens)

Upload files via a file input element (by ref or selector). For hidden/gated inputs, click the visible upload button first to reveal the input. See browser_cheatsheet for per-platform upload flows.

Input parameters:

- `filePaths` (array, required): Absolute file paths to upload.
- `nthMatch` (integer): If the selector matches multiple file inputs, upload to the Nth (0-indexed).
- `ref` (string): Element ref from browser_snapshot, e.g. "e12". Preferred over selector — exact match, no guessing.
- `selector` (string): Playwright selector for the file input element (CSS, text="...", :has-text("..."), role=..., [data-testid="..."]). Fallback when you have no ref. NEVER use :contains().
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `textHint` (string): What the upload control is, in words (e.g. "Add photo"). If the file input is not found, the visible controls are ranked against this phrase — usually the button that reveals the hidden input. Adviso…

### `browser_snapshot` (~439 tokens)

Observe page structure and element refs for click/fill/type. Scope with selector on complex pages. AI mode deduplicates delivered observations and supports snapshot IDs and diffs. Refs target elements in the latest captured scope; refresh after navigation or a stale-ref error.

Input parameters:

- `baselineId` (string): Diff against this delivered snapshot ID. A missing or incompatible baseline returns a full view.
- `depth` (integer): Limit tree depth (mode="ai" only). Use 10-14 on deep feed pages to shrink output.
- `diff` (boolean): Return only the changed region vs your previous snapshot of this tab (mode="ai" only).
- `force` (boolean): Return the full snapshot even if the page is unchanged since your last snapshot.
- `format` (string): Only meaningful with mode="interactive": "json" = compact array.
- `intent` (string): What you want to do on this page, in words (e.g. "open account settings"). mode="ai" only: the refs of THIS snapshot are ranked against it and the best one is named in a "Jev target:" line. Advisory…
- `maxChars` (integer): Cap snapshot text in characters, excluding brief metadata (default 30000). Truncates at complete lines.
- `mode` (string): "ai" (default) = compact YAML with [ref=eN] element refs — pass ref to browser_click/fill/type to act on elements. "interactive" = flat list of clickable elements with selector hints. "full" = legacy…
- `selector` (string): Scope snapshot to a specific element's subtree. Dramatically reduces output on complex pages.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `viewport` (boolean): Drop off-screen nodes (legacy modes only; ignored for mode="ai" — use depth/selector instead).

### `browser_content` (~204 tokens)

Get the content of the current page. Set format="markdown" for clean markdown with structure preserved — preferred for LLM consumption. Returns up to maxChars (default 20000); pass offset to page through long pages.

Input parameters:

- `format` (string): Output format. "text" = raw innerText. "markdown" = clean markdown (headings/links/lists, nav/footer/ads stripped) — better for LLM consumption.
- `maxChars` (integer): Max characters returned (default 20000). Response notes total size when truncated.
- `offset` (integer): Character offset to continue a previously truncated read.
- `selector` (string): Read one article or result container instead of the whole page. Must match exactly one element.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_screenshot` (~403 tokens)

Take a screenshot of the current page (localhost pages included): the viewport as JPEG, downscaled to 1024 px wide, by default. For visual QA pass width/height (breakpoints 375 / 768 / 1440 — emulated for this capture only), fullPage for the whole page, and save or path to write a PNG and get its path. Prefer browser_snapshot to read structure; it is far more token-efficient.

Input parameters:

- `format` (string): Image format. Default: JPEG for the returned image, PNG for a saved file.
- `fullPage` (boolean): Capture the whole scrollable page instead of the viewport.
- `height` (integer): Viewport height in CSS px for this capture only (default: the current height).
- `maxWidth` (integer): Downscale the returned image to this width in px (default 1024). 0 = native resolution. A saved file is always full resolution.
- `path` (string): Absolute .png / .jpg / .jpeg file to save to, inside a registered project or the screenshots folder (implies save). Parent folders are created; only an existing image is ever replaced.
- `quality` (integer): JPEG quality 10-100 (default 60 for the returned image, 90 for a saved JPEG).
- `save` (boolean): Also save the full-resolution image as a file (default folder ~/.synabun/data/media/screenshots/<date>/) and return its path.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `width` (integer): Viewport width in CSS px for this capture only, e.g. 375, 768 and 1440 for breakpoints. Emulated on the tab (mobile below 768) and reset right after.

### `browser_console` (~227 tokens)

Read the current tab's console messages and uncaught page errors (the last 200, kept from when SynaBun opened the tab), localhost pages included. Use level "error" to check a page for errors, and clear or since to see only what a reload or an action produced.

Input parameters:

- `clear` (boolean): Empty the tab's buffer after reading, so the next call shows only new entries.
- `level` (string): Lowest level to return; each level includes the more severe ones (error < warning < info < log). Default "all". Uncaught page errors count as errors.
- `limit` (integer): Return at most this many of the newest matching entries (default 50).
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `since` (string): Only entries after this time (ISO timestamp or epoch ms), e.g. the "latest" value of a previous call.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_evaluate` (~131 tokens)

Execute JavaScript in the browser page context and return the result. Useful for reading DOM state, extracting data, or performing actions not covered by other tools.

Input parameters:

- `expression` (string): Alias for "script" — accepted for compatibility with Playwright conventions.
- `script` (string): JavaScript code to execute in the browser page context. The return value will be serialized to JSON.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_wait` (~216 tokens)

Wait for an element to reach a certain state, a page load state, or a fixed timeout. Useful after navigation or clicks that trigger async content loading. Use loadState="networkidle" after posting on Twitter/X or after navigation to ensure all async requests have settled.

Input parameters:

- `loadState` (string): Page load state to wait for. Use "networkidle" after posting a tweet to confirm XHR requests settled. Takes priority over selector when provided.
- `selector` (string): CSS selector to wait for. If omitted and loadState also omitted, waits for timeout.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `state` (string): Element state to wait for (default: "visible"). Only used with selector.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `timeout` (number): Timeout in ms (default: 10000 for element waits, 15000 for loadState).

### `browser_session` (~101 tokens)

Manage browser sessions — list open sessions, create a new browser, or close an existing one.

Input parameters:

- `action` (string, required): "list" = list open sessions, "create" = open a new browser, "close" = close a session.
- `sessionId` (string): Session ID for "close" action. Required for close when multiple sessions exist.
- `url` (string): Starting URL for "create" action (default: about:blank).

### `browser_cheatsheet` (~121 tokens)

Look up stable selectors and flow notes for a social platform (twitter, facebook, tiktok, whatsapp, instagram, linkedin). Call this before automating a platform the first time in a session — then reuse the returned selectors for browser_click / browser_type / browser_fill / browser_scroll / browser_snapshot.

Input parameters:

- `action` (string): Optional: filter to a single action (click/type/fill/scroll/snapshot/extract/evaluate). If omitted, returns every action known for the platform.
- `platform` (string, required): Target platform to fetch selectors for.

### `browser_extract_tweets` (~282 tokens)

Extract visible tweets as structured JSON (author, handle, text, time, url, replies, reposts, likes, views). Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call (e.g. scrolls:3 minItems:30). Much faster than browser_snapshot for data harvesting. Navigate to x.com/search?q=%23hashtag&f=live first for latest-first hashtag results.

Input parameters:

- `fields` (array): Return only these fields; identity deduplication still uses the full items.
- `maxChars` (integer): Cap the JSON items in characters, keeping complete items. Defaults to no additional character cap.
- `maxItems` (integer): Cap on returned items (default 50).
- `minItems` (integer): Stop scrolling once this many unique items are collected.
- `scrolls` (integer): Auto-scroll up to N times, extracting + deduping after each (default 0 = current view only). Stops early at minItems or end of feed.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `timeoutMs` (integer): Total extraction deadline with browser V2 enabled (default 15000ms).

### `browser_x_compose_state` (~537 tokens)

Inspect the X/Twitter compose surface in ONE call (read-only). Returns: composerOpen, composerText (read back from [data-testid="tweetTextarea_0"]), charCount, overLimit; quoteCard {present, type:"quote"|"link"|"none", author, handle, text, url} — type "quote" means a real embedded quoted-tweet card rendered (safe to post a quote), "link" means only a plain link-preview card (posting would publish a bare reply — do NOT post; fix the status URL or skip the target), "none" means nothing embedded; submitButton {testid:"tweetButtonInline"|"tweetButton", present, enabled, selector} (tweetButtonInline for inline replies, tweetButton for the compose dialog); isModal (the glitchy centered reply dialog is open — close it and retry inline), composerCount (>1 ⇒ pass nthMatch to disambiguate the two reply textareas), hasStaleDraft (duplicated/garbled leftover text — discard and reopen), warnings[]; and recommendedAction {submit|type|open-composer|fix-quote-url|trim-text|unknown} — the deterministic next step. QUOTE flow: navigate x.com/compose/tweet, browser_type the full status URL, call this probe, post via submitButton.selector ONLY if quoteCard.type==="quote". REPLY flow: click the reply icon, call this probe, if isModal close it and retry inline, type, post via submitButton.selector. After submitting, re-call this probe (composer should have cleared) and confirm with browser_extract_tweets on the author profile /with_replies (a NEW, higher status id = published). On loop tabs a server-side gate ALSO blocks a tweetButton click when a status URL is in the body but quoteCard.type!=="quote" (response carries quoteGuard) — so a quote can never silently misfire into a bare reply. Read-only — never types or clicks. When recommendedAction is "unknown" or warnings[] is non-empty, an additive `judgment` {advisory:true, state, confidence, suggestedControl?, note} may appear: a Jev reading of the ambiguous probe built from booleans and counts only (never the composer text or the quot…

Input parameters:

- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_extract_fb_posts` (~254 tokens)

Extract visible Facebook posts as structured JSON (author, authorUrl, text, time, postUrl, reactions). Works on group feeds and Pages. Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call. Much faster than browser_snapshot for data harvesting from Facebook.

Input parameters:

- `fields` (array): Return only these fields; identity deduplication still uses the full items.
- `maxChars` (integer): Cap the JSON items in characters, keeping complete items. Defaults to no additional character cap.
- `maxItems` (integer): Cap on returned items (default 50).
- `minItems` (integer): Stop scrolling once this many unique items are collected.
- `scrolls` (integer): Auto-scroll up to N times, extracting + deduping after each (default 0 = current view only). Stops early at minItems or end of feed.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `timeoutMs` (integer): Total extraction deadline with browser V2 enabled (default 15000ms).

### `browser_fb_composer_state` (~755 tokens)

Inspect the Facebook posting surface in ONE call (read-only). Returns: modal {open,title,closeSelector,containsComposer} (modal.open is true ONLY for a visible posting dialog — FBs permanent hidden 0x0 Notifications dialog is ignored); trigger {found,text,suggestedSelector} — the Create-post button to CLICK first when no composer dialog is open yet (on a bare feed the probe can only see boxes that already exist, so use this to OPEN the composer; after opening, browser_type with NO selector into the auto-focused editor — selector-targeting the dialog editor is flaky); composers[] (search boxes filtered out) each with scope inline|dialog, inDialog, visible, rect, text, ariaLabel, placeholder, isPersonalProfile, isComment, isPostComposer (a comment box is flagged isComment and is NEVER a post composer — do not type a post into it), suggestedSelector; submitButton {label,scope,matchType,selector,enabled} scoped to the active visible dialog (matchType "label" = matched a publish/approval verb incl. German Senden/Veröffentlichen/Zur Genehmigung senden; "heuristic" = inferred as the dialog footer primary button when the label was untranslated, so verify via submission.state after clicking); submission {state: visible-post|pending-approval|posting-failed|composer-open|unknown, evidence}; and recommendedAction {submit|type|open-composer|done|retry|unknown} — the deterministic next step (submit = composer open with text AND an enabled submit button; use it to FINISH a half-typed post before starting anything new). Locale-tolerant (PT/EN/TR/FR/ES/DE incl. approval-flow groups). Flow: probe; if recommendedAction is "submit", click submitButton.selector and confirm FIRST; else if no composer dialog, click trigger.suggestedSelector; re-probe; type the full post into the auto-focused isPostComposer box with browser_type mode:"insert" (blank lines between paragraphs, link alone on the final line — insertText keeps the paragraphs and the isolated URL without firing Enter, so the ty…

Input parameters:

- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_extract_fb_groups` (~521 tokens)

Extract ALL JOINED Facebook groups from the current page (navigate to facebook.com/groups/joins/?ordering=viewer_added first) as a region-sorted index. Auto-scrolls the full virtualized joins list and dedupes by url in ONE call (defaults: scrolls:10, maxItems:1000 — override for very large/small lists). Each group {name, url, subtitle, member_count, region, lang, currency, source} is reconciled against the curated seed-queue memory first; groups not in it are classified from name+slug (language tokens: pt/tr/de/fr/es/pl/it/nl, and country aliases) into region + posting-currency, source:"name-heuristic"; the still-ambiguous ones land in region "Unknown" and under "unmatched". Spanish groups split into LatAm (USD) vs Spain (EUR). Returns { counts, byRegion: { UK:[...], US:[...], EU:[...], Brazil:[...], LatAm:[...], ... }, unmatched:[...] }. Pass region to filter to one bucket. Feed the whole JSON to fb_groups import {fromExtract} to populate/refresh the structured directory.

Input parameters:

- `fields` (array): Return only these fields; identity deduplication still uses the full items.
- `maxChars` (integer): Cap the complete grouped JSON response, preserving whole groups. Metadata must fit; unmatched duplicates are omitted first.
- `maxItems` (integer): Cap on returned items (default 50).
- `minItems` (integer): Stop scrolling once this many unique items are collected.
- `region` (string): Optional case-insensitive filter: only return groups in this region bucket (UK, US, EU, Brazil, LatAm, Turkey, Australia, Canada, Unknown).
- `scrolls` (integer): Auto-scroll up to N times, extracting + deduping after each (default 0 = current view only). Stops early at minItems or end of feed.
- `seedQueueId` (string): Memory id of the curated seed-queue (url | lang | currency) used to reconcile region/currency. Default: the built-in seed-queue memory id.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `timeoutMs` (integer): Total extraction deadline with browser V2 enabled (default 15000ms).

### `fb_groups` (~1090 tokens)

Structured Facebook group directory + per-group posting checklist (SQLite-backed; the single source of truth that replaces the free-text seed-queue). Actions: worklist {currency|region, offerSlug, limit?, freshDays?=14, includePending?=false, reset?} — returns the groups STILL to post to for this offer: joined, promo not forbidden, region/currency match, not pending/cooldown, not already posted for this offer within freshDays; never-posted first, then least-recently-posted, then largest. Re-call it to RESUME (it returns only what is left); a new offerSlug (or reset:true) starts FRESH. mark {url, offerSlug, currency, status, postUrl?, note?} — record ONE group right after posting (durable checklist; call after EACH group, never batch). status posted=visible-post, pending=pending-approval (success; engages a 48h cooldown so the worklist skips it), failed=posting-failed, skipped. import {fromMemoryIds?, fromExtract?} — (re)build the directory from the surviving memories and/or a live browser_extract_fb_groups payload (idempotent). set {url | groups:[…]} with region/lang/currency/country/name/member_count/allows_promo — curation: authoritatively classify one or many groups (currency must be a SUPPORTED deal currency: USD/GBP/EUR/BRL/TRY/CAD/AUD). exclude {url, reason} — mark a group promo-forbidden (permanently dropped from worklists). list/stats {region?} — coverage counts by region, pending/cooldown, last-posted per offer. recategorize {} — one-shot cleanup: re-derive region/lang/currency/country for every group from name + post history and backfill allows_promo from confirmed visible posts (idempotent). Region buckets: UK, US, EU, Brazil, LatAm, Turkey, Australia, Canada, Unknown.

Input parameters:

- `action` (string, required): worklist: ordered groups still to post to (region/currency + offerSlug). mark: tick one group after posting. set: curate classification (region/lang/currency) for one or many groups. import: (re)buil…
- `allows_promo` (string): set: promo permission.
- `cooldownHours` (number): mark: hours a pending-approval group is held out of the worklist (default 48).
- `country` (string): descriptive country label. set: classify a group. worklist: narrow to one country.
- `currency` (string): GBP | USD | EUR | BRL | TRY | AUD | CAD. Preferred worklist filter (authoritative seed-queue currency). USD covers both US and LatAm — add lang:"es" to target LatAm groups specifically.
- `freshDays` (number): worklist: skip groups already posted this offer within N days (default 14).
- `fromExtract`: import: a browser_extract_fb_groups JSON payload (object or JSON string) — the authority for currently-joined groups + region buckets.
- `fromMemoryIds` (array): import: specific memory ids to parse. Omit to use the default seed/ledger ids + facebook-groups-* subcategory scan.
- `groups` (array): set (bulk): array of group classifications to write in one call.
- `includePending` (boolean): worklist: include pending-approval / cooldown groups (default false).
- `lang` (string): language code (pt/en/de/fr/es/tr/pl/it/nl). set: classify a group. worklist: narrow a currency bucket to one language (e.g. EUR + de for German-copy groups).
- `limit` (number): worklist max groups (default 20).
- `member_count` (number): set: approximate member count.
- `name` (string): set: group display name.
- `note` (string): mark: short note (e.g. skip reason or failure detail).
- `offerSlug` (string): Offer/campaign slug, e.g. "spring-sale". Required for worklist and mark.
- `postUrl` (string): mark: the resulting post URL, if known.
- `reason` (string): exclude: why promo is forbidden (group rules).
- `region` (string): UK | US | EU | Brazil | LatAm | Turkey | Australia | Canada | Unknown (case-insensitive). Alternative to currency for worklist/list/stats. LatAm = Spanish-speaking Latin America (posts the USD link).
- `reset` (boolean): worklist: ignore prior posts for this offer (re-seed the whole region from scratch).
- `sessionId` (string): mark: loop/session id for provenance.
- `status` (string): mark status: posted/visible-post, pending/pending-approval (cooldown 48h, counts as success), failed/posting-failed, or skipped. Synonyms accepted.
- `url` (string): Group URL (normalized internally). Required for mark and exclude.

### `browser_extract_tiktok_videos` (~277 tokens)

Extract visible TikTok videos from the For You or Following feed as structured JSON (handle, videoUrl, caption, likes, comments, saves, shares, music). Navigate to tiktok.com/ or tiktok.com/following first. Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call. Much faster than browser_snapshot for data harvesting from TikTok feeds.

Input parameters:

- `fields` (array): Return only these fields; identity deduplication still uses the full items.
- `maxChars` (integer): Cap the JSON items in characters, keeping complete items. Defaults to no additional character cap.
- `maxItems` (integer): Cap on returned items (default 50).
- `minItems` (integer): Stop scrolling once this many unique items are collected.
- `scrolls` (integer): Auto-scroll up to N times, extracting + deduping after each (default 0 = current view only). Stops early at minItems or end of feed.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `timeoutMs` (integer): Total extraction deadline with browser V2 enabled (default 15000ms).

### `browser_extract_tiktok_search` (~262 tokens)

Extract visible TikTok search result videos as structured JSON (videoUrl, handle, profileUrl, caption, views). Navigate to tiktok.com/search?q=<query> first. Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call. Much faster than browser_snapshot for harvesting TikTok search results.

Input parameters:

- `fields` (array): Return only these fields; identity deduplication still uses the full items.
- `maxChars` (integer): Cap the JSON items in characters, keeping complete items. Defaults to no additional character cap.
- `maxItems` (integer): Cap on returned items (default 50).
- `minItems` (integer): Stop scrolling once this many unique items are collected.
- `scrolls` (integer): Auto-scroll up to N times, extracting + deduping after each (default 0 = current view only). Stops early at minItems or end of feed.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `timeoutMs` (integer): Total extraction deadline with browser V2 enabled (default 15000ms).

### `browser_extract_tiktok_studio` (~267 tokens)

Extract visible posts from TikTok Studio content list as structured JSON (title, url, date, privacy, stats[]). Navigate to tiktok.com/tiktokstudio/content first. Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call. Use this to audit, manage, or bulk-read your published TikTok content.

Input parameters:

- `fields` (array): Return only these fields; identity deduplication still uses the full items.
- `maxChars` (integer): Cap the JSON items in characters, keeping complete items. Defaults to no additional character cap.
- `maxItems` (integer): Cap on returned items (default 50).
- `minItems` (integer): Stop scrolling once this many unique items are collected.
- `scrolls` (integer): Auto-scroll up to N times, extracting + deduping after each (default 0 = current view only). Stops early at minItems or end of feed.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `timeoutMs` (integer): Total extraction deadline with browser V2 enabled (default 15000ms).

### `browser_extract_tiktok_profile` (~126 tokens)

Extract profile info and video grid from a TikTok profile page as structured JSON (name, handle, bio, followers, following, likes, videos[{videoUrl, views}]). Navigate to tiktok.com/@username first. Scroll down to load more videos in the grid. Use this to audit a creator profile or collect video URLs for further processing.

Input parameters:

- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_extract_wa_chats` (~271 tokens)

Extract visible WhatsApp chats from the sidebar as structured JSON (name, lastMsg, time, unreadCount, muted, pinned). Must be on web.whatsapp.com with the chat list visible. Pass scrolls/minItems to auto-scroll the sidebar and dedupe in ONE call. Use browser_click on span[title="Chat Name"] to open a specific chat.

Input parameters:

- `fields` (array): Return only these fields; identity deduplication still uses the full items.
- `maxChars` (integer): Cap the JSON items in characters, keeping complete items. Defaults to no additional character cap.
- `maxItems` (integer): Cap on returned items (default 50).
- `minItems` (integer): Stop scrolling once this many unique items are collected.
- `scrolls` (integer): Auto-scroll up to N times, extracting + deduping after each (default 0 = current view only). Stops early at minItems or end of feed.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `timeoutMs` (integer): Total extraction deadline with browser V2 enabled (default 15000ms).

### `browser_extract_wa_messages` (~269 tokens)

Extract visible messages from the open WhatsApp chat as structured JSON (sender, time, date, direction, text, dataId). Open a chat first by clicking span[title="Chat Name"]. Pass scrolls/minItems to auto-scroll UP through history and dedupe in ONE call. direction is "in" for received and "out" for sent messages.

Input parameters:

- `fields` (array): Return only these fields; identity deduplication still uses the full items.
- `maxChars` (integer): Cap the JSON items in characters, keeping complete items. Defaults to no additional character cap.
- `maxItems` (integer): Cap on returned items (default 50).
- `minItems` (integer): Stop scrolling once this many unique items are collected.
- `scrolls` (integer): Auto-scroll up to N times, extracting + deduping after each (default 0 = current view only). Stops early at minItems or end of feed.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `timeoutMs` (integer): Total extraction deadline with browser V2 enabled (default 15000ms).

### `browser_extract_ig_feed` (~255 tokens)

Extract visible Instagram feed posts as structured JSON (username, profileUrl, postUrl, caption, likes, comments, time, datetime, isSponsored, hasFollow). Navigate to instagram.com/ first. Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call.

Input parameters:

- `fields` (array): Return only these fields; identity deduplication still uses the full items.
- `maxChars` (integer): Cap the JSON items in characters, keeping complete items. Defaults to no additional character cap.
- `maxItems` (integer): Cap on returned items (default 50).
- `minItems` (integer): Stop scrolling once this many unique items are collected.
- `scrolls` (integer): Auto-scroll up to N times, extracting + deduping after each (default 0 = current view only). Stops early at minItems or end of feed.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `timeoutMs` (integer): Total extraction deadline with browser V2 enabled (default 15000ms).

### `browser_extract_ig_profile` (~116 tokens)

Extract Instagram profile data as structured JSON (username, displayName, bio, posts, followers, followerExact, following, isVerified, website, gridPosts, highlights). Navigate to instagram.com/username/ first. Returns bio, stats, post grid (up to 12), and story highlights.

Input parameters:

- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_extract_ig_post` (~123 tokens)

Extract a single Instagram post with comments as structured JSON (author, caption, likes, commentCount, time, datetime, comments[{username, text, time, datetime}]). Navigate to instagram.com/p/POST_ID/ or instagram.com/reel/REEL_ID/ first. Scroll the comment area to load more comments before extracting.

Input parameters:

- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_extract_ig_reels` (~257 tokens)

Extract visible Instagram Reels with engagement data as structured JSON (username, profileUrl, caption, likes, comments, audioName, audioUrl, hasFollow). Navigate to instagram.com/reels/ first. Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call.

Input parameters:

- `fields` (array): Return only these fields; identity deduplication still uses the full items.
- `maxChars` (integer): Cap the JSON items in characters, keeping complete items. Defaults to no additional character cap.
- `maxItems` (integer): Cap on returned items (default 50).
- `minItems` (integer): Stop scrolling once this many unique items are collected.
- `scrolls` (integer): Auto-scroll up to N times, extracting + deduping after each (default 0 = current view only). Stops early at minItems or end of feed.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `timeoutMs` (integer): Total extraction deadline with browser V2 enabled (default 15000ms).

### `browser_extract_ig_search` (~260 tokens)

Extract posts from the Instagram Explore page as structured JSON (url, alt, isReel). Navigate to instagram.com/explore/ first. Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call. For hashtag search, navigate to instagram.com/explore/tags/HASHTAG/.

Input parameters:

- `fields` (array): Return only these fields; identity deduplication still uses the full items.
- `maxChars` (integer): Cap the JSON items in characters, keeping complete items. Defaults to no additional character cap.
- `maxItems` (integer): Cap on returned items (default 50).
- `minItems` (integer): Stop scrolling once this many unique items are collected.
- `scrolls` (integer): Auto-scroll up to N times, extracting + deduping after each (default 0 = current view only). Stops early at minItems or end of feed.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `timeoutMs` (integer): Total extraction deadline with browser V2 enabled (default 15000ms).

### `browser_extract_li_feed` (~282 tokens)

Extract visible LinkedIn feed posts as structured JSON (author, authorUrl, headline, time, text, reactions, commentsCount, mediaType, articleTitle, articleLink, isPromoted, isRepost, postUrl). Navigate to linkedin.com/feed/ first. Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call. Much faster than browser_snapshot for data harvesting from the LinkedIn feed.

Input parameters:

- `fields` (array): Return only these fields; identity deduplication still uses the full items.
- `maxChars` (integer): Cap the JSON items in characters, keeping complete items. Defaults to no additional character cap.
- `maxItems` (integer): Cap on returned items (default 50).
- `minItems` (integer): Stop scrolling once this many unique items are collected.
- `scrolls` (integer): Auto-scroll up to N times, extracting + deduping after each (default 0 = current view only). Stops early at minItems or end of feed.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `timeoutMs` (integer): Total extraction deadline with browser V2 enabled (default 15000ms).

### `browser_extract_li_profile` (~128 tokens)

Extract LinkedIn profile data as structured JSON (name, headline, location, profilePic, connections, about, sections[{heading, items[{title, subtitle, meta}]}], recentActivity). Navigate to linkedin.com/in/USERNAME/ first. Sections include Experience, Education, Skills, etc. Use linkedin.com/in/me/ for the logged-in user's own profile.

Input parameters:

- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_extract_li_post` (~138 tokens)

Extract a single LinkedIn post with comments as structured JSON (author, authorUrl, headline, time, text, reactions, commentsCount, postUrn, comments[{author, authorUrl, text, time, likes}]). Navigate to linkedin.com/feed/update/urn:li:activity:ID/ first. Click "Comentar" button to expand comment section, then scroll to load more comments before extracting.

Input parameters:

- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_extract_li_notifications` (~253 tokens)

Extract LinkedIn notifications as structured JSON (text, time, isUnread, url, image). Navigate to linkedin.com/notifications/ first. Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call. Useful for monitoring engagement, connection requests, and mentions.

Input parameters:

- `fields` (array): Return only these fields; identity deduplication still uses the full items.
- `maxChars` (integer): Cap the JSON items in characters, keeping complete items. Defaults to no additional character cap.
- `maxItems` (integer): Cap on returned items (default 50).
- `minItems` (integer): Stop scrolling once this many unique items are collected.
- `scrolls` (integer): Auto-scroll up to N times, extracting + deduping after each (default 0 = current view only). Stops early at minItems or end of feed.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `timeoutMs` (integer): Total extraction deadline with browser V2 enabled (default 15000ms).

### `browser_extract_li_messages` (~144 tokens)

Extract LinkedIn messaging data as structured JSON with two arrays: conversations[{name, lastMessage, time, isUnread, url}] (sidebar list) and activeThread[{sender, text, time, direction}] (open conversation messages). Navigate to linkedin.com/messaging/ first. Click a conversation to load its messages. To send a message: browser_fill on .msg-form__contenteditable then browser_click on .msg-form__send-button.

Input parameters:

- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_extract_li_search_people` (~264 tokens)

Extract LinkedIn people search results as structured JSON (name, profileUrl, headline, location, mutual, actionButton, image). Navigate to linkedin.com/search/results/people/?keywords=QUERY first. Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call. Also works on linkedin.com/search/results/all/.

Input parameters:

- `fields` (array): Return only these fields; identity deduplication still uses the full items.
- `maxChars` (integer): Cap the JSON items in characters, keeping complete items. Defaults to no additional character cap.
- `maxItems` (integer): Cap on returned items (default 50).
- `minItems` (integer): Stop scrolling once this many unique items are collected.
- `scrolls` (integer): Auto-scroll up to N times, extracting + deduping after each (default 0 = current view only). Stops early at minItems or end of feed.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `timeoutMs` (integer): Total extraction deadline with browser V2 enabled (default 15000ms).

### `browser_extract_li_network` (~159 tokens)

Extract LinkedIn My Network data as structured JSON with two arrays: invitations[{name, subtitle, profileUrl, acceptLabel, ignoreLabel}] (pending connection requests) and suggestions[{name, subtitle, followers, profileUrl, action, image}] (people/creators to follow or connect). Navigate to linkedin.com/mynetwork/ first. Scroll down to load more suggestions. To accept an invitation: browser_click on button with the acceptLabel. To connect: browser_click on the respective Conectar/Connect button.

Input parameters:

- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.

### `browser_extract_li_jobs` (~274 tokens)

Extract LinkedIn job listings as structured JSON (jobId, title, company, companyUrl, location, salary, jobUrl, logo, promoted, easyApply, postedDate). Works on linkedin.com/jobs/ (recommendations) and linkedin.com/jobs/search/?keywords=QUERY&location=LOCATION. Pass scrolls/minItems to auto-scroll, extract, and dedupe in ONE call.

Input parameters:

- `fields` (array): Return only these fields; identity deduplication still uses the full items.
- `maxChars` (integer): Cap the JSON items in characters, keeping complete items. Defaults to no additional character cap.
- `maxItems` (integer): Cap on returned items (default 50).
- `minItems` (integer): Stop scrolling once this many unique items are collected.
- `scrolls` (integer): Auto-scroll up to N times, extracting + deduping after each (default 0 = current view only). Stops early at minItems or end of feed.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session. Auto-resolved from environment if omitted.
- `timeoutMs` (integer): Total extraction deadline with browser V2 enabled (default 15000ms).

### `bluesky_session` (~180 tokens)

BlueSky: who am I? Returns the logged-in account (did, handle, pdsUrl). Use first to confirm you are signed in. A blank assigned tab is safely initialized at bsky.app; nonblank tabs are never navigated implicitly. An expired session token is renewed inside the tool (waiting for bsky.app, then reloading its tab at most once), so "not logged in" means the page really has no session. Pass validate:true to check the token against the server.

Input parameters:

- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session (the bsky.app tab). Auto-resolved if omitted.
- `validate` (boolean): Also call com.atproto.server.getSession to verify the token server-side.

### `bluesky_timeline` (~170 tokens)

BlueSky: read your home timeline (following feed) as compact JSON posts (uri, cid, author, text, counts, viewer). Pass maxItems to auto-paginate. Returns the next cursor.

Input parameters:

- `cursor` (string): Pagination cursor from a prior call. Omit for the first page.
- `limit` (integer): Items per page (default 50, max 100).
- `maxItems` (integer): Auto-paginate (follow cursors) until this many items are gathered in ONE call. Default = one page.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session (the bsky.app tab). Auto-resolved if omitted.

### `bluesky_author_feed` (~200 tokens)

BlueSky: read a user's posts (author feed) as compact JSON. Pass actor (handle or DID), optional filter, and maxItems to auto-paginate.

Input parameters:

- `actor` (string, required): Handle (e.g. alice.bsky.social) or DID of the author.
- `cursor` (string): Pagination cursor from a prior call. Omit for the first page.
- `filter` (string): Server-side filter. Default posts_with_replies.
- `limit` (integer): Items per page (default 50, max 100).
- `maxItems` (integer): Auto-paginate (follow cursors) until this many items are gathered in ONE call. Default = one page.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session (the bsky.app tab). Auto-resolved if omitted.

### `bluesky_thread` (~173 tokens)

BlueSky: read a post and its thread (parents + replies) as compact JSON. Accepts an AT-URI or a bsky.app post URL. Each post includes uri+cid (needed to reply/like/repost).

Input parameters:

- `depth` (integer): Reply levels to fetch (default 6).
- `parentHeight` (integer): Parent levels to fetch (default 5).
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session (the bsky.app tab). Auto-resolved if omitted.
- `uri` (string, required): Post AT-URI (at://...) OR a bsky.app post URL (https://bsky.app/profile/<handle>/post/<rkey>).

### `bluesky_profile` (~109 tokens)

BlueSky: get an actor profile (did, handle, name, bio, follower/following/post counts, and your viewer relationship: following/followedBy/muted/blocking).

Input parameters:

- `actor` (string, required): Handle or DID to look up.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session (the bsky.app tab). Auto-resolved if omitted.

### `bluesky_search_posts` (~251 tokens)

BlueSky: full-text search posts. Supports sort (top/latest), since/until, author, lang. Pass maxItems to auto-paginate. Returns compact posts + next cursor.

Input parameters:

- `author` (string): Limit to posts by this handle/DID.
- `cursor` (string): Pagination cursor from a prior call. Omit for the first page.
- `lang` (string): BCP-47 language filter, e.g. en.
- `limit` (integer): Items per page (default 50, max 100).
- `maxItems` (integer): Auto-paginate (follow cursors) until this many items are gathered in ONE call. Default = one page.
- `q` (string, required): Search query.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `since` (string): Lower bound, ISO datetime or YYYY-MM-DD.
- `sort` (string): Ranking. Default top.
- `tabId` (string): Target a specific tab within the session (the bsky.app tab). Auto-resolved if omitted.
- `until` (string): Upper bound, ISO datetime or YYYY-MM-DD.

### `bluesky_search_actors` (~180 tokens)

BlueSky: search for users (actors). Returns compact actor cards (did, handle, name, bio, viewer relationship) + next cursor. Pass maxItems to auto-paginate.

Input parameters:

- `cursor` (string): Pagination cursor from a prior call. Omit for the first page.
- `limit` (integer): Items per page (default 50, max 100).
- `maxItems` (integer): Auto-paginate (follow cursors) until this many items are gathered in ONE call. Default = one page.
- `q` (string, required): Search query (name / handle).
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session (the bsky.app tab). Auto-resolved if omitted.

### `bluesky_notifications` (~196 tokens)

BlueSky: list your notifications (likes, reposts, replies, mentions, follows) as compact JSON. Pass markSeen:true to clear the unread badge, maxItems to auto-paginate.

Input parameters:

- `cursor` (string): Pagination cursor from a prior call. Omit for the first page.
- `limit` (integer): Items per page (default 50, max 100).
- `markSeen` (boolean): Mark notifications seen (updates the seen timestamp) after fetching.
- `maxItems` (integer): Auto-paginate (follow cursors) until this many items are gathered in ONE call. Default = one page.
- `priority` (boolean): Only priority notifications.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session (the bsky.app tab). Auto-resolved if omitted.

### `bluesky_graph` (~186 tokens)

BlueSky: list an actor's followers or follows as compact actor cards + next cursor. Pass maxItems to auto-paginate.

Input parameters:

- `actor` (string, required): Handle or DID whose graph to read.
- `cursor` (string): Pagination cursor from a prior call. Omit for the first page.
- `limit` (integer): Items per page (default 50, max 100).
- `maxItems` (integer): Auto-paginate (follow cursors) until this many items are gathered in ONE call. Default = one page.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session (the bsky.app tab). Auto-resolved if omitted.
- `which` (string, required): followers = who follows them; follows = who they follow.

### `bluesky_likes` (~227 tokens)

BlueSky: list likes. mode=post → the actors who liked a given post; mode=actor → the posts an actor has liked. Pass maxItems to auto-paginate.

Input parameters:

- `actor` (string): Handle or DID (mode=actor).
- `cursor` (string): Pagination cursor from a prior call. Omit for the first page.
- `limit` (integer): Items per page (default 50, max 100).
- `maxItems` (integer): Auto-paginate (follow cursors) until this many items are gathered in ONE call. Default = one page.
- `mode` (string, required): post = who liked a post (needs uri); actor = posts an actor has liked (needs actor).
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session (the bsky.app tab). Auto-resolved if omitted.
- `uri` (string): Post AT-URI or bsky.app URL (mode=post).

### `bluesky_feed` (~215 tokens)

BlueSky: read a custom feed generator (mode=feed) or a list timeline (mode=list) by its AT-URI. Returns compact posts + next cursor. Pass maxItems to auto-paginate.

Input parameters:

- `cursor` (string): Pagination cursor from a prior call. Omit for the first page.
- `limit` (integer): Items per page (default 50, max 100).
- `maxItems` (integer): Auto-paginate (follow cursors) until this many items are gathered in ONE call. Default = one page.
- `mode` (string, required): feed = a custom feed generator; list = a user list timeline.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session (the bsky.app tab). Auto-resolved if omitted.
- `uri` (string, required): AT-URI of the feed generator (mode=feed) or the list (mode=list).

### `bluesky_post` (~270 tokens)

BlueSky: publish a post. Supports plain text with auto-facets (@mentions, links, #hashtags), replies (replyTo), quote-posts (quote), and up to 4 images (by url or local path, each with alt text). A link card (OG preview with thumbnail) is auto-generated for the first URL when the post has no images and no quote. Returns the new post uri+cid.

Input parameters:

- `images` (array): Up to 4 images; give url OR path for each. Images take precedence over a quote embed.
- `langs` (array): BCP-47 language tags. Default ["en"].
- `quote` (string): Quote-post this post (AT-URI or bsky.app URL).
- `replyTo` (string): Reply to this post (AT-URI or bsky.app URL). Root/parent refs are derived automatically.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session (the bsky.app tab). Auto-resolved if omitted.
- `text` (string, required): Post text (max 300 graphemes). @mentions, URLs and #hashtags are auto-detected into rich-text facets.

### `bluesky_action` (~169 tokens)

BlueSky: act on a post or actor. Post: like/unlike, repost/unrepost, delete (your own). Actor: follow/unfollow, mute/unmute, block/unblock. Undo actions resolve the record key automatically — never pass rkeys.

Input parameters:

- `action` (string, required): The action to perform.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session (the bsky.app tab). Auto-resolved if omitted.
- `target` (string, required): Post actions (like/unlike/repost/unrepost/delete): post AT-URI or bsky.app URL. Actor actions (follow/unfollow/mute/unmute/block/unblock): handle or DID.

### `bluesky_resolve` (~94 tokens)

BlueSky: resolve a handle to its DID (com.atproto.identity.resolveHandle).

Input parameters:

- `handle` (string, required): Handle to resolve, e.g. alice.bsky.social.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session (the bsky.app tab). Auto-resolved if omitted.

### `bluesky_dm` (~258 tokens)

BlueSky DMs (chat.bsky.*): list_convos, read messages in a convo, send a message (by convoId or members), or mark_read. Returns compact JSON.

Input parameters:

- `action` (string, required): list_convos = your DM conversations; messages = messages in a convo; send = send a message; mark_read = mark a convo read.
- `convoId` (string): Conversation ID (messages/mark_read; send if not using members).
- `cursor` (string): Pagination cursor from a prior call. Omit for the first page.
- `limit` (integer): Items per page (default 50, max 100).
- `maxItems` (integer): Auto-paginate (follow cursors) until this many items are gathered in ONE call. Default = one page.
- `members` (array): For send: handles/DIDs to open/find a convo with, instead of convoId.
- `sessionId` (string): Browser session ID. If omitted, auto-selects the only open session.
- `tabId` (string): Target a specific tab within the session (the bsky.app tab). Auto-resolved if omitted.
- `text` (string): Message text (required for send).

### `gsc_navigate` (~287 tokens)

Open a Google Search Console page (overview, performance, inspect, pages, sitemaps, removals, links, security, settings, etc.). Always call before any gsc_* tool to land on the right report. Pages: overview, insights, performance_search, performance_discover, performance_news, inspect, pages, videos, sitemaps, removals, cwv_mobile, cwv_desktop, https, security, manual_actions, enhancements_breadcrumbs, enhancements_faq, enhancements_sitelinks, enhancements_videos, enhancements_products, enhancements_recipes, enhancements_review, enhancements_events, enhancements_jobposting, enhancements_speakable, enhancements_qa, enhancements_logos, enhancements_sitenames, enhancements_dataset, enhancements_practice, enhancements_math, enhancements_video_indexing, links, achievements, settings, crawl_stats, users, change_address, associations, disavow, shopping, merchant.

Input parameters:

- `page` (string, required): GSC section to open. Property is preserved from current resource_id unless `property` is set.
- `property` (string): Property to load (e.g. "sc-domain:example.com" or "https://example.com/"). Defaults to active property.
- `sessionId` (string): Browser session ID. Auto-resolved or auto-created.
- `tabId` (string): Target a specific tab. Auto-resolved if omitted.

### `gsc_property` (~177 tokens)

Manage GSC property selection — list registered properties, switch the active one (re-navigates current page), read the active property from the URL, or open the Add Property dialog. [mutating for action=add — adds a new property to the Google account]

Input parameters:

- `action` (string, required): list = enumerate properties from picker; select = switch active property; current = read URL property; add = open Add Property dialog.
- `property` (string): Property string (e.g. "sc-domain:example.com" or "https://example.com/") for select. For add: domain or URL prefix value.
- `sessionId` (string)
- `tabId` (string): Target a specific tab. Auto-resolved if omitted.
- `type` (string): For add action: property type. Default: domain.

### `gsc_inspect_url` (~163 tokens)

Run URL Inspection on a URL — opens the inspect tool, fills the URL, polls up to 30s for the result panel, returns structured JSON (pageIndexed, verdict, indexingState, coverage, canonicalUser, canonicalGoogle, lastCrawl, crawlStatus, crawlAllowed, fetchStatus, robotsAllowed, sitemap, referringPage, httpStatus, enhancements, summary, fullText).

Input parameters:

- `property` (string): Override active property (e.g. "sc-domain:example.com").
- `sessionId` (string)
- `tabId` (string)
- `timeoutMs` (integer): Polling timeout in ms (default 30000).
- `url` (string, required): Absolute URL to inspect (must belong to the active GSC property).

### `gsc_inspect_test_live` (~123 tokens)

Click the "Test live URL" button on the URL Inspection page and poll up to 90s for results. Useful to verify a live page after a fix without waiting for re-indexing. Returns same shape as gsc_inspect_url with `liveTest:true`.

Input parameters:

- `sessionId` (string)
- `tabId` (string)
- `timeoutMs` (integer): Polling timeout (default 90000 — live test is slow).
- `url` (string): URL to inspect first (skip if already on the inspect result page).

### `gsc_inspect_request_indexing` (~128 tokens)

[mutating — affects Google's crawl queue] Submit a URL to Google's indexing queue. Clicks "Request indexing" on the inspection result page (running a live test first if needed). Polls for the success/error modal and returns `{ requested, queued, error }`. Quota: ~10/day per property.

Input parameters:

- `sessionId` (string)
- `tabId` (string)
- `timeoutMs` (integer): Polling timeout (default 60000).
- `url` (string): URL to inspect first. Skip if already on the inspect result page.

### `gsc_inspect_view_crawled` (~87 tokens)

Open the "View crawled page" panel from the URL Inspection result and switch to the requested view (html / screenshot / http_response / more_info). Use browser_screenshot or browser_snapshot afterwards to capture content.

Input parameters:

- `sessionId` (string)
- `tabId` (string)
- `view` (string, required): Which crawled-page view to open.

### `gsc_performance_query` (~228 tokens)

Run a Performance report query — sets searchType, dateRange (preset or custom), primary dimension, chip filters, and optional comparison; returns total clicks/impressions/CTR/position plus full table rows as JSON. Auto-scrolls the grid to load up to `limit` rows.

Input parameters:

- `compare` (boolean): Enable date-range comparison.
- `customEnd` (string): YYYY-MM-DD end (with dateRange="custom").
- `customStart` (string): YYYY-MM-DD start (with dateRange="custom").
- `dateRange` (string): Preset range or "custom" with customStart/customEnd.
- `dimension` (string): Primary dimension to group by. Default: query.
- `filters` (array): Chip filters to apply. Op default: contains.
- `limit` (integer): Max rows (default 200, GSC table caps at 1000 visible).
- `property` (string)
- `searchType` (string): Search type filter. Default: web.
- `sessionId` (string)
- `tabId` (string)

### `gsc_performance_export` (~78 tokens)

Trigger Performance report export menu in the active tab. Format: csv → ZIP download; excel → XLSX; google_sheets → opens a new Sheet. Browser handles the actual download to its default download dir.

Input parameters:

- `format` (string, required): Export format.
- `sessionId` (string)
- `tabId` (string)

### `gsc_performance_chart_screenshot` (~45 tokens)

Capture a screenshot scoped to the Performance chart panel only — useful for visual reports.

Input parameters:

- `sessionId` (string)
- `tabId` (string)

### `gsc_pages_report` (~109 tokens)

Read the Pages (Coverage/Indexação) report — totals indexed/notIndexed and per-reason buckets with counts and trends. Pass `reason` to drill into a bucket and list URL examples.

Input parameters:

- `property` (string)
- `reason` (string): Drill into a specific reason (e.g. "Not found (404)", "Excluded by ‘noindex’ tag"). Returns URL examples for that bucket.
- `sessionId` (string)
- `tabId` (string)

### `gsc_pages_validate_fix` (~98 tokens)

[mutating — starts a Google validation cycle] Open a Pages-report reason bucket and click "Validate fix" so Google re-checks the URLs. Returns confirmation status.

Input parameters:

- `property` (string)
- `reason` (string, required): Reason name for which to start a "Validate fix" run (e.g. "Server error (5xx)").
- `sessionId` (string)
- `tabId` (string)

### `gsc_videos_report` (~52 tokens)

Read the Video indexing report — same shape as gsc_pages_report but for video pages.

Input parameters:

- `property` (string)
- `sessionId` (string)
- `tabId` (string)

### `gsc_sitemap` (~105 tokens)

Manage sitemaps. action=list returns all submitted sitemaps; action=submit adds a sitemap (mutating); action=delete removes one (mutating); action=view_errors opens the per-sitemap detail and returns issues.

Input parameters:

- `action` (string, required)
- `property` (string)
- `sessionId` (string)
- `tabId` (string)
- `url` (string): Sitemap URL (relative or absolute) for submit/delete/view_errors.

### `gsc_removals` (~135 tokens)

Manage URL removals. list_* returns existing requests; action=new submits a new removal (mutating). removalType: temporary (6-month hide), outdated_content (refresh Google's cached version), safe_search (report adult content).

Input parameters:

- `action` (string, required)
- `property` (string)
- `removalType` (string): Required for action=new.
- `scope` (string): For action=new + temporary: remove only this URL or all URLs starting with this prefix.
- `sessionId` (string)
- `tabId` (string)
- `target` (string): URL or prefix for action=new.

### `gsc_removals_cancel` (~74 tokens)

[mutating] Cancel a pending temporary removal request. URL must match the listed entry exactly.

Input parameters:

- `property` (string)
- `sessionId` (string)
- `tabId` (string)
- `url` (string, required): URL of the removal request to cancel (must match exactly as listed).

### `gsc_cwv_report` (~71 tokens)

Read Core Web Vitals report for mobile or desktop. Returns counts of poor / needs-improvement / good URLs and per-issue URL group examples.

Input parameters:

- `device` (string, required)
- `property` (string)
- `sessionId` (string)
- `tabId` (string)

### `gsc_https_report` (~56 tokens)

Read the HTTPS report — counts of HTTPS vs non-HTTPS URLs and reasons for non-HTTPS URLs with examples.

Input parameters:

- `property` (string)
- `sessionId` (string)
- `tabId` (string)

### `gsc_security_issues` (~83 tokens)

Read Security Issues. action=list returns active + history. action=request_review clicks "Request review" (mutating, requires fixed issues).

Input parameters:

- `action` (string): list (default) returns active issues; request_review submits a reconsideration request.
- `property` (string)
- `sessionId` (string)
- `tabId` (string)

### `gsc_manual_actions` (~92 tokens)

Read Manual Actions. action=list returns penalties (or "No issues detected"). action=reconsideration submits a reconsideration request with `body` (mutating).

Input parameters:

- `action` (string)
- `body` (string): Reconsideration request body text. Required for action=reconsideration.
- `property` (string)
- `sessionId` (string)
- `tabId` (string)

### `gsc_enhancements` (~104 tokens)

Read a structured-data Enhancements report. Returns valid / warnings / errors counts and per-issue URL examples. Reports: breadcrumbs, faq, sitelinks, videos, products, recipes, review, events, jobposting, speakable, qa, logos, sitenames, dataset, practice, math, merchant.

Input parameters:

- `property` (string)
- `report` (string, required)
- `sessionId` (string)
- `tabId` (string)

### `gsc_links_report` (~86 tokens)

Read a Links report section. top_linked_external / top_linking_sites / top_linking_text / top_linked_internal. Returns full table.

Input parameters:

- `limit` (integer): Max rows to scroll-load (default 100).
- `property` (string)
- `section` (string, required)
- `sessionId` (string)
- `tabId` (string)

### `gsc_links_export` (~59 tokens)

Trigger Links report Export menu. Browser handles file download.

Input parameters:

- `property` (string)
- `scope` (string, required): Export scope from the Links report Export menu.
- `sessionId` (string)
- `tabId` (string)

### `gsc_settings` (~97 tokens)

Read or modify property settings — ownership/verification, users, address. action=get returns the settings page summary; action=set_address/change_address mutate.

Input parameters:

- `action` (string): Default get. set_address sets the Change-of-address target. change_address opens flow.
- `newProperty` (string): Target property for change_address.
- `property` (string)
- `sessionId` (string)
- `tabId` (string)

### `gsc_crawl_stats` (~65 tokens)

Read Crawl Stats — totals (requests, download size, response time) and breakdowns by host status, response code, file type, Googlebot type.

Input parameters:

- `property` (string)
- `sessionId` (string)
- `tabId` (string)

### `gsc_users` (~86 tokens)

Manage property users. list returns email + role. add invites a user (mutating). remove revokes (mutating). change_role updates permissions (mutating).

Input parameters:

- `action` (string, required)
- `email` (string)
- `property` (string)
- `role` (string)
- `sessionId` (string)
- `tabId` (string)

### `gsc_associations` (~99 tokens)

Manage Associations (Analytics / Merchant / Ads / Play / YouTube / Actions / Chrome Web Store). list returns existing associations; add/remove mutate.

Input parameters:

- `action` (string, required)
- `identifier` (string): Service-specific ID (e.g. GA4 measurement ID, Merchant Center account ID).
- `property` (string)
- `service` (string)
- `sessionId` (string)
- `tabId` (string)

### `gsc_disavow` (~97 tokens)

[mutating for upload/delete — affects how Google trusts links to your site] Manage the Disavow Links file. download exports current; upload replaces (use sparingly).

Input parameters:

- `action` (string, required)
- `filePath` (string): Absolute path of disavow .txt file (action=upload).
- `property` (string)
- `sessionId` (string)
- `tabId` (string)

### `gsc_shopping` (~48 tokens)

Read Shopping/Merchant Listings report — counts and per-issue example URLs.

Input parameters:

- `property` (string)
- `sessionId` (string)
- `tabId` (string)

### `gsc_extract_table` (~66 tokens)

Generic GSC grid → JSON extractor. Useful when no specific gsc_*_report tool covers a panel.

Input parameters:

- `selector` (string): CSS scope selector (default: [role="grid"]).
- `sessionId` (string)
- `tabId` (string)

### `gsc_screenshot` (~47 tokens)

Capture a full-page screenshot of the active GSC tab. Saved via SynaBun image staging.

Input parameters:

- `sessionId` (string)
- `tabId` (string)

### `youtube_source` (~368 tokens)

Discover FRESH candidate game trailers (already-posted ones are removed automatically via the youtube-videos memory ledger — no manual dedup/recall needed). Searches YouTube for recently published trailers, queries IGDB for games (+ Steam appid and official YouTube trailer ids), and resolves Steam direct mp4 URLs. Returns trimmed candidates: { game, source, igdbId, appid, releaseDate, trailerPublishedAt, trailerTitle, genres, ytTrailerIds, steamMp4Url, summary }. Feed one to youtube_download (prefer steamMp4Url; fall back to a ytTrailerIds value), then pass its game/igdbId/appid/sourceTrailerId back into youtube_upload so it records the ledger.

Input parameters:

- `appids` (array): Steam appids to resolve (required for source=steam).
- `excludePosted` (boolean): Drop trailers already on the youtube-videos memory ledger (exact igdb/appid/ytid/name match). Default true — leave it on so the autopilot never re-posts. Set false only to inspect the raw pool.
- `limit` (number): Max candidates (1-50, default 10).
- `lookbackDays` (number): For source=youtube: published-after window. For IGDB/auto: release-date lookback window (default from config / 60).
- `query` (string): Game title or trailer search query. For source=youtube, omit to search official game trailers by publish date.
- `source` (string): Discovery backend. 'youtube' = YouTube Data API date-ordered recent trailer search; 'auto' (default) = IGDB games enriched with Steam mp4 URLs; 'igdb' = metadata + trailer pointers only; 'steam' = re…

### `youtube_download` (~269 tokens)

Download a trailer file. Prefers steamMp4Url (direct publisher asset, lowest copyright risk); otherwise yt-dlp on ytId/url. Returns { filePath, bytes, source }. Pass filePath to youtube_upload. [requires yt-dlp + ffmpeg on the host for the YouTube fallback path].

Input parameters:

- `appid` (number): Steam appid — used only to name the output file.
- `filename` (string): Base output filename (without extension). Defaults derived from ytId/appid.
- `quality` (string): yt-dlp -f format string. Default: best video+audio ≤1080p, merged to mp4.
- `steamMp4Url` (string): Direct Steam mp4 URL (from youtube_source steamMovies[].mp4). Preferred — no yt-dlp/ffmpeg required.
- `url` (string): Explicit video URL to download via yt-dlp.
- `useCookies` (boolean): Cookie fallback for the yt-dlp path. The server downloads cookieless first and only retries with browser cookies if YouTube demands auth (age/region/members-gated). Defaults on; pass false to hard-di…
- `ytId` (string): YouTube video id to download via yt-dlp (fallback for YouTube-only trailers).

### `youtube_navigate` (~106 tokens)

Open a YouTube Studio section (dashboard, content, analytics, playlists, comments, subtitles, copyright, earn, customization). Auto-creates a browser session on studio.youtube.com using the signed-in Google account. Call before other youtube_* browser tools.

Input parameters:

- `section` (string, required): Studio section to open.
- `sessionId` (string): Browser session ID. Auto-resolved or auto-created.
- `tabId` (string): Target a specific tab. Auto-resolved if omitted.

### `youtube_upload` (~379 tokens)

Upload a local video file to YouTube Studio, publish it, and record it to the youtube-videos dedup ledger. Opens Create → Upload, sets the file, fills title/description/tags, advances the wizard, sets visibility, clicks Done, then verifies the wizard closed and resolves the new video id. [mutating — publishes to the channel]. Pass game/igdbId/appid/sourceTrailerId so the upload is remembered and never re-posted. Default visibility=private so you can schedule afterwards with youtube_schedule.

Input parameters:

- `appid` (number): Steam appid (from youtube_source). Dedup ledger key — pass it whenever known.
- `description` (string): Video description (credits, store link, etc.).
- `filePath` (string, required): Absolute path to the local video file (from youtube_download).
- `game` (string): Game name (from the youtube_source candidate). Recorded to the youtube-videos dedup ledger.
- `igdbId` (number): IGDB id (from youtube_source). Dedup ledger key — pass it whenever known.
- `madeForKids` (boolean): COPPA audience flag. Default false (Not made for kids).
- `sessionId` (string)
- `source` (string): Where the downloaded file came from (recorded for the ledger).
- `sourceTrailerId` (string): The SOURCE trailer YouTube id you downloaded (a youtube_source ytTrailerIds value). Dedup ledger key.
- `tabId` (string): Target a specific tab. Auto-resolved if omitted.
- `tags` (array): Tags/keywords (added under "Show more").
- `title` (string, required): Video title (≤100 chars). Studio truncates beyond 100.
- `visibility` (string): Publish visibility. Default: private (schedule/publish later with youtube_schedule).

### `youtube_metadata` (~171 tokens)

Edit an existing video's metadata on its Studio edit page: title, description, tags, category, made-for-kids. Saves on completion. [mutating]. Use youtube_schedule for visibility/publish-time.

Input parameters:

- `category` (string): Category name, e.g. "Gaming". Set via the Show-more category dropdown.
- `description` (string): New description (replaces existing).
- `madeForKids` (boolean): COPPA audience flag.
- `sessionId` (string)
- `tabId` (string): Target a specific tab. Auto-resolved if omitted.
- `tags` (array): Tags/keywords (replaces existing; revealed under "Show more").
- `title` (string): New title (≤100 chars).
- `videoId` (string, required): YouTube video id to edit.

### `youtube_thumbnail` (~104 tokens)

Upload a custom thumbnail to a video via its Studio edit page (uses the hidden thumbnail file input). Saves on completion. [mutating].

Input parameters:

- `filePath` (string, required): Absolute path to the thumbnail image (JPG/PNG, ≤2MB, 1280×720 recommended).
- `sessionId` (string)
- `tabId` (string): Target a specific tab. Auto-resolved if omitted.
- `videoId` (string, required): YouTube video id.

### `youtube_schedule` (~169 tokens)

Schedule a video to go public at a future time (or set immediate visibility) via the Studio visibility dialog. Pass publishAt for scheduling. [mutating]. Locale-aware date entry (US + pt-BR); the response echoes the picker read-back as scheduledDisplay — verify it matches your intended slot.

Input parameters:

- `publishAt` (string): Scheduled publish time, ISO ("2026-06-20T18:00") or "YYYY-MM-DD HH:MM". Required unless setting an immediate visibility.
- `sessionId` (string)
- `tabId` (string): Target a specific tab. Auto-resolved if omitted.
- `videoId` (string, required): YouTube video id.
- `visibility` (string): Set immediate visibility, or "schedule" (default when publishAt is given).

### `youtube_playlist` (~145 tokens)

Manage playlists. action=list enumerates them; action=create makes a new playlist; action=add adds a video to an existing playlist (by name). [mutating for create/add].

Input parameters:

- `action` (string, required): list = enumerate playlists; create = make a new playlist; add = add a video to a playlist.
- `name` (string): Playlist name (required for create/add).
- `sessionId` (string)
- `tabId` (string): Target a specific tab. Auto-resolved if omitted.
- `videoId` (string): Video id to add (required for action=add).
- `visibility` (string): New playlist visibility (create). Default public.

### `youtube_endscreen` (~142 tokens)

Apply an end-screen template to a video (links to a related video/playlist + a subscribe element) via the Studio end-screen editor, then save. [mutating]. End-screen editing is canvas-based and may need a manual touch-up.

Input parameters:

- `sessionId` (string)
- `tabId` (string): Target a specific tab. Auto-resolved if omitted.
- `template` (string): Which end-screen layout to apply. 'default' = first built-in template; 'last_video_subscribe' = best-for-retention; 'import' = copy from your most recent video.
- `videoId` (string, required): YouTube video id.

### `youtube_analytics` (~156 tokens)

Read-only YouTube Analytics (views, watch-time, likes, subscribers, etc.) via the API — needs the YouTube API configured/authorized in Settings → YouTube. Channel-wide or per-video.

Input parameters:

- `channelId` (string): Channel id (UC…). Defaults to the configured/owning channel.
- `endDate` (string): YYYY-MM-DD. Default: today.
- `metrics` (array): Metrics, e.g. ["views","estimatedMinutesWatched","likes","subscribersGained"]. Sensible defaults if omitted.
- `startDate` (string): YYYY-MM-DD. Default: 28 days ago.
- `videoId` (string): Limit the report to one video. Omit for channel-wide.

### `youtube_channel` (~105 tokens)

Read channel info or list recent uploads from Studio (browser). Use action=list to dedupe the autopilot against videos already on the channel.

Input parameters:

- `action` (string, required): info = channel id/name; list = recent uploads (id, title, visibility) for dedup.
- `limit` (number): Max videos for action=list (default 30).
- `sessionId` (string)
- `tabId` (string): Target a specific tab. Auto-resolved if omitted.

### `discord_guild` (~116 tokens)

Discord server overview and listing. Actions: info, channels, members, roles, audit_log.

Input parameters:

- `action` (string, required): Action: info (server details), channels (list all), members (list), roles (list all), audit_log (recent actions).
- `action_type` (number): Audit log action type filter (audit_log only).
- `guild_id` (string): Guild ID. Defaults to DISCORD_GUILD_ID env var.
- `limit` (number): Max results for members/audit_log (default 50).

### `discord_channel` (~347 tokens)

Discord channel management. Actions: create, edit, delete, list, permissions. Handles text, voice, categories, forums, stages.

Input parameters:

- `action` (string, required): Action: create, edit, delete, list, or permissions.
- `allow` (string): Permission flags to allow, comma-separated (permissions). E.g. "SEND_MESSAGES,VIEW_CHANNEL".
- `bitrate` (number): Voice bitrate in bps (voice channels, create/edit).
- `channel` (string): Channel name or ID (required for edit/delete/permissions).
- `deny` (string): Permission flags to deny, comma-separated (permissions). E.g. "SEND_MESSAGES".
- `guild_id` (string): Guild ID. Defaults to DISCORD_GUILD_ID env var.
- `name` (string): Channel name (create required, edit optional).
- `nsfw` (boolean): NSFW flag (create/edit).
- `parent` (string): Parent category name or ID (create/edit). Empty string to remove.
- `position` (number): Sort position (create/edit).
- `reason` (string): Audit log reason.
- `slowmode` (number): Slowmode in seconds, 0-21600 (create/edit).
- `target` (string): Role or user name/ID (permissions action). Use "type:role" or "type:user" prefix, or bare name/ID.
- `topic` (string): Channel topic/description (create/edit).
- `type` (string): Channel type (create only, default: text). Use "category" for channel categories.
- `user_limit` (number): Voice user limit, 0=unlimited (voice channels, create/edit).

### `discord_role` (~229 tokens)

Discord role management. Actions: create, edit, delete, list, assign (role to member), remove (role from member).

Input parameters:

- `action` (string, required): Action: create, edit, delete, list, assign (to member), remove (from member).
- `color` (string): Hex color e.g. "#ff0000" (create/edit).
- `guild_id` (string): Guild ID. Defaults to DISCORD_GUILD_ID env var.
- `hoist` (boolean): Display separately in sidebar (create/edit).
- `member` (string): User name or ID (assign/remove actions).
- `mentionable` (boolean): Allow @mention by anyone (create/edit).
- `name` (string): Role name (create required, edit optional).
- `permissions` (string): Permission flags, comma-separated (create/edit). E.g. "SEND_MESSAGES,MANAGE_CHANNELS".
- `position` (number): Sort position (edit only).
- `reason` (string): Audit log reason.
- `role` (string): Role name or ID (required for edit/delete/assign/remove).

### `discord_message` (~298 tokens)

Discord message operations. Actions: send, edit, delete, pin, unpin, react, bulk_delete, list.

Input parameters:

- `action` (string, required): Action: send, edit, delete, pin, unpin, react, bulk_delete, list.
- `after` (string): Fetch messages after this message ID (list action).
- `before` (string): Fetch messages before this message ID (list action).
- `channel` (string, required): Channel name or ID (required for all actions).
- `content` (string): Message text (send required, edit optional).
- `embed` (object): Embed object: {title?, description?, color? (int), fields?: [{name, value, inline?}], footer?: {text}, image?: {url}, thumbnail?: {url}}. (send/edit)
- `emoji` (string): Emoji for react action. Unicode emoji or custom format "name:id".
- `guild_id` (string): Guild ID for channel name resolution. Defaults to DISCORD_GUILD_ID env var.
- `limit` (number): Max messages to fetch (list action, default 50, max 100).
- `message_id` (string): Message ID (required for edit/delete/pin/unpin/react).
- `message_ids` (array): Array of message IDs for bulk_delete (2-100 messages, max 14 days old).
- `reply_to` (string): Message ID to reply to (send only).

### `discord_member` (~168 tokens)

Discord member moderation. Actions: info, kick, ban, unban, timeout, nickname.

Input parameters:

- `action` (string, required): Action: info, kick, ban, unban, timeout, nickname.
- `delete_days` (number): Days of messages to delete, 0-7 (ban action, default 0).
- `duration` (number): Timeout duration in minutes (timeout action). 0 to remove timeout.
- `guild_id` (string): Guild ID. Defaults to DISCORD_GUILD_ID env var.
- `member` (string, required): User name, tag, or ID (required for all actions).
- `nickname` (string): New nickname (nickname action). Empty string to reset.
- `reason` (string): Moderation reason for audit log (kick/ban/timeout).

### `discord_onboarding` (~288 tokens)

Discord server onboarding and setup. Actions: get, set_welcome, set_rules, set_verification, set_onboarding.

Input parameters:

- `action` (string, required): Action: get (current config), set_welcome (welcome screen), set_rules (rules channel), set_verification (level), set_onboarding (prompts & defaults).
- `default_channels` (array): Default channel IDs for new members (set_onboarding).
- `description` (string): Welcome screen description text (set_welcome).
- `enabled` (boolean): Enable/disable onboarding (set_onboarding).
- `guild_id` (string): Guild ID. Defaults to DISCORD_GUILD_ID env var.
- `prompts` (array): Onboarding prompts array (set_onboarding). Each: {title, options: [{title, description?, emoji_name?, channel_ids?, role_ids?}], single_select?, required?, in_onboarding?}
- `rules_channel` (string): Channel name or ID for rules (set_rules).
- `system_channel` (string): Channel name or ID for system messages (set_rules).
- `verification_level` (string): Verification level (set_verification). none=unrestricted, low=email, medium=5min, high=10min, very_high=phone.
- `welcome_channels` (array): Welcome screen channels: [{channel_id, description, emoji_name?}] (set_welcome).

### `discord_webhook` (~203 tokens)

Discord webhook management. Actions: create, edit, delete, list, execute (send message as webhook).

Input parameters:

- `action` (string, required): Action: create, edit, delete, list, execute.
- `avatar_url` (string): Avatar URL (create/edit).
- `channel` (string): Channel name or ID (required for create/list).
- `content` (string): Message content (execute).
- `embeds` (array): Embeds array (execute). Each: {title?, description?, color?, fields?: [{name, value}]}.
- `guild_id` (string): Guild ID for channel name resolution. Defaults to DISCORD_GUILD_ID env var.
- `name` (string): Webhook name (create required, edit optional).
- `username` (string): Override display name (execute).
- `webhook_id` (string): Webhook ID (required for edit/delete/execute).
- `webhook_token` (string): Webhook token (required for execute).

### `discord_thread` (~189 tokens)

Discord thread management. Actions: create (from message or standalone), archive, unarchive, lock, delete.

Input parameters:

- `action` (string, required): Action: create, archive, unarchive, lock, delete.
- `auto_archive` (number): Auto-archive duration in minutes: 60, 1440, 4320, or 10080 (create only).
- `channel` (string): Parent channel name or ID (create only).
- `guild_id` (string): Guild ID for channel name resolution. Defaults to DISCORD_GUILD_ID env var.
- `message_id` (string): Create thread from this message (create only). Omit for standalone thread.
- `name` (string): Thread name (create required).
- `private` (boolean): Create private thread (create only, default false).
- `thread` (string): Thread ID (required for archive/unarchive/lock/delete).

### `whiteboard_read` (~200 tokens)

Read the whiteboard. Returns viewport truth (usable canvas size, origin offset, whether a browser is connected and in Focus mode), every element with its final box x,y,w,h (text/list sizes are browser-measured; ~ marks server estimates not yet measured), z-order, rotation, resolved arrow endpoints and anchors, then a layout analysis: content bounds, elements overflowing the usable area, overlapping pairs, section containment (with spill-outs), z-order and dangling-anchor notes. Call it before placing or moving elements and after edits to verify. format:'json' returns the same as structured JSON; verbose:true prints full text.

Input parameters:

- `format` (string): "text" (default): annotated element list + layout analysis. "json": {viewport, connection, elements, analysis} as JSON.
- `verbose` (boolean): Text mode only: print full text content (default truncates at 300 chars) and every list item (default 20).

### `whiteboard_add` (~338 tokens)

Add elements. Coordinates: px (default) are absolute canvas pixels and are NOT offset — start at the origin reported by whiteboard_read (values are clamped into the usable area). pct = 0-100 of the usable area (offsets applied; also converts arrow/pen points). parent:<sectionId> makes x/y relative to that section and clamps inside it. layout row/column/grid/center overrides x/y using real sizes. Sizes: text/list auto-size (do not pass width/height); shapes default 160x100 (rect, pill, circle, triangle, drawn-circle); sections default per sectionType; images need width/height. Arrows: 2+ points plus optional startAnchor/endAnchor (unknown IDs dropped with a warning; anchored ends snap to the target edge). Returns the FINAL geometry per element after defaults/pct/layout/clamping with the adjustments made, then overflow/overlap warnings for the new elements. Guidance: keep content within ~70-80% of the usable width, centered, fit vertically, ~20px margins.

Input parameters:

- `coordMode` (string): "px" (default): absolute canvas pixels — NOT offset; the usable area starts at the origin whiteboard_read reports and values are clamped into it. "pct": 0-100 of the usable area (or of the parent sec…
- `elements` (array, required): Elements to add (1-100).
- `layout` (string): Auto-layout using real element sizes; overrides x/y. Runs inside the parent section when parent is set.

### `whiteboard_update` (~292 tokens)

Update one element ({id, updates}) or many atomically ({items:[{id, updates}]}: one save, one render, one undo step in the browser). Only listed fields change; changing content/items/fontSize re-estimates a text/list size until the browser re-measures it. coordMode pct and parent:<sectionId> work as in whiteboard_add. Positions are clamped into the usable area; unknown anchor IDs are dropped with a warning. Per-item results include the final geometry; a missing ID fails only that item.

Input parameters:

- `coordMode` (string): "px" (default): absolute canvas pixels — NOT offset; the usable area starts at the origin whiteboard_read reports and values are clamped into it. "pct": 0-100 of the usable area (or of the parent sec…
- `id` (string): Single form: element ID (use together with updates).
- `items` (array): Batch form: many updates in one save / one render / one undo step. Per-item results; a missing ID fails only that item. (List bullet text goes in updates.items, not here.)
- `parent` (string): Single form: interpret x/y (px or pct) relative to this section and clamp inside it.
- `updates` (object): Single form: fields to change.

### `whiteboard_remove` (~94 tokens)

Remove one element ({id}) or several atomically ({ids}). Arrows anchored to a removed element are detached and their endpoint moved to its centre (reported as cascade updates). Omit both to clear the whole board (undoable in the browser with Ctrl+Z).

Input parameters:

- `id` (string): Element ID to remove.
- `ids` (array): Several element IDs removed atomically (one save, one undo step).

### `whiteboard_screenshot` (~136 tokens)

Capture the live whiteboard from the primary connected browser window as a JPEG, preceded by a text block with the coordinate mapping (canvas size, image scale: image px ÷ scale = canvas px, usable viewport origin, element count). Fails with a clear message when no browser is connected. Use whiteboard_read for exact numbers; use this to judge visual overlap, legibility and how the board actually looks.

Input parameters:

- `crop` (string): "full" (default): the whole canvas, so image px ÷ scale = canvas px. "usable": cropped to the usable viewport (origin offset reported in the text block).

### `card_list` (~60 tokens)

List all currently open memory cards in the Neural Interface. Returns each card's memory UUID, position, size, compact/pin state, content preview, and the current viewport dimensions (width x height). Use this before placing cards to know the available screen size.

### `card_open` (~216 tokens)

Open a memory as a floating card in the Neural Interface. Use card_list first to see viewport size.

Coordinate modes (coordMode): "px" (default) = absolute pixels. "pct" = percentage of viewport (0-100), e.g. left:50 top:50 = center of screen.

If the card is already open, it is brought to the front. Omit left/top for auto-cascade positioning.

Input parameters:

- `compact` (boolean): Open in compact mode (220x120px mini-card). Default: false.
- `coordMode` (string): Coordinate mode. "px" (default) = absolute pixels. "pct" = percentage of viewport (0-100). left:50 top:50 = center of screen.
- `left` (number): X position from left edge. Omit for auto-cascade.
- `memoryId` (string, required): UUID of the memory to open as a floating card
- `top` (number): Y position from top edge. Omit for auto-cascade.

### `card_close` (~61 tokens)

Close a memory card by its UUID, or close all open cards if no memoryId is provided. Use card_list first to see which cards are open.

Input parameters:

- `memoryId` (string): UUID of the card to close. Omit to close ALL open cards.

### `card_update` (~198 tokens)

Update an open memory card's position, size, compact/expand state, or pin state. Set coordMode to "pct" to use percentage-based positioning. Only specified fields are changed; others remain untouched. Changes appear in real-time.

Input parameters:

- `compact` (boolean): true = switch to compact mode (220x120px), false = expand to full size
- `coordMode` (string): Coordinate mode for position/size values. "pct" = percentage of viewport.
- `height` (number): New height (ignored in compact mode)
- `left` (number): New X position
- `memoryId` (string, required): UUID of the card to update (must be currently open)
- `pinned` (boolean): true = pin card (locked position, dimmed, z-index 180), false = unpin
- `top` (number): New Y position
- `width` (number): New width (ignored in compact mode)

### `card_screenshot` (~43 tokens)

Take a visual screenshot of the Neural Interface showing all open memory cards in their current positions. Returns a JPEG image. Requires the Neural Interface to be open in a browser.

### `git` (~227 tokens)

Git repository operations. Actions: "status" shows branch and changed files, "diff" returns raw diff content for analysis, "commit" stages and commits with a message, "log" shows recent commit history, "branches" lists all branches. Use "diff" to analyze changes before generating commit messages.

Input parameters:

- `action` (string, required): Git action. "status" = branch + changes list. "diff" = raw diff content for analysis. "commit" = stage and commit. "log" = recent commit history. "branches" = list all branches.
- `count` (number): Number of commits to return (default 10). Only used for "log" action.
- `files` (array): Specific files to stage for "commit". If omitted, stages all changes (git add -A).
- `max_lines` (number): Max lines of diff output (default 500). Only used for "diff" action.
- `message` (string): Commit message (required for "commit" action).
- `path` (string, required): Absolute path to the git repository working directory.

### `image_staged` (~177 tokens)

List, clear, or remove images from SynaBun's image store (data/images/). Images arrive when users paste them in the Neural Interface chat. Use "list" to see available images with their full absolute paths — these paths can be passed to browser_upload, Read, or any tool that accepts file paths. Use "clear" to delete all attachment-type images (auto-clear after use). Use "remove" to delete a specific file.

Input parameters:

- `action` (string, required): Action: "list" = show all images with paths. "clear" = delete all attachment images. "remove" = delete a specific image.
- `filename` (string): Filename to remove (for "remove" action).
- `type` (string): Filter by image type. Default: "all". "attachment" = images pasted in chat.

### `style_guide` (~651 tokens)

A project's SynaBun Style Guide: brand, colors (light/dark), type, spacing, motion, components and rules, as a summary, the full DESIGN.md or tokens (CSS variables, Tailwind theme, W3C design tokens). Call it BEFORE UI, design, copy, marketing, image or video work and use its tokens instead of inventing values. Pass projectPath (your working directory). To change the guide, use action "propose": the user reviews proposals; never edit DESIGN.md or the token files by hand.

Input parameters:

- `action` (string): "summary": the compact brand block (start here). "get": summary + the full DESIGN.md (or one `section`). "tokens": the tokens in a `format`. "contrast": WCAG ratio + APCA for `fg` on `bg`. "propose":…
- `bg` (string): contrast: the background color, same forms as fg.
- `changes` (object): propose: a JSON merge patch (RFC 7396) against the guide, e.g. {"colors":{"status":{"danger":"#dc2626"}}}. null deletes a key. agents and exports settings cannot be proposed.
- `fg` (string): contrast: the text color — a hex, rgb(), hsl(), oklch(), or an alias like "{semantic.text}" or "{primary.500}".
- `format` (string): tokens: "json" (resolved values, default), "dtcg" (W3C design tokens), "css" (custom properties), "tailwind-v4" (@theme) or "tailwind-v3" (theme.extend).
- `formats` (array): export: which files to write (default: the ones the guide has enabled).
- `model` (string): propose: the authoring model, if known.
- `projectPath` (string): The project root or any path inside it (your working directory). The default is the server's cwd, which is usually NOT your project — pass it.
- `provider` (string): propose: the authoring provider, if known.
- `reason` (string): propose: why the guide should change (required).
- `runId` (string): propose: the dispatched run id, if known.
- `section` (string): get: only this DESIGN.md section, e.g. "Colors", "Typography", "Components", "Do's and Don'ts".
- `size` (string): contrast: "large" for text ≥ 24px (or ≥ 18.66px bold) and UI components.
- `status` (string): proposals: only this status.
- `taskClass` (string): summary: the kind of work (e.g. "image_gen" or "video_gen" puts imagery and the generation prefix first).
- `theme` (string): tokens / contrast: one theme (default: the guide's default theme).

### `morelogin` (~239 tokens)

Manage MoreLogin (anti-detect, multi-account browser) profiles. Actions: "status" (is MoreLogin installed/running, which profile is the default AI browser), "list" (profiles), "create" (new profile), "start"/"stop" (launch/close a profile), "use_default" (set a profile as the default AI browser — afterwards all browser_* tools automatically drive that MoreLogin profile). Requires the MoreLogin desktop app to be running with its local API enabled.

Input parameters:

- `action` (string, required): MoreLogin action. "status" = installed/running + current default. "list" = browser profiles (environments). "create" = new profile. "start"/"stop" = launch/close a profile. "use_default" = make a pro…
- `envId` (string): MoreLogin environment (profile) id — required for start, stop, and use_default. Get ids from the "list" action.
- `name` (string): Name for a new profile ("create" action). Defaults to "SynaBun".

### `tictactoe` (~228 tokens)

Play Tic Tac Toe on the whiteboard. Actions: "start" sets up the board (piece defaults to X), "move" places the current turn's piece in cell 1-9, "state" shows the current board, "end" closes the game. The board renders visually on the whiteboard. X always goes first. Returns ASCII board + game status after each action.

Input parameters:

- `action` (string, required): Game action. "start" = set up board (optional piece: X or O). "move" = place piece (requires cell 1-9). "state" = get current board. "end" = tear down game.
- `cell` (number): Cell number 1-9 (required for "move" action). Layout:   1 | 2 | 3   ---------   4 | 5 | 6   ---------   7 | 8 | 9
- `piece` (string): Which piece you play as (for "start" action). Default: X. X always goes first.

## Diagnostics

Captured diagnostic sections: Provenance, Install scripts, Vulnerabilities, Dependencies. The full working is on the page: https://verifymcp.io/servers/danilokhury-synabun/synabun#diagnostics

## Score history

- 2026-11-04: 72
- 2026-11-03: 72
- 2026-11-02: 72
- 2026-11-01: 72
- 2026-10-31: 72
- 2026-10-30: 72
- 2026-10-29: 57

## Common questions

### What is the SynaBun MCP server?

SynaBun is an MCP server listed in the public MCP registry as io.github.danilokhury/synabun. Persistent memory MCP server for Claude Code, Codex and OpenCode, stored locally in SQLite. This page covers its npm package (synabun).

### Is the SynaBun MCP server safe to use?

SynaBun scores 72 out of 100 on VerifyMCP. We recorded 5 known advisories against it as of 4 November 2026. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the SynaBun MCP server expose?

SynaBun exposes 136 tools: remember, recall, forget, restore, reflect, and 131 more. Their descriptions and schemas cost roughly 27,468 tokens of context every time the server is loaded.

### Is the SynaBun MCP server still maintained?

SynaBun is still listed as active in the MCP registry. We last reached this channel on 4 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What licence is the SynaBun MCP server under?

SynaBun declares the Apache-2.0 licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.

## Links

- npm package: https://www.npmjs.com/package/synabun
- Socket report: https://socket.dev/npm/package/synabun
- Repository: https://github.com/danilokhury/Synabun
- Website: https://synabun.ai/
- Changelog RSS feed: https://verifymcp.io/servers/danilokhury-synabun/synabun.xml
- Changelog JSON feed: https://verifymcp.io/servers/danilokhury-synabun/synabun.json
- HTML version of this page: https://verifymcp.io/servers/danilokhury-synabun/synabun
