# ai.spideriq/publish (npm · @spideriq/mcp-publish)

SpiderIQ Publish: content platform MCP (pages, posts, templates, components, domains, media)

- Trust score: 48/100 (low)
- Change this week: +13
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- npm · `@spideriq/mcp-publish`: 48/100 (this document), [markdown](https://verifymcp.io/servers/ai-spideriq-publish/spideriq-mcp-publish.md), [page](https://verifymcp.io/servers/ai-spideriq-publish/spideriq-mcp-publish)

## Channel facts

- Registry: `npm`
- Package: `@spideriq/mcp-publish`
- Version: `1.25.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-08-03.

- **Supply Chain Security**: 70/100
  - No malware found by supply-chain analysis.
  - CVE check failed: a known high-severity CVE affects sharp 0.33.5, a direct dependency. A fixed version is available.
  - No install/post-install scripts declared.
  - Only part of the dependency tree could be resolved (131 of 135), so this covers what we could see, not the whole tree.
- **Provenance & Transparency**: 19/100
  - Repository check failed: the declared repository URL returned HTTP 404.
  - Provenance check failed: no build-provenance attestation is published.
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 7 days ago).
  - Security-disclosure policy not yet verified: we couldn't inspect the source repository.
- **Schema Quality & AI Usability**: 27/100
  - AI-judged instruction clarity (poor).
  - Context-footprint check failed: tool/resource definitions use about 36639 tokens (~234/item across 156 items; 156 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 27/100
  - Stability observed for 8 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 91/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 72% of tool parameters carry a description.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### Claude

```bash
claude mcp add ai-spideriq-publish -- npx -y @spideriq/mcp-publish
```

### Codex

```bash
codex mcp add ai-spideriq-publish -- npx -y @spideriq/mcp-publish
```

### opencode

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

### OpenClaw

```bash
openclaw mcp add ai-spideriq-publish --command npx --arg -y --arg @spideriq/mcp-publish
```

### Hermes

```yaml
mcp_servers:
  ai-spideriq-publish:
    command: "npx"
    args: ["-y", "@spideriq/mcp-publish"]
```

### Other

```json
{
  "mcpServers": {
    "ai-spideriq-publish": {
      "command": "npx",
      "args": [
        "-y",
        "@spideriq/mcp-publish"
      ]
    }
  }
}
```

## 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-08-02 (score 48, +36)

- [security regression] GHSA-f88m-g3jw-g9cj affects this package: high
- [security regression] Provenance: unverified → fail
- [security regression] Known CVEs: unverified → fail
- [security improvement] Install scripts: unverified → pass
- [security improvement] Malware scan: unverified → pass
- [functional improvement] License: unverified → pass
- [functional improvement] Dependency health: unverified → partial
- [functional improvement] Maintenance: unverified → pass
- [functional improvement] MCP protocol: unverified → pass
- [functional improvement] Stability: unverified → 0.23
- [functional improvement] Schema quality: unverified → poor
- [functional] Licence: MIT

### 2026-08-01 (score 12, −23)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-30 (score 35, +17)

- [functional improvement] Tool coverage: unverified → 100

### 2026-07-28 (score 18, −17)

- [functional regression] Tool coverage: 100 → unverified
- [functional] First check of Schema quality: unverified

### 2026-07-27 (score 35)

First indexed and scored.

## MCP tools (156)

### `request_access` (~120 tokens)

Request access to SpiderIQ API. This sends an approval email to the admin.
After calling this, use check_access_status to poll for approval.
Once approved, the token is automatically saved for subsequent API calls.

Input parameters:

- `api_url` (string): API URL (default: https://spideriq.ai)
- `email` (string, required): Admin email address (the person who will approve access)
- `project` (string): Project name (shown in approval email)
- `scopes` (array): Requested permission scopes (default: jobs:submit, jobs:read)

### `check_access_status` (~152 tokens)

Check the status of a PAT access request.
Returns 'pending', 'active', 'denied', 'expired', or 'revoked' (matches the
backend PATRequestStatus enum). Once status==='active', the token is saved to
\~/.spideriq/credentials.json automatically. Multi-brand approvals save one
entry per workspace under client_id, with the first aliased as 'default' so
existing tools (upload_local_file, etc.) keep working without --workspace.

Input parameters:

- `api_url` (string): API URL (default: https://spideriq.ai)
- `poll_token` (string, required): Poll token from request_access
- `request_id` (string, required): Request ID from request_access

### `get_auth_status` (~33 tokens)

Check if you are authenticated and get current user info.

Input parameters:

- `workspace` (string): Workspace name (default: default)

### `logout` (~25 tokens)

Remove stored authentication credentials.

Input parameters:

- `workspace` (string): Workspace name (default: default)

### `list_workspaces` (~19 tokens)

List all configured workspaces and their authentication status.

### `health_check` (~51 tokens)

Check if the SpiderIQ API is healthy and responsive.

Input parameters:

- `api_url` (string): API URL (default: https://spideriq.ai)
- `workspace` (string): Workspace name (default: default)

### `get_queue_stats` (~48 tokens)

Get statistics about job queues (pending jobs, consumers, etc.).

Input parameters:

- `format` (string): Response format (default: json)
- `workspace` (string): Workspace name (default: default)

### `get_api_info` (~33 tokens)

Get information about the SpiderIQ API and your connection.

Input parameters:

- `workspace` (string): Workspace name (default: default)

### `content_list_pages` (~105 tokens)

List your brand's content pages (including drafts).

Input parameters:

- `limit` (number): Max results
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `status` (string): Filter by status
- `workspace` (string)

### `content_create_page` (~1356 tokens)

Create a new content page with blocks. Phase 11+12 Lock 4 gate is opt-in via dry_run/confirm_token.

🚨 BLOCK FIELD NAMES MATTER. The default theme's snippets read SPECIFIC `data.*` keys per block-type. Unrecognized keys are stored verbatim but render as empty markup (silent-blank-section trap). For the canonical per-block-type field list, call `template_inspect_block_fields(block_type)` OR read the `blocks` param schema below. Page auditor warns at read-time via `render.unused_field_in_default_theme` (rule shipped 2026-05-22).

Most-confused mappings:
  hero          → data.{headline, subheadline, cta_primary:{label,url}, cta_secondary:{label,url}, background_image_url, style}
                  (NOT title/subtitle/cta_text/cta_url — those are silent-no-op)
  cta_section   → data.{headline, description, cta_primary:{label,url}}
  stats_bar     → data.{stats: [{value, label}]}
  rich_text     → data.{html: '<raw html>'} OR data.{content: <Tiptap JSON doc>}
                  (data.content as a STRING is rejected — use data.html instead)

The `template` param selects which Liquid theme file renders the page (templates/<template>.liquid) — backend column is a free string, default 'default'.

Input parameters:

- `blocks` (array): Page content blocks (JSON array). Each block shape:   {id: '<uuid>', type: '<block_type>', data: {...}} Block types + the `data.*` fields the DEFAULT theme reads:   • hero            : headline, sub…
- `collection_type` (string): Phase MA-2 PR-D: required when `template` is 'dynamic_list' or 'dynamic_item'; MUST be null/absent for any other template. Allowed values: 'posts', 'docs', 'directory_listings'. Backend `_validate_co…
- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `dry_run` (boolean): Preview the change without mutating and receive a confirm_token. When omitted, the change is applied immediately (legacy behaviour preserved).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `seo_description` (string): SEO meta description
- `seo_title` (string): SEO title override
- `slug` (string): URL slug (auto-generated from title if omitted). Flat slugs only — `/` is rejected (pattern ^[a-z0-9][a-z0-9-]*$). Nested URLs not supported for general pages; docs use parent_id chains.
- `template` (string): Page template — selects which themes/default/templates/<template>.liquid the renderer uses. Free string (backend default 'default'). Common values bundled with the default theme: 'default' (standard…
- `title` (string, required): Page title
- `workspace` (string)

### `content_get_page` (~332 tokens)

Get a content page by ID (includes blocks, SEO, status).

IMPORTANT — `page_id` MUST be a UUID, not a slug. Passing a slug returns 404 (not 500 — task `3daae81c` fixed the previous unhandled-ValueError crash). To look up by slug, call `content_list_pages` and filter the response client-side (`pages.filter(p => p.slug === 'my-slug')`), then pass the matching `page.id` here.

P5: pass `audit_level` to surface a `_page_audit` block — "warnings" (default) returns errors + warnings from the PageAuditor walk so the agent learns about scroll-sequence empty frames, missing primary domains, latent Tier 3 components, etc. without a separate content_export_page call. Pass "off" to skip the auditor.

Input parameters:

- `audit_level` (string): P5: include a `_page_audit` block on the response. 'off' skips the auditor entirely (cheapest). 'errors' / 'warnings' / 'all' filter by severity. Default 'warnings'.
- `page_id` (string, required): Page UUID (NOT a slug — see tool description for the slug → UUID lookup pattern via content_list_pages).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_export_page` (~268 tokens)

Export a page as a self-contained envelope: page row + every component referenced by page.blocks (full body inlined — html_template, js, css, props_schema, dependencies, agent_meta, kind, layouts) + site settings + domains + a PageAuditor walk (10 v1 rules: scroll-sequence empty frames, missing primary domain, page SEO holes, latent Tier 3 components, etc.). Use this instead of content_get_page when you need the FULL picture before editing — e.g. to understand what `vp-hero` actually is, or to surface broken sections before redeploying.

Input parameters:

- `format` (string): json (default) — flat JSON envelope. md — human-readable Markdown. archive — ZIP byte stream matching the VSCode extension's local registry layout (page.json + components/<slug>@<version>.json + sett…
- `page_id` (string, required): Page ID
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_update_page` (~281 tokens)

Update a content page (title, blocks, SEO, template). Phase 11+12 Lock 4 gate is opt-in via dry_run/confirm_token.

Input parameters:

- `blocks` (array): Updated content blocks
- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `dry_run` (boolean): Preview the change without mutating and receive a confirm_token. When omitted, the change is applied immediately (legacy behaviour preserved).
- `page_id` (string, required): Page ID
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `seo_description` (string)
- `seo_title` (string)
- `slug` (string)
- `template` (string): Page template/layout. Known values: 'default' (templates/page.liquid), 'landing', 'blank', 'dynamic_landing', 'dynamic_list', 'dynamic_item', '404'. dynamic_list/dynamic_item also require collection_…
- `title` (string)
- `workspace` (string)

### `content_delete_page` (~165 tokens)

Archive/delete a content page. Phase 11+12: defaults to dry_run=true — review the preview and call again with confirm_token to actually delete.

Input parameters:

- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `dry_run` (boolean): Preview the change without mutating. Defaults to true — call again with confirm_token to actually mutate.
- `page_id` (string, required)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_publish_page` (~169 tokens)

Publish a draft page (creates a version snapshot). Phase 11+12: defaults to dry_run=true — review the preview and call again with confirm_token to actually publish.

Input parameters:

- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `dry_run` (boolean): Preview the change without mutating. Defaults to true — call again with confirm_token to actually mutate.
- `page_id` (string, required)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_unpublish_page` (~169 tokens)

Revert a published page to draft. Phase 11+12: defaults to dry_run=true — review the preview and call again with confirm_token to actually unpublish.

Input parameters:

- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `dry_run` (boolean): Preview the change without mutating. Defaults to true — call again with confirm_token to actually mutate.
- `page_id` (string, required)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_lock_page` (~179 tokens)

Lock a content page against further edits. Use when handing the page off for client review or scheduled launch. Idempotent — re-locking refreshes the reason. Other agents and dashboard users will receive 423 Locked on every mutation until you (or a super_admin) call content_unlock_page.

Input parameters:

- `page_id` (string, required): Page ID (UUID).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `reason` (string): Why the page is being locked. Surfaced in 423 Locked responses so the next agent knows whether to back off or override.
- `workspace` (string)

### `content_unlock_page` (~176 tokens)

Unlock a content page. Default: only the actor who originally locked it can unlock. Pass force=true (super_admin or brand_admin only) to override regardless of who holds the lock. Returns 403 with `not_lock_holder` if the caller is not the lock-holder and force is not set.

Input parameters:

- `force` (boolean): Override the lock-holder check (super_admin / brand_admin only). Use when the original lock-holder is unavailable.
- `page_id` (string, required): Page ID (UUID).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_list_page_versions` (~159 tokens)

List version snapshots for a page (newest first). Each version is created on publish + on restore — use this as the canonical "history" before content_restore_page_version. Returns metadata only (block_count, blocks_size, change_summary, created_at, changed_by); the heavy `blocks` payload is fetched lazily via content_get_page_version.

Input parameters:

- `page_id` (string, required): Page ID (UUID).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_get_page_version` (~145 tokens)

Fetch a single page version snapshot in full (includes the historical `blocks` body). Use when you need to diff a candidate restore against the current page before calling content_restore_page_version.

Input parameters:

- `page_id` (string, required): Page ID (UUID).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `version_number` (number, required): 1-indexed version number from content_list_page_versions.
- `workspace` (string)

### `content_restore_page_version` (~262 tokens)

Restore a page to a historical version snapshot. Phase 11+12 gated: defaults to dry_run=true — review the preview (which lists snapshot_block_count vs current_block_count + snapshot_created_at) and call again with confirm_token to actually restore. The restored page becomes draft; a new version row is appended recording the restore. Returns 423 Locked when the page is locked — pass force=true (super_admin / brand_admin only) to override.

Input parameters:

- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `dry_run` (boolean): Preview the change without mutating. Defaults to true — call again with confirm_token to actually mutate.
- `force` (boolean): Bypass page lock (super_admin / brand_admin only).
- `page_id` (string, required): Page ID (UUID).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `version_number` (number, required): 1-indexed version to restore.
- `workspace` (string)

### `content_list_posts` (~110 tokens)

List your brand's blog posts.

Input parameters:

- `limit` (number)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `status` (string): Filter by status
- `tag` (string): Filter by tag
- `workspace` (string)

### `content_create_post` (~495 tokens)

Create a blog post (Tiptap JSON body, metadata, tags, author, categories, cover image, featured flag, SEO).

Input parameters:

- `author_id` (string): Author UUID
- `author_name` (string): Free-text author name (used when no author_id)
- `body` (object): Post body (Tiptap JSON document)
- `category_ids` (array): Category UUIDs to assign — list, not single. Use [] to clear.
- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `cover_image_url` (string): Cover image URL. Field name MUST end with `_url` to persist.
- `dry_run` (boolean): Preview the change without mutating and receive a confirm_token. When omitted, the change is applied immediately (legacy behaviour preserved).
- `excerpt` (string): Short excerpt / summary
- `featured_image_alt` (string): Alt text for the cover image
- `is_featured` (boolean): Mark as featured post (field name is `is_featured`, not `featured`)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `related_post_ids` (array): Related post UUIDs (preserves order)
- `seo_description` (string): SEO meta description
- `seo_title` (string): SEO <title>; falls back to `title` if omitted
- `slug` (string): URL slug — kebab-case, no leading slash
- `tag_ids` (array): Tag entity UUIDs (new system; preferred over `tags`)
- `tags` (array): Post tags as strings (legacy text-tag system)
- `title` (string, required): Post title
- `tldr_summary` (string): TL;DR (2–3 sentences) shown above body
- `vayapin_pins` (array): VayaPin pin ids that fit this article (e.g. ['BB:TAPAS','BB:CHAMPERS']) — auto-renders a card strip at the post bottom. Resolve valid ids first via GET /content/vayapin/cards; unknown/unlisted pins a…
- `workspace` (string)

### `content_publish_post` (~89 tokens)

Publish a blog post.

Input parameters:

- `post_id` (string, required)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_docs_tree` (~84 tokens)

Get your brand's documentation tree structure.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_create_doc` (~127 tokens)

Create a documentation page.

Input parameters:

- `body` (object): Doc body (Tiptap JSON)
- `parent_id` (string): Parent doc ID (for nesting)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string): URL slug
- `title` (string, required): Doc title
- `workspace` (string)

### `content_list_docs` (~164 tokens)

List your brand's docs as a FLAT list (metadata only — no body). Complements content_docs_tree (which returns the hierarchy). Use this to discover a doc's UUID by title/status before fetching or mutating it via content_get_doc. Each item carries id, slug, full_path, title, status, parent_id, is_section, sort_order, seo_*, timestamps.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `status` (string): Filter by status.
- `workspace` (string)

### `content_get_doc` (~190 tokens)

Get a documentation page by ID (includes Tiptap body, SEO, status, full_path, preview_url).

IMPORTANT — `doc_id` MUST be a UUID, not a slug or full_path. Passing a non-UUID returns 404 (not 500). To look up by title/path, call content_list_docs (flat) or content_docs_tree (hierarchy) and filter client-side, then pass the matching `id` here.

Input parameters:

- `doc_id` (string, required): Doc UUID (NOT a slug/full_path — see tool description for the lookup pattern).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_update_doc` (~344 tokens)

Update a documentation page (title, body, SEO, hierarchy). Slug is immutable — to re-path a doc, change its `parent_id` (full_path is recomputed for the doc + its whole subtree). Moving a doc under one of its own descendants is rejected (cycle → 400). Phase 11+12 gate is opt-in via dry_run/confirm_token (omit both ⇒ immediate update).

Input parameters:

- `body` (object): Doc body (Tiptap JSON document). body_text (full-text search) is kept in sync automatically.
- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `doc_id` (string, required): Doc UUID.
- `dry_run` (boolean): Preview the change without mutating and receive a confirm_token. When omitted, the change is applied immediately (legacy behaviour preserved).
- `is_section` (boolean): Whether this doc is a section header (groups children, no own page).
- `parent_id` (string): Move the doc under a new parent (rebuilds full_path for the doc + descendants). Pass null/omit to leave unchanged.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `seo_description` (string)
- `seo_title` (string)
- `sort_order` (number): Position among siblings (ascending).
- `title` (string)
- `workspace` (string)

### `content_publish_doc` (~168 tokens)

Publish a draft doc (status → published). Phase 11+12: defaults to dry_run=true — review the preview and call again with confirm_token to actually publish.

Input parameters:

- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `doc_id` (string, required)
- `dry_run` (boolean): Preview the change without mutating. Defaults to true — call again with confirm_token to actually mutate.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_unpublish_doc` (~169 tokens)

Revert a published doc to draft. Phase 11+12: defaults to dry_run=true — review the preview and call again with confirm_token to actually unpublish.

Input parameters:

- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `doc_id` (string, required)
- `dry_run` (boolean): Preview the change without mutating. Defaults to true — call again with confirm_token to actually mutate.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `changelog_list` (~217 tokens)

List your brand's changelog entries (version, title, status, published_at). This IS the built-in CHANGELOG content type — a /changelog route, RSS+Atom feeds, and dashboard editor already exist; you do NOT need to build a changelog. Note the tool naming: changelog_list / changelog_create / changelog_publish use a `changelog_` prefix (NOT `content_*_changelog_entry`). An empty list means zero entries created yet, not a missing feature. Use this to discover an entry's UUID before publishing it via changelog_publish. Optionally filter by status (draft/published/archived).

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `status` (string): Filter by status.
- `workspace` (string)

### `changelog_create` (~178 tokens)

Create a DRAFT changelog entry. `version` must be unique for the brand (e.g. "v2.10.0"); a duplicate returns 409. `body` is a Tiptap JSON document. Publish it afterwards with changelog_publish.

Input parameters:

- `body` (object, required): Entry body (Tiptap JSON document).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `title` (string, required): Release title.
- `version` (string, required): Version label, unique per brand (e.g. "v2.10.0").
- `workspace` (string)

### `changelog_publish` (~152 tokens)

Publish a changelog entry (status → published). It appears on the public /changelog timeline + RSS/Atom feeds and, on the first publish, fires the changelog.published notification to subscribers. Reversible (no dry_run gate). Pass the entry UUID from changelog_list.

Input parameters:

- `changelog_id` (string, required): Changelog entry UUID (from changelog_list).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_delete_doc` (~186 tokens)

Archive/delete a documentation page (soft delete → archived). Children are left intact (a deleted section still anchors its descendants by parent_id). Phase 11+12: defaults to dry_run=true — review the preview and call again with confirm_token to actually delete.

Input parameters:

- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `doc_id` (string, required)
- `dry_run` (boolean): Preview the change without mutating. Defaults to true — call again with confirm_token to actually mutate.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_export_doc` (~182 tokens)

Export a doc as a self-contained envelope: doc row (Tiptap body, SEO, full_path) + site settings + domains. Docs are prose-first, so there are no component bodies to inline (unlike content_export_page). format='json' (default) returns the JSON envelope; format='md' returns human-readable Markdown rendered from the body.

Input parameters:

- `doc_id` (string, required)
- `format` (string): json (default) — JSON envelope; md — Markdown rendered from the Tiptap body.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_import_markdown` (~446 tokens)

Import a doc OR page from a Markdown body — the universal Markdown→content bridge. target='doc' parses Markdown into a Tiptap doc body; target='page' parses prose runs into rich_text blocks. `:::component{slug=… version=… props={…}}` directives become embedded components (the MDX unlock). Create a NEW item (omit the id, pass slug + title) or REPLACE an existing one's body/blocks (pass doc_id for a doc / page_id for a page). The Phase 11+12 gate is opt-in via dry_run/confirm_token and applies on the REPLACE path (omit both ⇒ immediate). Round-trips with content_export_markdown. Markdown is capped at 256 KB.

Input parameters:

- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `doc_id` (string): Existing doc to replace (target='doc'); omit to create.
- `dry_run` (boolean): Preview the change without mutating and receive a confirm_token. When omitted, the change is applied immediately (legacy behaviour preserved).
- `markdown` (string, required): Markdown source (≤256 KB). `:::component{...}` directives are preserved.
- `page_id` (string): Existing page to replace blocks on (target='page'); omit to create.
- `parent_id` (string): Parent doc/page id (nesting on create; doc re-path on update).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string): Flat slug — required when creating, ignored when updating (slug is immutable).
- `target` (string, required): What to create/update from the Markdown.
- `template` (string): Page template (target='page' create only; default 'default').
- `title` (string): Required when creating; updates the title when set on an existing item.
- `workspace` (string)

### `content_import_openapi` (~376 tokens)

Generate a full API-reference docs section from ANY OpenAPI 3.x or Swagger 2.0 spec (the flagship 'docs as a product' feature — Stripe/ReadMe/Mintlify-tier). Provide EXACTLY ONE of source_url (fetched server-side, SSRF-safe) or spec_content (pasted JSON/YAML). Creates one doc page per tag under the `section` slug (default 'api-reference'), each endpoint with method/path/params/schemas and auto multi-language code samples (curl/Python/JS/Go) in a `:::codegroup` block. Re-import is IDEMPOTENT — the importer owns the section subtree (upserts tag pages, archives removed ones). Use dry_run=true to preview the planned section + pages without writing. Docs are created as drafts unless publish=true.

Input parameters:

- `dry_run` (boolean): Preview the planned section + pages without writing anything.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `publish` (boolean): Publish the generated docs immediately (default false → created as drafts for review).
- `section` (string): Slug of the docs section to generate under (default 'api-reference'). Importer-owned subtree.
- `source_url` (string): HTTPS/HTTP URL of the OpenAPI/Swagger spec (fetched SSRF-safely). Provide this OR spec_content.
- `spec_content` (string): Raw spec text (JSON or YAML) — alternative to source_url.
- `spec_format` (string): Spec body format (default 'auto').
- `workspace` (string)

### `content_export_markdown` (~196 tokens)

Export a doc OR page as pure, round-trippable Markdown. target='doc' renders the Tiptap body; target='page' renders the blocks with each component block serialized back to a `:::component{...}` directive. The text round-trips through content_import_markdown. (For the richer JSON export envelope — components inlined, settings, domains, audit — use content_export_doc / content_export_page instead.)

Input parameters:

- `id` (string, required): Doc UUID (target=doc) or Page UUID (target=page).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `target` (string, required): Which resource to export.
- `workspace` (string)

### `content_get_navigation` (~96 tokens)

Get navigation menu (header, footer, docs_sidebar).

Input parameters:

- `location` (string, required): Menu location
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_update_navigation` (~102 tokens)

Update navigation menu items.

Input parameters:

- `items` (array, required): Navigation items (nested JSON)
- `location` (string, required): Menu location
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_get_settings` (~93 tokens)

Get your brand's content settings (site name, SEO defaults, analytics, colors).

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_update_settings` (~338 tokens)

Update content settings (site name, SEO, analytics code, primary color, custom head scripts, etc.). IMPORTANT: wrap the fields you want to change inside a top-level `settings` object — pass `{ settings: { site_name: 'X', primary_color: '#abc' } }`, NOT `{ site_name: 'X', primary_color: '#abc' }` and NOT `{ changes: { ... } }` (other tools like `form_update` use `changes:`; this tool uses `settings:`). The wrapper is required; calls without it return 422 'Field required'. Phase 11+12: defaults to dry_run=true — review the preview and call again with confirm_token to apply.

Input parameters:

- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `dry_run` (boolean): Preview the change without mutating. Defaults to true — call again with confirm_token to actually mutate.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `settings` (object, required): REQUIRED top-level wrapper. The dict of settings fields to update (e.g. { site_name: 'X', primary_color: '#abc', custom_head_scripts: '<script>…</script>' }). Note: tool wrapper, NOT `changes` (which…
- `workspace` (string)

### `content_list_domains` (~87 tokens)

List custom domains configured for your brand's content site.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_add_domain` (~109 tokens)

Add a custom domain for your content site. Requires DNS verification after adding.

Input parameters:

- `domain` (string, required): Domain name (e.g., "blog.mycompany.com")
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_verify_domain` (~99 tokens)

Verify DNS for a custom domain (checks CNAME/A record).

Input parameters:

- `domain` (string, required): Domain to verify
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_set_primary_domain` (~102 tokens)

Set a verified domain as the primary domain for your content site.

Input parameters:

- `domain` (string, required): Domain to set as primary
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_delete_domain` (~95 tokens)

Remove a custom domain from your content site.

Input parameters:

- `domain` (string, required): Domain to remove
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_get_post` (~102 tokens)

Get a blog post by ID (includes body, tags, author, status).

Input parameters:

- `post_id` (string, required): Post ID
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_update_post` (~441 tokens)

Update a blog post (title, body, excerpt, tags, cover image, author, categories, featured, SEO).

Input parameters:

- `author_id` (string): Author UUID
- `author_name` (string)
- `body` (object): Post body (Tiptap JSON document)
- `category_ids` (array): Category UUIDs to assign — list, not single. Use [] to clear.
- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `cover_image_url` (string): Cover image URL. Field name MUST end with `_url` to persist.
- `dry_run` (boolean): Preview the change without mutating and receive a confirm_token. When omitted, the change is applied immediately (legacy behaviour preserved).
- `excerpt` (string)
- `featured_image_alt` (string): Alt text for the cover image
- `is_featured` (boolean): Mark as featured post (field name is `is_featured`, not `featured`)
- `og_image_url` (string)
- `post_id` (string, required): Post ID
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `related_post_ids` (array)
- `seo_description` (string)
- `seo_title` (string)
- `slug` (string)
- `tag_ids` (array): Tag entity UUIDs (new system)
- `tags` (array): Legacy text tags
- `title` (string)
- `tldr_summary` (string)
- `vayapin_pins` (array): VayaPin pin ids that fit this article (e.g. ['BB:TAPAS','BB:CHAMPERS']) — auto-renders a card strip at the post bottom. Omit to leave unchanged; pass [] to clear. Resolve ids via GET /content/vayapin…
- `workspace` (string)

### `content_delete_post` (~173 tokens)

Delete a blog post. Phase 11+12 Lock 4 gate is opt-in via dry_run/confirm_token (defaults preserve immediate-delete for backward compat).

Input parameters:

- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `dry_run` (boolean): Preview the change without mutating and receive a confirm_token. When omitted, the change is applied immediately (legacy behaviour preserved).
- `post_id` (string, required): Post ID
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_unpublish_post` (~95 tokens)

Revert a published post to draft.

Input parameters:

- `post_id` (string, required): Post ID
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_update_post_status` (~106 tokens)

Update post status (draft, published, archived).

Input parameters:

- `post_id` (string, required): Post ID
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `status` (string, required): New status
- `workspace` (string)

### `content_search_posts` (~106 tokens)

Search published posts by keyword (public, no auth needed).

Input parameters:

- `limit` (number): Max results
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `query` (string, required): Search query
- `workspace` (string)

### `content_featured_posts` (~101 tokens)

Get featured blog posts (public, no auth needed).

Input parameters:

- `limit` (number): Max results (default 5)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_list_authors` (~84 tokens)

List your brand's blog authors.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_create_author` (~166 tokens)

Create a blog author profile.

Input parameters:

- `agent_type` (string): Human or AI author
- `avatar_url` (string): Avatar image URL
- `bio` (string): Author biography
- `city` (string)
- `country` (string)
- `email` (string): Author email
- `full_name` (string, required): Author full name
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `role` (string): Author role
- `slug` (string): URL slug
- `workspace` (string)

### `content_get_author` (~93 tokens)

Get an author profile by ID.

Input parameters:

- `author_id` (string, required): Author ID
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_update_author` (~157 tokens)

Update an author profile.

Input parameters:

- `agent_type` (string)
- `author_id` (string, required): Author ID
- `avatar_url` (string)
- `bio` (string)
- `city` (string)
- `country` (string)
- `email` (string)
- `full_name` (string)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `role` (string)
- `slug` (string)
- `workspace` (string)

### `content_delete_author` (~92 tokens)

Soft-delete an author profile.

Input parameters:

- `author_id` (string, required): Author ID
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_list_tags` (~87 tokens)

List your brand's blog tags (includes post count).

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_create_tag` (~108 tokens)

Create a blog tag.

Input parameters:

- `description` (string): Tag description
- `name` (string, required): Tag name
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string): URL slug
- `workspace` (string)

### `content_update_tag` (~112 tokens)

Update a blog tag.

Input parameters:

- `description` (string)
- `name` (string)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string)
- `tag_id` (string, required): Tag ID
- `workspace` (string)

### `content_delete_tag` (~91 tokens)

Delete a blog tag.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `tag_id` (string, required): Tag ID
- `workspace` (string)

### `content_list_categories` (~86 tokens)

List your brand's blog categories (supports hierarchy).

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_create_category` (~136 tokens)

Create a blog category (supports parent_id for hierarchy).

Input parameters:

- `description` (string)
- `name` (string, required): Category name
- `parent_id` (string): Parent category ID (for nesting)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string): URL slug
- `sort_order` (number): Display order
- `workspace` (string)

### `content_update_category` (~131 tokens)

Update a blog category.

Input parameters:

- `category_id` (string, required): Category ID
- `description` (string)
- `name` (string)
- `parent_id` (string): Parent category ID
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string)
- `sort_order` (number)
- `workspace` (string)

### `content_delete_category` (~91 tokens)

Delete a blog category.

Input parameters:

- `category_id` (string, required): Category ID
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_list_components` (~131 tokens)

List UI components (reusable blocks with Shadow DOM isolation).

Input parameters:

- `category` (string): Filter by category
- `include_global` (boolean): Include global (system) components
- `limit` (number): Max results
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `status` (string): Filter by status
- `workspace` (string)

### `content_create_component` (~1288 tokens)

Create a reusable UI component (auto-wrapped in Shadow DOM for CSS isolation).

IMPORTANT — set `kind` at create time. Components without a `kind` are flagged as latent Tier 3 by the page auditor (rule `creation.kind_null_with_dependencies`) and excluded from marketplace_search. If you're shipping `dependencies` (gsap, chartjs, etc.) you almost always want `kind='interactive'` + `js_runtime='vanilla'`. See the `kind` field for the full taxonomy and the kind→js_runtime/block_type/sources invariant matrix.

P5: pass `authoring_hints` to surface preferred_path / common_mistakes / must_set / must_not_set on the _rules envelope when other agents insert your component. The response carries an _audit block flagging latent traps (kind=interactive without js, global component without agent_meta, etc.).

Input parameters:

- `agent_meta` (object): Phase A agent-discovery metadata. Validated by `ComponentAgentMeta` (Pydantic `extra='forbid'`). Shape: { interaction_pattern?: enum, trigger_kind?: enum, intent?: string, audience_tags?: string[] }.…
- `authoring_hints` (object): P5 — author-written rules surfaced via the _rules envelope when this component is inserted. Shape: {preferred_path?: string, common_mistakes?: string[], must_set?: string[], must_not_set?: string[]}.…
- `block_type` (string): Generic block shape — REQUIRED when kind='dynamic', MUST be NULL otherwise (DB CHECK constraint chk_components_kind via migration 174). Drives the editor's block-shape picker.
- `brand_fit_tags` (array): Universal axis — multi-value industry vertical fit. Drives marketplace cross-filter.
- `category` (string): Component category
- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `css` (string): Component CSS (isolated via Shadow DOM — no leaks)
- `default_props` (object): Default prop values
- `dependencies` (array): CDN library keys from allowlist (Tier 3). E.g. ["gsap", "gsap/ScrollTrigger"]. Use content_list_cdn_allowlist to see available keys. When non-empty, set `kind` to `interactive` / `dynamic` / `extensi…
- `description` (string): Component description
- `dry_run` (boolean): Preview the change without mutating and receive a confirm_token. When omitted, the change is applied immediately (legacy behaviour preserved).
- `framework` (string): Framework for Tier 4 app components
- `html_template` (string, required): Liquid HTML template for the component
- `is_global` (boolean): Make available to all clients
- `js` (string): Vanilla JS scoped to shadow root (Tier 2). Receives root (shadowRoot) and props arguments.
- `js_runtime` (string): JavaScript runtime pattern — REQUIRED for kind ∈ {interactive, dynamic, extension}, MUST be NULL when kind='static'.   vanilla       — inline <script> blocks; no module bundling.   web-component — C…
- `kind` (string): Behavioural class (Phase A 4-class taxonomy). DEFAULTS TO NULL — components without a kind are flagged 'latent Tier 3' by the page auditor and excluded from marketplace_search.   static       — prop…
- `mood` (array): Universal axis — multi-value mood tags for marketplace discovery (Phase A agent-discovery).
- `name` (string, required): Display name
- `palette` (array): Universal axis — open vocabulary palette tokens (e.g. "warm-neutrals", "monochrome", "neon-cyan-magenta"). Max 12.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `props_schema` (object): JSON Schema defining accepted props
- `scene_type` (string): Universal axis — single-value scene/intent. Component-scoped values listed; cross-asset values live on bg-videos / site-templates.
- `slug` (string, required): Component slug (URL-safe identifier)
- `source_code` (string): Framework source code (JSX/Vue SFC/Svelte)
- `sources` (array): Live Data — the data source(s) this component binds to. REQUIRED (non-empty) when kind='dynamic' (backend 422 via chk_components_kind). At render the server fetches each source and exposes the result…
- `tags` (array): Tags for discovery
- `thumbnail_url` (string): Preview thumbnail URL
- `version` (string): Semver version (default 1.0.0)
- `workspace` (string)

### `content_get_component` (~101 tokens)

Get a UI component by ID (includes template, CSS, props schema).

Input parameters:

- `component_id` (string, required): Component ID
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_get_component_by_slug` (~114 tokens)

Get a UI component by slug (optionally a specific version).

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string, required): Component slug
- `version` (string): Specific version (default: latest published)
- `workspace` (string)

### `content_update_component` (~1146 tokens)

Update a UI component (template, CSS, JS, props schema, metadata).

Use this to upgrade an existing component to a Phase A 4-class taxonomy entry — pass `kind` + (when kind != 'static') `js_runtime`. PATCH semantics: cross-field invariants (kind+block_type pairing for kind='dynamic', extension_spec required for kind='extension') are validated by the DB CHECK constraints in migration 174 — backend returns 400 with the constraint name if the patched row would violate them. Use the universal axes (mood / palette / brand_fit_tags / scene_type) to backfill agent-discovery metadata on rows authored before the marketplace search shipped.

Input parameters:

- `agent_meta` (object): Phase A agent-discovery metadata. Validated by `ComponentAgentMeta` (Pydantic `extra='forbid'`). Shape: { interaction_pattern?: enum, trigger_kind?: enum, intent?: string, audience_tags?: string[] }.…
- `authoring_hints` (object): P5 — replace component-author-written rules surfaced via the _rules envelope. Pass {} to clear. Shape: {preferred_path?: string, common_mistakes?: string[], must_set?: string[], must_not_set?: string…
- `block_type` (string): Generic block shape — REQUIRED when kind='dynamic', MUST be NULL otherwise (DB CHECK constraint chk_components_kind via migration 174). Drives the editor's block-shape picker.
- `brand_fit_tags` (array): Universal axis — multi-value industry vertical fit. Drives marketplace cross-filter.
- `category` (string)
- `component_id` (string, required): Component ID
- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `css` (string): Component CSS
- `default_props` (object)
- `dependencies` (array): CDN library keys (Tier 3). Use content_list_cdn_allowlist for available keys. When adding deps to a component without a `kind`, also patch `kind`/`js_runtime` in the same PATCH to avoid the latent-Ti…
- `description` (string)
- `dry_run` (boolean): Preview the change without mutating and receive a confirm_token. When omitted, the change is applied immediately (legacy behaviour preserved).
- `framework` (string): Framework for Tier 4 app components
- `html_template` (string): Liquid HTML template
- `js` (string): Vanilla JS scoped to shadow root (Tier 2)
- `js_runtime` (string): JavaScript runtime pattern — REQUIRED for kind ∈ {interactive, dynamic, extension}, MUST be NULL when kind='static'.   vanilla       — inline <script> blocks; no module bundling.   web-component — C…
- `kind` (string): Behavioural class (Phase A 4-class taxonomy). DEFAULTS TO NULL — components without a kind are flagged 'latent Tier 3' by the page auditor and excluded from marketplace_search.   static       — prop…
- `mood` (array): Universal axis — multi-value mood tags for marketplace discovery (Phase A agent-discovery).
- `name` (string)
- `palette` (array): Universal axis — open vocabulary palette tokens (e.g. "warm-neutrals", "monochrome", "neon-cyan-magenta"). Max 12.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `props_schema` (object): JSON Schema for props
- `scene_type` (string): Universal axis — single-value scene/intent. Component-scoped values listed; cross-asset values live on bg-videos / site-templates.
- `source_code` (string): Framework source code (JSX/Vue SFC/Svelte)
- `sources` (array): Live Data — the data source(s) this component binds to. REQUIRED (non-empty) when kind='dynamic' (backend 422 via chk_components_kind). At render the server fetches each source and exposes the result…
- `tags` (array)
- `thumbnail_url` (string)
- `workspace` (string)

### `content_delete_component` (~166 tokens)

Delete a UI component. Phase 11+12: defaults to dry_run=true — review the preview and call again with confirm_token to actually delete.

Input parameters:

- `component_id` (string, required): Component ID
- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `dry_run` (boolean): Preview the change without mutating. Defaults to true — call again with confirm_token to actually mutate.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_publish_component` (~172 tokens)

Publish a draft component (makes it available for use in page blocks). Phase 11+12: defaults to dry_run=true — review the preview and call again with confirm_token.

Input parameters:

- `component_id` (string, required): Component ID
- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `dry_run` (boolean): Preview the change without mutating. Defaults to true — call again with confirm_token to actually mutate.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_archive_component` (~172 tokens)

Archive a component (removes from active use, keeps for reference). Phase 11+12: defaults to dry_run=true — review the preview and call again with confirm_token.

Input parameters:

- `component_id` (string, required): Component ID
- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `dry_run` (boolean): Preview the change without mutating. Defaults to true — call again with confirm_token to actually mutate.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_list_component_versions` (~95 tokens)

List all versions of a component by slug.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string, required): Component slug
- `workspace` (string)

### `content_list_cdn_allowlist` (~113 tokens)

List available CDN libraries for component dependencies (Tier 3). Returns keys, names, URLs, categories. Use these keys in the dependencies array when creating/updating components.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_get_build_status` (~112 tokens)

Get the build status of a framework component (Tier 4). Returns build_status, build_error, bundle_url.

Input parameters:

- `component_id` (string, required): Component ID
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string): Workspace name

### `content_rebuild_component` (~112 tokens)

Trigger a rebuild of a framework component (Tier 4). Returns 202 — poll with content_get_build_status.

Input parameters:

- `component_id` (string, required): Component ID
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string): Workspace name

### `content_upload_component_preview` (~371 tokens)

Upload a preview thumbnail (PNG/JPG/GIF/WEBP/MP4) for a component.

Reads the file from the local filesystem, sniffs the content-type from the
extension, POSTs multipart to /content/components/{id}/upload-preview, and
the server uploads to R2 + PATCHes preview_thumbnail_url on the row in one
round-trip. Allowed extensions: png, jpg, jpeg, gif, webp, mp4. 5 MB cap
(server-enforced; for larger animated MP4 use SpiderMedia upload then PATCH
preview_thumbnail_url manually).

CRO bug-fix bundle (2026-05-08, Antigravity report Bug 2): the API endpoint
existed since Marketplace Admin Slice 1 (2026-04-28) but was not exposed
through any agent-facing surface — agents using @spideriq/mcp-publish had
no way to reach it. Now wired up.

Returns: {url, key, size_bytes, content_type, component_id, preview_thumbnail_url}.

Input parameters:

- `component_id` (string, required): Component ID (UUID) to attach the preview to.
- `ext` (string): Override extension (default: extension from local_path, lowercased). One of: png, jpg, jpeg, gif, webp, mp4.
- `local_path` (string, required): Absolute or cwd-relative path to the preview file on disk.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string): Workspace name (default: "default").

### `content_upload_bg_video` (~335 tokens)

Upload a bg-video MP4 (or poster image) to R2 for the marketplace bg-video catalog.

Reads the file from the local filesystem, POSTs multipart to
/content/bg-videos/upload, server uploads to R2 at `bg-videos/<slug>.<ext>`
and returns the public URL. Allowed extensions: mp4 (video), webp/png/jpg/jpeg/gif (poster).
50 MB cap (server-enforced).

Unlike component uploads, this tool does NOT touch the catalog row — call
\`content_create_bg_video` or `content_update_bg_video` afterwards with
the returned URL in `video_url` or `poster_url`. Both fields are
strict-allowlisted to R2 hosts as of 2026-05-12.

Returns: {url, key, size_bytes, content_type}.

Input parameters:

- `ext` (string): Override extension (default: extension from local_path, lowercased). One of: mp4, webp, png, jpg, jpeg, gif.
- `local_path` (string, required): Absolute or cwd-relative path to the file on disk.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string, required): Bg-video slug — used as the R2 key stem (bg-videos/<slug>.<ext>).
- `workspace` (string): Workspace name (default: "default").

### `content_upload_site_template_preview` (~327 tokens)

Upload a preview image (PNG/JPG/GIF/WebP) for a site template.

Reads the file from the local filesystem, POSTs multipart to
/content/site-templates/{slug}/upload-preview, server uploads to R2 at
\`templates/<slug>.<ext>` and returns the public URL. Allowed extensions:
png, jpg, jpeg, gif, webp. 5 MB cap.

Unlike component uploads, this tool does NOT patch the catalog row — call
\`content_update_site_template` afterwards with the returned URL in
\`preview_thumbnail_url` (and optionally `preview_url`). Both fields are
strict-allowlisted to R2 + curated preview hosts as of 2026-05-12.

Returns: {url, key, size_bytes, content_type}.

Input parameters:

- `ext` (string): Override extension (default: extension from local_path, lowercased). One of: png, jpg, jpeg, gif, webp.
- `local_path` (string, required): Absolute or cwd-relative path to the preview file on disk.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string, required): Site template slug — used as the R2 key stem (templates/<slug>.<ext>) AND the path segment.
- `workspace` (string): Workspace name (default: "default").

### `content_visual_check` (~611 tokens)

Open a URL in a real browser and report what an end-user actually sees. Returns screenshot + DOM info + console errors + failed requests + per-assertion results.

USE: verify a content page or form is rendering correctly after a publish operation; catch silent-200-with-broken-content failures that monitoring doesn't see.

NOT: don't use for crawling external sites; URL allowlist restricts to spideriq.ai subdomains + tenant verified custom domains.

CRITICAL ASSERTION RULE (from learnings_visual_check_assert_on_shadow_hosts.md, codified 2026-05-18): when verifying a form is rendering correctly, ALWAYS assert on `dom.shadow_hosts.includes("spideriq-form")`. DO NOT assert on `body_text_preview` for cross-origin iframe contents — the iframe body is opaque to the parent page's DOM, so field labels and button text are NOT in body_text_preview even when the form is rendering correctly. Same applies to any custom-element shadow-host: assert on its tag name in dom.shadow_hosts, not on body text.

WARN: screenshot upload may be degraded if R2 isn't configured; check screenshot_url for null. Engine still works in degraded mode.

PITFALLS:
\- Asserting on body_text_preview for embedded form/booking widgets — will FAIL even on a working form, because the iframe body is cross-origin.
\- Forgetting to pass viewport='mobile' when checking responsive behavior — defaults to desktop 1440x900.
\- Hitting non-allowlisted URLs — will return URL_NOT_WHITELISTED envelope.

LIMITS:
\- 30s default / 60s hard-cap timeout per check
\- 5MB page-size cap
\- 20 requests/min per client

Input parameters:

- `expected_no_text` (array): Strings that MUST NOT appear (e.g. "couldn't load this booking").
- `expected_text` (array): Strings that MUST appear in body_text_preview. NOTE: opaque to cross-origin iframe contents — assert on dom.shadow_hosts for form/booking widgets instead.
- `page_url` (string, required): Full URL to check. Must be on the allowlist (spideriq.ai subdomains or a tenant verified custom domain).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `tenant_id` (string): Optional. Expands the URL allowlist to that tenant's verified primary domain.
- `timeout_ms` (number): Total navigation + wait timeout, in ms. Default 30000, hard cap 60000.
- `viewport` (string): Viewport preset. desktop=1440x900, mobile=375x667. Defaults to desktop.
- `wait_for_text` (string): Optional — wait until this string appears in the DOM before snapshotting.

### `template_get_help` (~391 tokens)

SpiderPublishREADME — agent orchestration entry-point. Returns four
sections in one response:
  • reference    — canonical schema (content types, block types, Liquid
                    filters/tags, template structure, data sources). The
                    exact YAML/JSON/MD payload the legacy tool returned.
                    Includes per-block-type field maps + agent-natural
                    alias hints (2026-05-22 usability F-19) so an agent
                    that writes `hero.title` instead of `hero.headline`
                    catches the mistake before publishing.
  • site_context  — current spideriq.json binding (client_id, project_name,
                    brand_name) walked up from cwd; null when unbound.
  • recipes      — workflow markdowns from @spideriq/skills (build-a-
                    homepage, add-a-component, swap-a-hero-block,
                    clone-a-site, add-a-domain). Read the matching one
                    BEFORE improvising.
  • routing      — "if user asks X, call tool Y" rules. Adopt before
                    improvising.

Call this FIRST in any SpiderPublish-related conversation. The reference
still comes from /api/v1/content/help so it tracks the deployed API.
For the live theme's per-block-type fields, call
\`template_inspect_block_fields(block_type)` — it returns the canonical
fields the ACTIVE theme's snippet reads + the agent-natural alias map.

Input parameters:

- `format` (string): Response format (default: yaml). Wraps reference + site_context + recipes + routing into one document.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `template_inspect_block_fields` (~312 tokens)

Get the canonical `data.*` fields the default theme reads for a block
type, plus the agent-natural alias map.

Use this BEFORE inserting a non-component block (hero, cta_section,
stats_bar, comparison_table, etc.) to avoid the silent-blank-section
trap from the 2026-05-22 usability report (F-9). Returns:
  • fields           — what the snippet actually reads
  • _aliases         — common mistakes → canonical field name
                       (e.g. {"title": "headline", "cta_text":
                       "cta_primary (object: {label, url})"})
  • _anti_patterns   — shapes that 422 (e.g. rich_text + data.content
                       as a string is REJECTED — pass data.html instead)
  • _notes           — free-form caveats

Omit `block_type` to list all known block types. Public read, no auth.

Input parameters:

- `block_type` (string): Specific block type to inspect (e.g. "hero", "cta_section"). Omit to list all.
- `format` (string): Response format (default: json).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_get_variables` (~207 tokens)

\**START HERE for personalized landing pages.** Returns the full merge-tag vocabulary ({{firstname}}, {{company_name}}, {{city}}, {{industry}}, {{logo}}, {{email}}, ~40 tokens total) for dynamic-landing templates — Mailchimp-style flat tags every LLM already knows. Includes plain-English descriptions, realistic example values from the Mario's Pizzeria demo fixture, and selection rules (e.g. how `{{ email }}` picks the best verified address). Works without auth. Fetch once at session start — you'll know every variable you can drop into a Liquid template.

Input parameters:

- `format` (string): Response format (default: yaml — token-efficient)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `template_list` (~84 tokens)

List all custom Liquid templates for your site.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `template_get` (~199 tokens)

Get a Liquid template source code by path (e.g. "templates/blog.liquid"). Returns YOUR tenant's KV override if one exists, otherwise the bundled default-theme file. A 404 means neither exists for this tenant — it does NOT mean the feature is missing: the page can still render from the default theme even when this returns 404 (e.g. templates/changelog.liquid). Likewise, a large inline-CSS template here is your own prior customization, not what SpiderPublish ships.

Input parameters:

- `path` (string, required): Template path (e.g. layout/theme.liquid, snippets/hero-block.liquid)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `template_upsert` (~445 tokens)

Create or update a Liquid template. Provide the FULL Liquid template source code. The `path` param is the file path under the client's theme (e.g. 'templates/default.liquid', 'layout/theme.liquid', 'snippets/post-card.liquid'). It is a FILENAME, not a slug or shorthand — passing 'form' or 'page' as `path` will store garbage that no template-lookup path consults. Customizing form-page chrome at /f/<flow_id>: override 'templates/forms-standalone.liquid' (NOT 'templates/form.liquid', which is unused). Same for booking pages: 'templates/booking-standalone.liquid'. Both extend layout/theme.liquid, so a layout override applies to page + form + booking chrome together. To target form pages from inside layout/theme.liquid use `{% if template == 'forms-standalone' %}` (the Liquid `template` variable mirrors the file's basename, NOT a short name like 'form'). Phase 11+12 Lock 4 gate is opt-in via dry_run/confirm_token.

Input parameters:

- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `content` (string, required): Liquid template source code (full file body, not a diff).
- `dry_run` (boolean): Preview the change without mutating and receive a confirm_token. When omitted, the change is applied immediately (legacy behaviour preserved).
- `path` (string, required): Template file path under the theme (e.g. 'templates/default.liquid', 'templates/forms-standalone.liquid', 'layout/theme.liquid'). Required. Backend rejects literal 'undefined' / 'null' / empty / non-…
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `theme` (string): Theme name (default: "default")
- `workspace` (string)

### `template_delete` (~183 tokens)

Delete a custom template (reverts to the theme default for that path). Phase 11+12 Lock 4 gate is opt-in via dry_run/confirm_token (defaults preserve immediate-delete for backward compat).

Input parameters:

- `confirm_token` (string): Token from a prior dry_run call. Single-use, 7d TTL.
- `dry_run` (boolean): Preview the change without mutating and receive a confirm_token. When omitted, the change is applied immediately (legacy behaviour preserved).
- `path` (string, required): Template path to delete
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `template_list_themes` (~83 tokens)

List available pre-built themes.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `template_apply_theme` (~166 tokens)

Apply a pre-built theme to your site. Copies all theme templates to your template set. Phase 11+12: defaults to dry_run=true. Review the preview, then call again with confirm_token to actually apply.

Input parameters:

- `confirm_token` (string): Token from a prior dry_run call.
- `dry_run` (boolean): Preview the change without mutating. Default true.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `theme` (string): Theme name (default: "default")
- `workspace` (string)

### `template_get_config` (~93 tokens)

Get template config: current theme, route overrides, settings, and connected data sources.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `template_update_config` (~148 tokens)

Update template config: theme, route overrides, settings, or data sources.

Input parameters:

- `data_sources` (array): Connected SpiderIQ data sources
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `routes` (object): Path → template overrides (e.g. {"/pricing": "templates/pricing.liquid"})
- `settings` (object): Theme-level settings
- `theme` (string): Theme name
- `workspace` (string)

### `template_preview` (~113 tokens)

Render a template with mock data and return the HTML output.

Input parameters:

- `data` (object): Mock data to pass to the template
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `template_path` (string, required): Template path to render
- `workspace` (string)

### `content_deploy_site_preview` (~134 tokens)

Phase 11+12 Stage 2 — issue a preview URL + confirm_token without deploying. Returns `{ preview_url, confirm_token, expires_at, preview: {...}, snapshot_hash }`. Call `content_deploy_site_production` with the returned confirm_token to actually deploy.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_deploy_site_production` (~146 tokens)

Phase 11+12 Stage 2 — consume a confirm_token from a prior `content_deploy_site_preview` call and run the real deploy (Lock 4). 410 on expired, 409 on already-consumed, 403 on mismatch.

Input parameters:

- `confirm_token` (string, required): Token returned by content_deploy_site_preview
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_deploy_site` (~188 tokens)

Deploy your site to Cloudflare edge. Uploads templates + config, site goes live in ~2-5 seconds. Phase 11+12: prefer `content_deploy_site_preview` + `content_deploy_site_production` for the safe two-step flow. This tool is kept for back-compat; set dry_run=true to preview, or pass confirm_token to consume a prior preview.

Input parameters:

- `confirm_token` (string): Consume a prior preview token and deploy.
- `dry_run` (boolean): Issue a preview + confirm_token without deploying.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_deploy_status` (~86 tokens)

Check the latest deploy status for your site.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_deploy_readiness` (~126 tokens)

Check if your site is ready to deploy. Returns a checklist of what is configured (settings, domain, templates, pages) and what is missing. Call this BEFORE content_deploy_site — deploy will reject if blocking items are not resolved.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `import_from_url` (~171 tokens)

Import file(s) from URL into your SpiderMedia bucket.
Supports single URL or batch. Auto-proxies Instagram/Facebook/Twitter CDN URLs.

Input parameters:

- `folder` (string): Target folder (e.g., "ads", "logos")
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `url` (string): Single URL to import
- `urls` (array): Batch URLs to import [{url, filename?}]
- `use_proxy` (boolean): Force proxy for CDN URLs (default: auto-detect)
- `workspace` (string): Workspace name

### `list_files` (~126 tokens)

List files in your SpiderMedia bucket.

Input parameters:

- `limit` (number): Max results (default: 20)
- `offset` (number): Offset for pagination
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `type` (string): Filter by file type (image, video, document)
- `workspace` (string): Workspace name

### `delete_file` (~104 tokens)

Delete a file from your SpiderMedia bucket by storage key.

Input parameters:

- `key` (string, required): File storage key (from list_files response)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string): Workspace name

### `list_videos` (~110 tokens)

List videos in your SpiderMedia bucket.

Input parameters:

- `limit` (number): Max results (default: 20)
- `offset` (number): Offset for pagination
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string): Workspace name

### `get_video_status` (~101 tokens)

Get processing status for a video (encoding, ready, failed).

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `video_id` (string, required): Video ID
- `workspace` (string): Workspace name

### `get_media_stats` (~92 tokens)

Get media storage statistics (file counts, storage used, by type).

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string): Workspace name

### `video_to_scroll_sequence` (~826 tokens)

Build a scroll-linked image-sequence hero from a video URL, end-to-end.

One call replaces the 5-step recipe: upload video -> submit extract_frames -> poll -> build block -> update page.
Extracts numbered WebP frames from the source video (ffmpeg, ~7x smaller than raw),
uploads them to the client's SpiderMedia bucket with a deterministic pattern
(frame_{0001..NNNN}.webp), then injects a 'sys-scroll-sequence' component block
into the target page AS A DRAFT.

\**Never auto-publishes.** After this tool returns, call:
  1\. content_deploy_site_preview  (review at preview-{hash}.sites.spideriq.ai)
  2\. content_deploy_site_production (with confirm_token)

When to use:
\- Agent received "add a scroll-sequence hero from this video" request
\- Video is at a public URL (SpiderMedia, di-atomic, or public http/https)
\- Target page already exists (use content_create_page first if not)

Frame-count strategies (pick one):
\- strategy='target_frames' + target_frames=N  — exact N frames spread across full duration (most common)
\- strategy='fps' + fps=N                      — sample at N frames/second
\- strategy='duration_fps' + fps + duration_seconds — clip + sample

Returns: manifest {base_url, pattern, count}, the inserted block JSON, and the new draft page version ID.

Input parameters:

- `background_color` (string): Hex color painted before frames load (default: #ffffff)
- `canvas_height` (number): Canvas render height, 240-1080 (default: 720)
- `canvas_width` (number): Canvas render width, 320-1920 (default: 1280)
- `dry_run` (boolean): If true, returns block JSON without touching the page (default: false)
- `duration_seconds` (number): Clip duration in seconds (1-120). Required if strategy=duration_fps
- `fps` (number): Sample FPS (1-60). Required if strategy=fps or duration_fps
- `output_format` (string): Frame format (default: webp — half the bytes of jpeg at same quality)
- `output_quality` (number): Encoder quality 50-95 (default: 80)
- `output_width` (number): Output frame width 320-1920 (default: 1280)
- `page_slug` (string, required): Target page slug — MUST already exist. Use content_create_page first if not.
- `poll_interval_seconds` (number): Poll interval in seconds (0.5-10, default: 2)
- `poll_timeout_seconds` (number): Max seconds to wait for extract_frames (30-900, default: 300)
- `position`: Where to insert: "append" (default), "prepend", {index: N}, {before: slug}, or {after: slug}
- `preload_strategy` (string): progressive (default) loads ±15 frame window; all pre-loads everything
- `priority` (number): Job priority 0-10 (default: 5)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `scroll_distance_vh` (number): Viewport heights to scroll through full sequence, 200-800 (default: 400)
- `strategy` (string): Frame-count strategy (default: target_frames)
- `target_frames` (number): Exact frame count (10-600). Required if strategy=target_frames. Default: 120
- `video_url` (string, required): Source video URL (SpiderMedia, di-atomic, or public http/https)
- `workspace` (string): Workspace name (default: "default")

### `content_override_section` (~579 tokens)

Override a site section (header, footer, hero, sidebar, etc.) — or the blog listing / single-post templates — for this client.

Param-name compatibility (the older templates.ts duplicate of this tool was merged here 2026-05-20 — both naming conventions work):
\- Canonical:  { section_slug, liquid_source }
\- Legacy:     { section, liquid }
Pass either pair. If both are supplied, the canonical names win.

When to use this instead of template_upsert:
\- You want to customize the header, footer, blog listing, or another named section just for this client
\- You have Liquid source and know the section slug
\- You don't want to touch layouts or individual page templates

Section slugs are the filename (without .liquid) under themes/default/sections/ — the common ones are
"header", "footer", "hero". The tool writes to sections/{slug}.liquid in the client's template override KV.

Special slugs that target top-level templates instead of sections/:
  "blog-listing" → templates/blog.liquid       (the /blog index)
  "blog-post"    → templates/blog-post.liquid  (single /blog/{slug} pages)
  "layout"       → layout/theme.liquid         (the outer HTML shell)
  "head"         → snippets/head.liquid        (the <head> contents)

There is no "dm-blog-listing" or other branded blog component — the blog UI is template-based, not block-based.
Use this tool (or template_upsert) to restyle it; do NOT try to PATCH a content_components row for the blog.

Use content_get_section_source(slug) first if you want to see the current override or know whether one exists.

Input parameters:

- `liquid` (string): Legacy alias for liquid_source (templates.ts duplicate compat). Pass either one.
- `liquid_source` (string): Canonical: full Liquid template source for the section. Will overwrite any existing override for this slug.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `section` (string): Legacy alias for section_slug (templates.ts duplicate compat). Pass either one.
- `section_slug` (string): Canonical section identifier — common values: "header", "footer", "hero". Special: "blog-listing", "blog-post", "layout", "head". No .liquid suffix.
- `theme` (string): Theme name (default: "default"). Usually leave as default.
- `workspace` (string): Workspace name (default: "default").

### `content_apply_layout_preset` (~344 tokens)

Apply a named layout preset to this client's site by writing layout/theme.liquid.

When to use this instead of template_upsert:
\- You want "blank" (no header/footer), "minimal" (footer only), "landing" (header only),
  "chromed" (edge-to-edge main), or "default" layouts without writing Liquid yourself
\- You want to quickly test "what does the site look like with no global header?"
\- You don't have Liquid source for a layout — you just want a sensible starting point

Available presets:
  "default"  — header + main + footer (standard; matches bundled theme)
  "blank"    — no header, no footer; full-page content
  "minimal"  — footer only, no header
  "landing"  — header only, no footer (marketing-landing chrome; from merged templates.ts duplicate, 2026-05-20)
  "chromed"  — header + footer, but main is edge-to-edge (no container padding)

After applying, customize individual sections with content_override_section().

Input parameters:

- `preset` (string, required): Layout preset name. One of: default, blank, minimal, chromed, landing
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `theme` (string): Theme name (default: "default").
- `workspace` (string): Workspace name (default: "default").

### `content_get_section_source` (~322 tokens)

Get the current Liquid source for a named section (header, footer, hero, etc.).

Param-name compatibility (templates.ts duplicate merged here 2026-05-20):
\- Canonical:  { section_slug }
\- Legacy:     { section }

When to use this instead of template_get:
\- You want to see "what Liquid is this client currently rendering for the header?"
\- You want to check whether an override exists for a section before writing one
\- You want to copy the current source as a starting point for modification

Returns:
\- If client has an override: returns the override source with origin="client_override"
\- If client has no override: returns origin="theme_default" with instructions. The bundled theme
  default source itself lives in the public starter kit, not the API — see SpiderIQ/SpiderPublish repo.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `section` (string): Legacy alias for section_slug (templates.ts duplicate compat). Pass either one.
- `section_slug` (string): Canonical section identifier — common values: "header", "footer", "hero". Special: "blog-listing", "blog-post", "layout", "head". No .liquid suffix.
- `workspace` (string): Workspace name (default: "default").

### `component_update_and_propagate` (~688 tokens)

Update a component's HTML/CSS/props/etc. AND repoint every consuming page to the new version, in one atomic call.

When to use this instead of component_update:
\- The component is referenced from multiple pages and you want all of them to pick up the change
\- You want a single confirm_token covering the component + all page mutations (instead of one per page)
\- You want staged rollout — pass `pages: ["home"]` to update the component everywhere but only repoint the home page; other pages keep referencing the old version

How it works:
1\. Call with `dry_run: true` — returns `affected_pages` (what would change) + a `confirm_token`
2\. Inspect the preview; if it's right, call again with `confirm_token: "cft_..."`
3\. The service bumps semver (default patch; also supports minor / major), writes a new published
   component row, and UPDATEs blocks on every affected page's `content_pages.blocks` JSONB
4\. Never auto-deploys the tenant KV. Block-level page updates render live via the content API on next request.
   Only run deploy_site_preview → deploy_site_production if you ALSO changed templates/theme/config.

Pages filter semantics:
\- omit `pages` or set null → propagate to every consuming page (default, matches "update everywhere" intent)
\- pass `["home", "pricing"]` → only those pages get the new version pin; other consumers keep the old pin

Field semantics:
\- At least one of html_template / css / js / props_schema / default_props / dependencies / name / description must be set
\- Inline `<style>` tags in html_template are rejected — put CSS in the css field
\- Dependencies validated against the Tier-3 CDN allowlist

Input parameters:

- `bump` (string): How to bump semver from current version. Default: patch.
- `confirm_token` (string): Token from a prior dry_run. Consume to perform the mutation.
- `css` (string): New CSS (injected via Shadow DOM at render time).
- `default_props` (object): New default prop values.
- `dependencies` (array): CDN library dependency keys (Tier 3). Validated against allowlist.
- `description` (string): Update description.
- `dry_run` (boolean): Preview mode — returns affected_pages + confirm_token without mutating. Default: false.
- `html_template` (string): New HTML template. Inline <style> tags will be rejected.
- `js` (string): New JS (Tier 2 scoped hydration).
- `name` (string): Update display name.
- `pages` (array): Limit propagation to these page slugs. Omit to propagate to every consuming page.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `props_schema` (object): New JSON Schema for prop validation.
- `slug` (string, required): Component slug (e.g. "hero", "pricing-cards"). Must already be published for this client.
- `workspace` (string): Workspace name (default: "default").

### `component_rollback` (~428 tokens)

Roll a component back to an earlier version's content. Creates a new published version
(so the forward audit trail stays intact) and repoints every consuming page to it.

When to use:
\- component_update_and_propagate went wrong and you need to unroll it
\- You want to revert to a known-good version without manually re-entering the old HTML/CSS
\- You want staged rollback — pass pages=["home"] to only revert the home page's pin

How it works:
1\. Call with dry_run=true — returns a confirm_token for the rollback action
2\. Inspect preview; if right, call again with confirm_token
3\. Service fetches target_version's content, creates a new published version with a fresh semver
   (bumped from the CURRENT version, default patch), and updates consuming pages' blocks to pin it
4\. Block-level page content renders live on next request — no tenant deploy needed

Pairs with component_update_and_propagate — the gate actions are distinct ("component_rollback"
vs "component_update_and_propagate") so a token issued for one can't be consumed by the other.

Input parameters:

- `bump` (string): How to bump the NEW version that gets the old content. Default: patch.
- `confirm_token` (string): Token from a prior dry_run.
- `dry_run` (boolean): Preview mode. Default: false.
- `pages` (array): Limit repoint to these page slugs. Omit for all.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string, required): Component slug to roll back.
- `target_version` (string, required): Version to restore (e.g. "1.0.3"). Must exist — check list_component_versions first.
- `workspace` (string): Workspace name (default: "default").

### `upload_local_file` (~342 tokens)

Upload a single local file to SpiderMedia.

Reads the file from disk, sniffs content-type from the extension, and POSTs
multipart to /dashboard/content/media/upload-batch. Server enforces weight
policy (500 KB/file for scroll-sequences/*, 20 MB otherwise; video/* gets
500 MB). Returns {public_url, key, size, content_type}.

Filenames: pass preserve_filename=true for deterministic storage keys
(scroll-sequences that consume {base_url, pattern, count}). Default false
keeps the legacy YYYYMMDD_HHMMSS_ prefix. Requires LLM11 SpiderMedia
backend 2026-04-18+ when preserve_filename=true.

Allowed extensions: webp, jpg, jpeg, png, gif, pdf, mp4, webm, mov.

Input parameters:

- `filename` (string): Rename the file on upload (default: use the local basename)
- `folder` (string): Target folder in the bucket, e.g. 'scroll-sequences/hero' or 'migrations/homepage'
- `local_path` (string, required): Absolute or cwd-relative path to the file on disk
- `preserve_filename` (boolean): If true, storage key is {folder}/{filename} exactly (overwrites on collision). Default false.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string): Workspace name (default: "default")

### `upload_local_directory` (~489 tokens)

Upload all matching files from a local directory to SpiderMedia.

Walks the directory (recursive), sniffs content-type, uploads in a single
/media/upload-batch request (up to 500 MB total for general folders, 20 MB
for scroll-sequences/*). Returns {uploaded: [...], failed: [...], warnings}.

Scroll-sequence workflow:
\- Default folder rule: if `folder` starts with "scroll-sequences/", the tool
  auto-enables both `auto_optimize=true` (Sharp → WebP q75, max 1920px) and
  \`preserve_filename=true` (so frame_0001.webp lands at frame_0001.webp).
\- Override with explicit flags if needed.

Filtering: pass `pattern` as a simple glob (e.g. "frame_*.webp") to filter
the dir; default is all allowed extensions. Allowed: webp, jpg, jpeg, png,
gif, pdf, mp4, webm, mov.

Sharp is an optional peer dep. If missing, auto_optimize silently falls back
to uploading originals (which may then hit server hard ceilings).

Input parameters:

- `auto_optimize` (boolean): Run Sharp locally before upload (WebP q75, max 1920px). Default: true for scroll-sequences/*, false otherwise.
- `folder` (string): Target folder in the bucket. For scroll-sequences use 'scroll-sequences/<name>'.
- `local_dir` (string, required): Absolute or cwd-relative path to the directory on disk
- `max_width` (number): When optimizing, max image width (default 1920)
- `pattern` (string): Optional glob pattern (e.g. "frame_*.webp"). Matched against filename and relative path.
- `preserve_filename` (boolean): Deterministic storage keys. Default: true for scroll-sequences/*, false otherwise.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `quality` (number): When optimizing, WebP quality 1-100 (default 75)
- `workspace` (string): Workspace name (default: "default")

### `directory_list_categories` (~147 tokens)

List every directory category for the current tenant (includes empty ones).

Returns {categories: [{id, name, slug, description, listing_count, city_count, seo_title_template, seo_description_template, ...}], total, page, page_size}.

Input parameters:

- `page` (number)
- `page_size` (number)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string): Workspace name (default: "default")

### `directory_create_category` (~238 tokens)

Create a directory category. SEO templates accept {category}, {city}, {listing} placeholders.

Example: {name: "Plumbers", seo_title_template: "Best {category} in {city} | Acme Directory"}.

Input parameters:

- `data_source` (object): Config for future SpiderMaps sync (job_type, query_filter, ...)
- `description` (string)
- `icon` (string)
- `name` (string, required)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `seo_description_template` (string): Supports {category}, {city}, {listing}
- `seo_title_template` (string): Supports {category}, {city}, {listing}
- `slug` (string): URL slug (auto-generated from name if omitted)
- `sort_order` (number)
- `template` (object): Per-category template config JSONB
- `workspace` (string)

### `directory_get_category` (~97 tokens)

Get a single category plus every city that has published listings in it.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string, required)
- `workspace` (string)

### `directory_update_category` (~158 tokens)

Update category fields. Pass only the fields you want to change.

Input parameters:

- `data_source` (object)
- `description` (string)
- `icon` (string)
- `name` (string)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `seo_description_template` (string)
- `seo_title_template` (string)
- `slug` (string, required)
- `sort_order` (number)
- `template` (object)
- `workspace` (string)

### `directory_delete_category` (~94 tokens)

Delete a directory category and all its listings (cascade).

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string, required)
- `workspace` (string)

### `directory_list_listings` (~154 tokens)

List directory listings. Filter by category, city, status.

Use this to verify what an IDAP dump wrote, or to audit a category before publishing changes.

Input parameters:

- `category_slug` (string)
- `city` (string)
- `page` (number)
- `page_size` (number)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `status` (string): draft | published | archived (default published)
- `workspace` (string)

### `directory_upsert_listing` (~288 tokens)

Create or update a single listing in a category. Upsert keyed on (category, slug).

For bulk work (IDAP dumps, SpiderMaps job output), use directory_bulk_upsert_listings instead — it's one call vs N.

Input parameters:

- `address` (string)
- `category_slug` (string, required)
- `city` (string)
- `country` (string)
- `data` (object): Free-form JSONB — hours, amenities, images, whatever
- `description` (string)
- `email` (string)
- `latitude` (number)
- `longitude` (number)
- `name` (string, required)
- `phone` (string)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `rating` (number)
- `review_count` (number)
- `slug` (string): Auto-generated from name if omitted
- `source_job_id` (string): SpiderIQ job UUID that produced this listing
- `state` (string)
- `status` (string): draft | published | archived (default published)
- `website` (string)
- `workspace` (string)

### `directory_bulk_upsert_listings` (~228 tokens)

Import many listings into a category in one transaction. Max 5000 per call.

Primary path for IDAP dumps + SpiderMaps job outputs. Each listing accepts the
same fields as directory_upsert_listing. Upsert keyed on (category, slug);
missing slugs auto-generate from name.

Returns {upserted, failed, affected_cities: ["city-slug-1", ...], failures}.
Refreshes category counts + city_stats materialized view on success.

Input parameters:

- `category_slug` (string, required)
- `listings` (array, required): Array of {name, slug?, city, state?, description?, phone?, email?, website?, rating?, review_count?, address?, latitude?, longitude?, data?, status?, source_job_id?}
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `directory_import_from_idap` (~338 tokens)

Populate a directory category from the tenant's IDAP data
(norm_cli_*.businesses). norm_cli_* is the canonical store for every
business SpiderIQ has seen for this tenant (SpiderMaps + SpiderSite +
SpiderCompanyData + SpiderPeople merged). This reads directly — no
scheduler, no sync pipeline, no external call.

Agent re-runs this tool whenever they want to refresh the directory.

Filters (all optional): category_filter matches the categories[] array,
country_code exact (uppercase), city is ILIKE substring, rating_min is
inclusive. limit caps at 5000 to align with bulk_upsert.

Returns {upserted, failed, source_rows, affected_cities, source_schema,
filter, failures?, hint?}. If the tenant has no norm_cli_* schema yet
(never ran SpiderMaps), hint explains the workaround.

Input parameters:

- `category_filter` (string): Match businesses.categories array member (e.g. "Plumber")
- `category_slug` (string, required)
- `city` (string): ILIKE substring match
- `country_code` (string): ISO-2 uppercase (e.g. "US")
- `limit` (number): Max rows to import (hard cap 5000)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `rating_min` (number): Inclusive lower bound on rating
- `workspace` (string)

### `directory_delete_listing` (~108 tokens)

Delete a listing by (category_slug, listing_slug). Refreshes city_stats.

Input parameters:

- `category_slug` (string, required)
- `listing_slug` (string, required)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_get_playbook` (~271 tokens)

Look up the canonical tool-sequence for a stated goal.

No intent → returns the index of all available playbooks (task keys + when-to-use summaries).
Intent = exact task key (e.g. "build_a_directory") → returns the full recipe.
Intent = natural language (e.g. "build a directory") → fuzzy-matches against task keys + when-text, returns up to 3 best matches ranked by score.

This is the fastest way for a fresh agent to find the right tool chain for a
given goal without scanning the full /content/help (~50 KB). Each recipe names
the exact tools to call, common variants, and anti-patterns.

Input parameters:

- `format` (string): yaml | json (default yaml — cheaper to parse for this shape)
- `intent` (string): Goal in natural language (e.g. "publish a blog post", "build a scroll hero") OR exact task key. Omit to get the index.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `content_duplicate_page` (~359 tokens)

Duplicate a page. Returns the new draft.

When to use:
\- Client wants a starting point that's similar to an existing page (faster than rebuilding from blocks)
\- You're applying a template by cloning master pages into the tenant (template gallery)
\- Internal A/B testing — fork a published page, edit copy, publish under a new slug

How it works:
1\. Reads the source page (must be owned by the caller's client; cross-tenant read refused 404)
2\. Picks a fresh slug (`{original}-copy`, `-copy-2`, `-copy-3`, ... lowest unused) unless `new_slug` is provided
3\. INSERTs a new content_pages row with status='draft', regenerated UUIDs on every block
4\. Title gets " (Copy)" appended so the dashboard list shows it distinctly
5\. Returns the full PageResponse

Not gated — duplicates create new rows rather than overwriting state, so no
confirm_token is required. Just call once and you get the new page.

Input parameters:

- `new_slug` (string): Optional flat slug for the duplicate. Auto-generated as `{original}-copy[-N]` if omitted. Must match `^[a-z0-9][a-z0-9-]*$` (no `/`).
- `page_id` (string, required): UUID of the page to duplicate.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string): Workspace name (default: "default").

### `content_duplicate_block` (~281 tokens)

Insert a deep copy of one block into the same page.

When to use:
\- Duplicating a CTA section to use in a different position on the same page
\- Cloning a tier-priced "feature card" inside a pricing-grid block
\- Building variations of the same section without rebuilding from scratch

How it works:
1\. Reads the source page; finds the block by id
2\. Deep-copies the block JSON, regenerates the block's id (fresh UUID)
3\. Inserts the copy at `position` ('before', 'after' default, or an int index)
4\. Returns the updated PageResponse with the new block in place

The page's status is unchanged (this doesn't unpublish a published page).

Input parameters:

- `block_id` (string, required): ID of the block to duplicate.
- `page_id` (string, required): UUID of the page.
- `position`: 'before' or 'after' (default) the source block, or an int index.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string): Workspace name (default: "default").

### `content_duplicate_post` (~161 tokens)

Duplicate a blog post. Returns the new draft with a fresh slug.

The body (Tiptap JSON), cover image URL, author, and tags all copy over.
Status is forced to 'draft' regardless of the source's state.

Input parameters:

- `new_slug` (string): Optional flat slug. Auto-generated if omitted.
- `post_id` (string, required): UUID of the post to duplicate.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string): Workspace name (default: "default").

### `content_duplicate_doc` (~146 tokens)

Duplicate a doc page. Copy lives as a sibling under the same parent
node in the docs tree (same parent_id), with a fresh slug + full_path.

Input parameters:

- `doc_id` (string, required): UUID of the doc to duplicate.
- `new_slug` (string): Optional flat slug. Auto-generated if omitted.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string): Workspace name (default: "default").

### `content_list_site_templates` (~341 tokens)

List SpiderIQ-curated site templates. Public read — no auth required.

When to use:
\- Client wants to see what starter sites are available before committing
\- Filtering for a specific industry (saas, agency, restaurant, ecommerce, portfolio,
  local-service, blog, event, landing) or use case (marketing, docs, blog, directory, personal)
\- Surfacing the featured set on a dashboard "browse templates" page

Each template carries:
\- slug (apply with content_apply_site_template)
\- name + description + industry + use_case + tags
\- preview_url (live preview at preview-XXX.sites.spideriq.ai)
\- preview_thumbnail_url (R2-hosted hero screenshot)
\- source_page_slugs[] (which pages get cloned on apply)
\- applied_count (popularity)

Input parameters:

- `industry` (string): saas | agency | restaurant | ecommerce | portfolio | local-service | blog | event | landing
- `is_featured` (boolean): Filter to is_featured templates only.
- `limit` (integer): Default 50.
- `offset` (integer)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `tag` (string): Filter to templates whose tags array contains this tag.
- `use_case` (string): marketing | docs | blog | directory | personal
- `workspace` (string): Workspace name (default: "default").

### `content_get_site_template` (~162 tokens)

Fetch a single site template by slug. Public read — no auth required.

Returns the full template detail including the list of pages, components, nav
locations, and settings keys that would be cloned on apply. Use this to preview
the impact before calling content_apply_site_template.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string, required): Template slug (e.g. "saas-landing", "restaurant-menu").
- `workspace` (string): Workspace name (default: "default").

### `content_apply_site_template` (~393 tokens)

Clone a site template into the current tenant. Phase 11+12 gated.

When to use:
\- New tenant just provisioned, agent wants to give them something to start from
\- Client picked a template from the gallery, agent wires it up
\- A/B testing different starter sites without rebuilding from blocks

How it works:
1\. Reads the template's source pages from the SpiderIQ-owned template-source tenant
2\. Clones each into the current tenant as status='draft' with fresh block UUIDs
3\. Copies navigation menus for header + footer (or whatever locations the template names)
4\. Copies whitelisted theme settings keys (primary_color, body_text_color, etc.)
5\. Bumps the template's applied_count for the leaderboard

Phase 11+12 flow:
\- First call with dry_run=true → returns {dry_run: true, preview, confirm_token, expires_at}
\- Inspect the preview (pages_to_create, settings_keys_to_apply)
\- Second call with confirm_token=<token> → returns {pages_created, nav_updated, settings_applied}
\- Cloned pages are drafts, NOT published. Review + publish individually, or use
  content_deploy_site to push the lot to production CF edge.

Input parameters:

- `confirm_token` (string): Phase 11+12: consume a prior preview token and apply for real.
- `dry_run` (boolean): Phase 11+12: preview the apply and receive a confirm_token without mutating.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string, required): Template slug to apply.
- `workspace` (string): Workspace name (default: "default").

### `content_create_site_template` (~653 tokens)

Register a NEW site-template catalog row so a built site/page becomes installable from the marketplace. Phase 11+12 gated. AUTHORING-ONLY.

Auth: needs super_admin OR a PAT scoped to a marketplace-AUTHORING brand
(clients.is_marketplace_authoring=TRUE — e.g. the demo-publish authoring account).
A normal tenant PAT gets 403. The source pages must already exist (published) on
source_client_id; this call just registers the catalog row that clones them on apply.

PAGE TEMPLATES: set is_single_page=true AND pass exactly ONE source_page_slug
(opt-in / thank-you / VSL / sales / …). The server enforces the single⇒1-slug CHECK.
Omit is_single_page (or false) + pass multiple slugs for a whole-site template.

Phase 11+12 flow: call once with dry_run=true → {dry_run, preview, confirm_token},
then again with confirm_token to actually create. Then content_update_site_template
can attach a preview image, and the row appears in the Studio templates gallery
(is_public=true).

Input parameters:

- `confirm_token` (string): Phase 11+12: consume a prior preview token and create for real.
- `description` (string)
- `dry_run` (boolean): Phase 11+12: preview + receive a confirm_token without mutating.
- `industry` (string)
- `is_featured` (boolean)
- `is_public` (boolean): Default true → visible in the gallery. Set false to stage a draft, flip true on review.
- `is_single_page` (boolean): TRUE = single-page "page template" (requires exactly one source_page_slug).
- `name` (string, required): Display name in the gallery.
- `preview_thumbnail_url` (string): Hero screenshot URL (host-allowlisted). Or attach later via content_update_site_template.
- `preview_url` (string): Live preview URL (host-allowlisted: R2 / curated stock).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `replication_prompt` (string)
- `slug` (string, required): Unique catalog slug, e.g. "opt-in-minimal".
- `source_client_id` (string, required): client_id (cli_… or UUID) whose published pages are the master copies to clone.
- `source_component_slugs` (array)
- `source_nav_locations` (array): Whole-site only; omit for page templates.
- `source_page_slugs` (array, required): Page slugs to clone on apply. For a page template: exactly ONE.
- `source_settings_keys` (array)
- `tags` (array)
- `use_case` (string): opt-in | thank-you | vsl | webinar | sales | pricing | coming-soon | 404 (page templates) — or a vertical for whole-site.
- `workspace` (string): Workspace name (default: "default").

### `content_update_site_template` (~368 tokens)

Patch an existing site-template catalog row (rename, attach a preview image, toggle is_public, retag, change source bindings, flip is_single_page). Phase 11+12 gated. AUTHORING-ONLY.

Auth: same as content_create_site_template (super_admin OR marketplace-authoring-brand PAT).
Commonly used right after content_create_site_template to set preview_thumbnail_url
from a content_upload_template_preview result, or to publish a staged draft
(is_public=true).

Phase 11+12 flow: dry_run=true → confirm_token → call again with confirm_token.
Only the fields you pass are changed.

Input parameters:

- `confirm_token` (string)
- `description` (string)
- `dry_run` (boolean)
- `industry` (string)
- `is_featured` (boolean)
- `is_public` (boolean)
- `is_single_page` (boolean)
- `name` (string)
- `preview_thumbnail_url` (string)
- `preview_url` (string)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `replication_prompt` (string)
- `slug` (string, required): Catalog slug to patch.
- `source_client_id` (string)
- `source_component_slugs` (array)
- `source_nav_locations` (array)
- `source_page_slugs` (array)
- `source_settings_keys` (array)
- `tags` (array)
- `use_case` (string)
- `workspace` (string): Workspace name (default: "default").

### `content_list_page_templates` (~390 tokens)

List SpiderIQ-curated SINGLE-PAGE templates (the Page Template catalog). Public read — no auth required.

When to use:
\- An agent or client needs a landing page, opt-in, thank-you, VSL, webinar, sales,
  coming-soon, 404, or pricing page and wants a proven starting point
\- ALWAYS prefer this over generating a page from scratch — clone-and-adapt is faster
  and more reliable than authoring Liquid blind ("adapt, don't generate")

Each template carries:
\- slug (clone with content_apply_page_template)
\- name + description + industry + use_case + tags
\- preview_url (live preview) + preview_thumbnail_url (R2 screenshot)
\- source_page_slugs[] — exactly ONE page (that's what makes it a page template)
\- applied_count (popularity)

This is the same catalog as content_list_site_templates, narrowed to is_single_page=true.
Use content_list_site_templates for WHOLE-SITE starter kits (multi-page).

Input parameters:

- `industry` (string): saas | agency | restaurant | ecommerce | portfolio | local-service | blog | event | landing
- `is_featured` (boolean): Filter to is_featured templates only.
- `limit` (integer): Default 50.
- `offset` (integer)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `tag` (string): Filter to templates whose tags array contains this tag.
- `use_case` (string): opt-in | thank-you | vsl | webinar | sales | pricing | coming-soon | 404
- `workspace` (string): Workspace name (default: "default").

### `content_get_page_template` (~185 tokens)

Fetch a single page template by slug. Public read — no auth required.

Returns the full detail including the ONE source page that gets cloned on apply,
its components, and any settings keys. Use this to preview a template before
calling content_apply_page_template. (A page template is a content_site_templates
row, so this resolves the same endpoint as content_get_site_template.)

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string, required): Page template slug (e.g. "opt-in-minimal", "vsl-classic").
- `workspace` (string): Workspace name (default: "default").

### `content_apply_page_template` (~395 tokens)

Clone a page template's single page into the current tenant. Phase 11+12 gated.

When to use:
\- A client/agent picked a page template and wants it added to their site
\- Building a funnel one page at a time (opt-in → thank-you → sales) from templates
\- You want a working page to ADAPT (edit copy/images/colors) instead of generating one

How it works:
1\. Reads the template's single source page from the SpiderIQ template-source tenant
2\. Clones it into the current tenant as status='draft' with fresh block UUIDs
3\. Applies any whitelisted theme settings the template carries

Phase 11+12 flow:
\- First call with dry_run=true → {dry_run: true, preview, confirm_token, expires_at}
\- Inspect preview.pages_to_create (one page)
\- Second call with confirm_token=<token> → {pages_created, settings_applied}
\- The cloned page is a DRAFT — review, adapt, then publish with content_publish_page
  (and run content_visual_check against the published URL per Agent Trust 5.1).

Same apply endpoint as content_apply_site_template; for a page template it clones
exactly one page.

Input parameters:

- `confirm_token` (string): Phase 11+12: consume a prior preview token and clone for real.
- `dry_run` (boolean): Phase 11+12: preview the apply and receive a confirm_token without mutating.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string, required): Page template slug to apply.
- `workspace` (string): Workspace name (default: "default").

### `content_list_marketplace_components` (~471 tokens)

Browse the SpiderIQ section library — ready-to-insert sections grouped by category. Public read, no auth.

When to use:
\- Filling out an existing page that needs a hero / pricing / FAQ block
\- Adding a sign-in / forgot-password / reset-password page (category=authentication)
\- Picking the right component shape before calling page_insert_section
\- Surfacing the gallery on a dashboard "browse sections" page

Categories (use `category` filter):
  hero, features, pricing, social-proof, content, forms, team, footer, header, cta, faq, authentication

The `authentication` category holds 3 designable sign-in bricks (spideriq/auth-login,
spideriq/auth-forgot-password, spideriq/auth-reset-password), each rendering a
\<spideriq-auth> custom element (CLOSED shadow DOM). Their props REQUIRE `auth_target`
("dashboard" = sign into the SpiderIQ dashboard; "site_members" = the tenant's own
members). These are a designable shell + integration contract — the real auth backends
are wired by Login Initiatives B/C; until then submit degrades gracefully. See the
content/help `build_a_login_page` task recipe for the full flow.

Each result carries:
\- slug + name + version (use slug + version for page_insert_section)
\- props_schema + default_props (validate before insert)
\- preview_thumbnail_url (designer-curated card art, R2)
\- marketplace_category + marketplace_featured + marketplace_description

Input parameters:

- `category` (string): hero | features | pricing | social-proof | content | forms | team | footer | header | cta | faq | authentication
- `is_featured` (boolean): Surface featured-only sections.
- `limit` (integer): Default 100.
- `offset` (integer)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `tag` (string): Filter to components whose tags array contains this tag.
- `workspace` (string): Workspace name (default: "default").

### `content_list_marketplace_bg_videos` (~237 tokens)

Browse the curated background-video library — 12 short looping clips across 6 categories. Public read, no auth.

When to use:
\- Picking a clip for a hero-video-bg or sys-bg-video block
\- Surfacing the catalog on a dashboard "browse bg videos" page

Categories: nature | city | abstract | food | tech | people

Each result carries: slug, name, description, r2_url, poster_url,
duration_seconds, loop_seconds, category, tags, is_featured.

Input parameters:

- `category` (string): nature | city | abstract | food | tech | people
- `is_featured` (boolean)
- `limit` (integer)
- `offset` (integer)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `tag` (string)
- `workspace` (string): Workspace name (default: "default").

### `content_get_marketplace_bg_video` (~98 tokens)

Fetch a single curated background video by slug. Public read.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string, required)
- `workspace` (string)

### `page_insert_section` (~529 tokens)

Insert a marketplace section into an existing page. Phase 11+12 gated.

When to use:
\- Adding a hero / pricing / FAQ block to a page the customer already has
\- Programmatic page assembly: list sections → preview → insert → publish

position semantics:
\- "end" (default) — append at the end of the blocks array
\- "start" — prepend
\- "before" / "after" — relative to anchor_block_id (REQUIRED when used)
\- integer — explicit 0-based index, clamped to [0, len(blocks)]

Phase 11+12 flow:
1\. Call with dry_run=true → returns {dry_run, preview, confirm_token, expires_at}
2\. Inspect the preview (insertion_index, new_block_id, blocks_count_before/after)
3\. Call again with confirm_token=<token> → mutates the page and returns the new block id

The inserted block is type='component' with the requested component_slug + props.
The page itself is NOT republished — call content_publish_page after if needed,
or content_deploy_site to push everything live.

Input parameters:

- `anchor_block_id` (string): Required when position is "before" or "after".
- `audit_level` (string): P5: include an `_audit` block on the success response (or `_rules` block on dry_run). 'all' (default for mutations) returns every finding so the agent sees scroll-sequence empty frames, missing requi…
- `component_slug` (string, required): Marketplace component slug (e.g. "hero-headline", "logo-cloud").
- `component_version` (string): Optional pinned version. Omit for latest published.
- `confirm_token` (string): Phase 11+12: consume a prior preview token.
- `dry_run` (boolean): Phase 11+12: preview the insertion without mutating.
- `page_id` (string, required): UUID of the target page.
- `position`: Where to place the new block. Default: "end".
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `props` (object): Component props matching the component's props_schema. Falls through default_props for omitted keys.
- `workspace` (string): Workspace name (default: "default").

### `marketplace_search` (~631 tokens)

Cross-table search across bg-videos / components / site-templates by AI-discovery axes (Phase D).

Use this BEFORE content_list_marketplace_components / content_list_marketplace_bg_videos when the user asks for an asset by intent ("a calm cinematic background video for a luxury hotel") rather than by category. The 4 universal axes (mood / palette / brand_fit / scene_type) plus per-asset agent_meta narrow the catalog by behaviour, not by component name.

Universal axes (controlled vocabulary, see marketplace_taxonomy.py):
\- mood: calm, energetic, bold, confident, dreamy, futuristic, urban, minimal, warm,
  sensory, editorial, professional, friendly, clear, technical, credible
\- palette: free-form (e.g. monochrome, deep-blue, cream, neutral-warm)
\- brand_fit: saas, agency, ecommerce, fintech, real-estate, hospitality, restaurant,
  wellness, healthcare, blog, publication, personal, tech, design, consulting,
  outdoor, lifestyle
\- scene_type: hero-bold, feature-grid, pricing-tiers, social-proof, faq-accordion,
  conversion-cta, navigation-header, navigation-footer, data-collection-form,
  editorial-content, team-grid (components); city-aerial, nature-landscape,
  abstract-motion, food-prep, people-lifestyle, tech-hardware (bg-videos);
  marketing-site, docs-site, directory-site, portfolio-site (site-templates)

Per-asset agent_meta (use marketplace_get_help for the full vocabulary):
\- bg-video: pace, time_of_day, weather, has_people, aspect_ratio, has_audio,
  music_tempo_bpm, transcript
\- component: interaction_pattern, trigger_kind, placement, motion_safety,
  conversion_strategy
\- site-template: page_count, has_blog, has_pricing, has_directory, has_booking,
  conversion_strategy, style_aesthetic, component_set

Restrict the search to specific asset types via asset_types — e.g. asset_types=["bg_video"] when you need just a hero background, ["component","site_template"] when you're planning a full page.

Public read, no auth required.

Input parameters:

- `agent_meta` (object): Key/value filters against agent_meta JSONB (e.g. {"pace":"slow","time_of_day":"night"}).
- `asset_types` (array): Restrict to specific marketplace tables. Omit for all 3.
- `brand_fit` (array): Industry-vertical fit tags.
- `limit` (integer): Default 20.
- `mood` (array): Mood values (any-of match against the column).
- `palette` (array): Palette tokens.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `scene_type` (string): Single scene_type filter.
- `workspace` (string)

### `list_data_sources` (~319 tokens)

List the 9 registered content data sources that drive kind='dynamic' components (Phase D).

Use this to discover the available source_id values when an agent is configuring a Dynamic block (List, Item Details, etc.). The registry includes:
\- 4 internal CMS collections: posts, authors, categories, tags
\- 4 IDAP collections: idap.countries → idap.cities → {idap.streets, idap.businesses}
  (hierarchical — pass --parent to walk the tree)
\- 1 singleton: idap.lead (per-request visitor lead context; only Item Details accepts it)

Each source carries:
\- id (use as the source_id in DataBinding / SourceBinding)
\- label + description (human-readable)
\- parent_id (NULL for top-level; set for hierarchical children)
\- is_collection (false for singletons like idap.lead — only item_details binds these)
\- schema_json.fields[] (filterable + sortable per field)
\- schema_json.filters[] (named filter helpers)

Public read.

Input parameters:

- `parent_id` (string): Filter to children of this source (e.g. "idap.countries" returns idap.cities).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `list_data_source_items` (~421 tokens)

Fetch live items from a registered content data source — the same door a kind='dynamic' component binds to (Live Data). Sibling of list_data_sources.

Use this to PREVIEW what a dynamic component will render, or to discover a source's row shape before wiring a component's `sources`. It returns real, published, tenant-scoped records.

v1 sources: posts, authors, categories, tags, changelog. (idap.* collections → 501 Phase 2; a singleton like idap.lead → 422 — those reach /lp/ templates as `lead`.)

Filtering: pass `filter` keys matching the source's filterable fields (discover via list_data_sources), e.g. {"tag":"news"} on posts. `sort` is a single field with optional ":asc"/":desc" (or "-field"); `limit` (1-500) + `offset` paginate; `fields` trims the returned keys.

Returns { items: [...], total, source_id }. Public read (X-Content-Domain tenant scope).

Input parameters:

- `fields` (array): Project to these field ids only (default: all).
- `filter` (object): Filter by the source's filterable fields, e.g. {"tag":"news","category":"..."}.
- `limit` (integer): Max rows (default 50).
- `offset` (integer): Pagination offset (default 0).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `sort` (string): Sort field with optional ':asc'/':desc' (or '-field'), e.g. '-published_at'.
- `source_id` (string, required): Registered source id (list_data_sources). v1: posts, authors, categories, tags, changelog.
- `workspace` (string)

### `set_component_kind` (~313 tokens)

Set the 4-class behavioural taxonomy on a component: kind ∈ {static, interactive, dynamic, extension}. Phase 11+12 gated.

When to use:
\- Curating a freshly-created custom component into the right marketplace tab
\- Reclassifying a legacy 'static' component as 'interactive' once you add JS
\- Promoting a Dynamic component (kind='dynamic' requires block_type + sources to already be set on the row, or this PATCH 400s on the DB CHECK constraint)

The DB CHECK constraints (migration 174) enforce kind invariants — setting kind='dynamic' on a row missing block_type returns 400 with a specific constraint message. Phase A schemas (marketplace_taxonomy.py) define the strict enum.

dry_run=true (default when neither flag set) returns a preview envelope with a confirm_token; pass confirm_token=<token> to commit.

Input parameters:

- `component_id` (string, required): UUID of the component.
- `confirm_token` (string): Consume a prior preview token to commit.
- `dry_run` (boolean): Default true — preview without mutating.
- `kind` (string, required): 4-class behavioural taxonomy (Phase A).
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `set_component_agent_meta` (~386 tokens)

Patch the agent-discovery axes on a component: universal axes (mood / palette / brand_fit_tags / scene_type) + per-component agent_meta JSONB. Phase 11+12 gated.

Use this to make a component findable by intent through marketplace_search. Strict enum validation at the API boundary — unknown values 422 with the accepted vocabulary listed.

agent_meta keys (ComponentAgentMeta, extra="forbid"):
\- interaction_pattern: static, click, hover, scroll, timer, form, drag
\- trigger_kind: page-load, scroll-into-view, click, hover, exit-intent,
  timer-fixed-date, timer-elapsed, form-submit, geo-match, none
\- placement: above-fold, below-fold, side-rail, modal, toast, footer, header, any
\- motion_safety: bool (TRUE if component honours prefers-reduced-motion)
\- accessibility_notes: string ≤ 1000 chars
\- conversion_strategy: primary-cta, secondary-cta, trust, scarcity, social-proof,
  education, navigation, none

Pass only the fields you want to change — exclude_unset semantics. Defaults dry_run=true.

Input parameters:

- `agent_meta` (object): ComponentAgentMeta keys (see description for vocabulary).
- `brand_fit_tags` (array)
- `component_id` (string, required)
- `confirm_token` (string)
- `dry_run` (boolean): Default true.
- `mood` (array)
- `palette` (array)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `scene_type` (string)
- `workspace` (string)

### `set_bg_video_agent_meta` (~403 tokens)

Patch agent-discovery axes + agent_meta on a bg-video catalog row (super_admin). Phase 11+12 gated.

Same shape as set_component_agent_meta, but BgVideoAgentMeta has different keys:
\- pace: slow, medium, fast (slow=meditative, medium=narrative, fast=energetic)
\- time_of_day: dawn, day, dusk, night
\- weather: clear, cloudy, rain, snow, fog, stormy (NULL = indoor / abstract)
\- has_people: bool (TRUE if humans visible)
\- aspect_ratio: 16:9, 9:16, 1:1, 4:3, 21:9
\- has_audio: bool
\- music_tempo_bpm: 20–300 (only meaningful when has_audio=true)
\- transcript: ≤ 2000 chars (accessibility + agent context)

The bg-video catalog is global — every tenant sees the same rows — so this is super_admin only on the server. replication_prompt also accepted for free-form curator notes.

Defaults dry_run=true.

Input parameters:

- `agent_meta` (object): BgVideoAgentMeta keys (see description).
- `brand_fit_tags` (array)
- `confirm_token` (string)
- `dry_run` (boolean): Default true.
- `mood` (array)
- `palette` (array)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `replication_prompt` (string): Optional free-form curator prompt (≤ 4000 chars).
- `scene_type` (string)
- `slug` (string, required): Bg-video slug (e.g. "alpine-wildflowers").
- `workspace` (string)

### `set_site_template_agent_meta` (~319 tokens)

Patch agent-discovery axes + agent_meta on a site_template catalog row (super_admin). Phase 11+12 gated.

SiteTemplateAgentMeta keys:
\- page_count: 1–200 (number of pages the template ships with)
\- has_blog: bool
\- has_pricing: bool
\- has_directory: bool (programmatic SEO target)
\- has_booking: bool (SpiderBook integration)
\- conversion_strategy: same vocabulary as ComponentAgentMeta
\- style_aesthetic: minimal, bold, editorial, playful, premium, technical, brutalist, soft
\- component_set: array of component slugs the template ships with (≤ 100)

The site-template catalog is global — super_admin only.

Defaults dry_run=true.

Input parameters:

- `agent_meta` (object): SiteTemplateAgentMeta keys (see description).
- `brand_fit_tags` (array)
- `confirm_token` (string)
- `dry_run` (boolean): Default true.
- `mood` (array)
- `palette` (array)
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `replication_prompt` (string)
- `scene_type` (string)
- `slug` (string, required): Site-template slug (e.g. "saas-minimal").
- `workspace` (string)

### `marketplace_suggest_agent_meta` (~466 tokens)

Suggest mood / palette / brand_fit_tags / scene_type / agent_meta for one marketplace asset using the SpiderGate V2 inference engine.

Two-step apply pattern (recommended):
1\. Call `marketplace_suggest_agent_meta` to get a SuggestEnvelope with proposed values + per-key confidence (high / medium / low → action: auto_apply | review | drop).
2\. Review the envelope. For values you trust, call the matching apply tool:
   \- bg_video → set_bg_video_agent_meta
   \- component → set_component_agent_meta
   \- site_template → set_site_template_agent_meta
   The apply tools are gated (dry_run=true default + confirm_token). They mark the row `agent_meta_source='llm_inferred'` so future bulk re-runs can distinguish machine suggestions from human curation.

Anti-hallucination: the engine validates proposed values against the locked Pydantic enums BEFORE returning. Off-vocab values are dropped and listed in `dropped_keys` so you can audit suggestions that didn't make the cut. Universal `palette` is intentionally open-vocabulary.

Confidence-gated apply (locked thresholds 0.75 / 0.55):
\- action="auto_apply" → safe to apply directly (≥0.75 + vocab match)
\- action="review"     → human eyeball recommended (0.55–0.75)
\- action="drop"       → engine already dropped these — don't apply

Cost: <$0.01 per call (Opus 4.7 via the spideriq/vision or spideriq/lead-analysis task aliases). Vision is used for bg-videos when poster_url is present; text-only otherwise.

Super_admin only.

Input parameters:

- `asset_type` (string, required): Which marketplace table to suggest for.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `slug` (string, required): Asset slug (e.g. "alpine-wildflowers", "hero-bold-default", "agency-minimal").
- `workspace` (string)

### `marketplace_form_test_submit` (~442 tokens)

Test-fire a submission against a dynamic form block. NOT the production submit path — real form submissions come from a visitor's browser via POST /content/forms/{form_id}/submit (no auth). This MCP tool exists so agents can validate a form's wiring during authoring + smoke-test before publishing.

When to use:
\- After authoring a new form block, fire a synthetic submission to confirm validation + persistence work.
\- After changing fields / submit_url / fallback_idap_lead, verify the new behaviour without leaving the editor.
\- Debugging cross-tenant isolation: pick a form_id from one tenant, attempt to write under another — server returns 404, never silently misroutes.

Cross-tenant isolation: form_id is the composite "<page_uuid>:<block_uuid>". The server resolves client_id ONLY from the page row; no tenant signal is accepted in the URL or body. A form_id from a different tenant simply 404s.

Validation:
\- Required fields must be present + non-empty.
\- Field type drives coercion (number → float, checkbox → bool, select/radio → must match options).
\- Unknown field names rejected with 400.

Returns the full FormSubmitResponse: ok, submission_id (when persisted), success_action ('redirect' | 'message' | 'modal'), success_redirect_url, success_message, webhook_status (when submit_url is configured).

Input parameters:

- `form_id` (string, required): Composite form id "<page_uuid>:<block_uuid>". Both halves UUIDs.
- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `request_id` (string): Optional retry-idempotency token. Combined with the resolved client_id, dedups duplicate test-fires within a 24h window.
- `submission` (object, required): Field name → value map. Validated against the form's props.fields list at the server. Extra fields rejected.
- `workspace` (string)

### `content_audit_links` (~276 tokens)

Walk every published page's blocks + navigation menus and validate internal links against the published-page roster + active redirects.

Returns a structured report:
  \- valid_count: number of links that resolved correctly
  \- broken: [{path, source, reason}] — each broken link with its tree position
  \- proposed_redirects: [{from, to, status_code}] — heuristic suggestions
  \- known_redirects: [{from, to, status_code}] — already-active redirects

The "source" field is JSONPath-shaped (e.g. "page:home/block[2].url",
"navigation:header[3]") so callers can navigate straight to the offending
position. Pre-push hook in the SpiderPublish extension uses this to surface
broken links as inline diagnostics before the push fan-out runs.

Use BEFORE deploying a content change to catch /en/* legacy URLs, renamed
slugs, or post-merge orphans. Idempotent — safe to run repeatedly.

Input parameters:

- `project` (string): Optional project — a website inside the workspace (proj_xxx) — to scope this call to. Sent as the X-Project-Id header. If omitted, the spideriq.json / SPIDERIQ_PROJECT_ID binding (or the workspace de…
- `workspace` (string)

### `list_projects` (~96 tokens)

List the projects (websites) in the current workspace. Each project has an `id` (proj_xxx) that you pass as the optional `project` argument of any content/template tool — or bind via `spideriq use <workspace> --project <proj_>` — to scope content operations to that website.

Input parameters:

- `workspace` (string): Credentials slot (default "default") in ~/.spideriq/credentials.json.

### `create_project` (~99 tokens)

Create a new project (website) in the current workspace. Returns the new project including its `proj_` id. May return 403 with an upgrade CTA if the workspace is already at its plan's project cap (max_deployed_sites).

Input parameters:

- `name` (string, required): Human-facing project name.
- `slug` (string): Optional URL-safe slug (auto-derived from name when omitted).
- `workspace` (string): Credentials slot (default "default").

### `list_recipes` (~97 tokens)

List all SpiderPublish workflow recipes shipped in @spideriq/skills.
Returns name, description, and kind (rule | recipe | config) for each
manifest entry. Call get_recipe(name) to read full content.

Use this when the user asks "how do I X?" — the recipe index points
you at a known-good workflow markdown.

Input parameters:

- `kind` (string): Filter to a single kind (default: all kinds)

### `get_recipe` (~90 tokens)

Fetch the full markdown content of a SpiderPublish recipe (or rule)
from @spideriq/skills. Pass the logical name from list_recipes.

Returns the recipe text verbatim — paste-able into the working
context, or use as a reference while implementing.

Input parameters:

- `name` (string, required): Logical name (e.g. "clone-a-site", "build-a-homepage", "claude-md")

## Diagnostics

Captured diagnostic sections: Provenance, Vulnerabilities, Dependencies. The full working is on the page: https://verifymcp.io/servers/ai-spideriq-publish/spideriq-mcp-publish#diagnostics

## Score history

- 2026-08-03: 48
- 2026-08-02: 48
- 2026-08-01: 12
- 2026-07-31: 35
- 2026-07-30: 35
- 2026-07-28: 18
- 2026-07-27: 35

## Links

- npm package: https://www.npmjs.com/package/@spideriq/mcp-publish
- Socket report: https://socket.dev/npm/package/@spideriq/mcp-publish
- Changelog RSS feed: https://verifymcp.io/servers/ai-spideriq-publish/spideriq-mcp-publish/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/ai-spideriq-publish/spideriq-mcp-publish/changelog.json
- HTML version of this page: https://verifymcp.io/servers/ai-spideriq-publish/spideriq-mcp-publish
