# ClicksPal MCP documentation

> Generated from the ClicksPal desktop tool registry. Regenerate with node scripts/sync-mcp-docs.mjs.

## Before connecting

Install and activate ClicksPal. Its MCP bridge uses the app’s binary; no separate Node installation is required for the bridge. Website builds still require the repository’s own tools and dependencies. AI and research accounts remain separate.

ClicksPal is the owner’s local SEO workbench: audits, keyword research, a content calendar, and build agents that write pages, tools and articles into a website repository. These tools drive the running app; the window shows the same state live.

Start with status. Ids come from status, jobs_list, calendar_get and audits_list.
Long work (audits, builds, research, shipping) runs in the app and returns at once: call wait, then read the result. One audit runs at a time and a website runs one task of a kind.
Builds stay in an isolated worktree until pipeline_ship or job_publish, which commit and deploy the live website — call those only when the owner asked to ship.
Tools marked as spending use the owner’s saved DataForSEO budget. Missing measurements are unknown (null), never zero; do not invent demand.
A task or setup in needs-input is waiting on a question: status lists them under needsYou. Ask the owner unless they already told you the answer.

## Connect

### Claude Code

**One click:** in ClicksPal, open **MCP** in the sidebar and press **Add** next to your agent. If you move the app, press **Update**.

**Or run** this once. On Windows, replace `YOU` with your Windows user name, or copy your exact command from ClicksPal’s MCP page.

Mac:

```bash
claude mcp add --scope user clickspal -e ELECTRON_RUN_AS_NODE=1 -- /Applications/ClicksPal.app/Contents/MacOS/ClicksPal /Applications/ClicksPal.app/Contents/Resources/mcp.cjs
```


Windows (replace YOU with your Windows user name):

```bash
claude mcp add --scope user clickspal -e ELECTRON_RUN_AS_NODE=1 -- 'C:\Users\YOU\AppData\Local\Programs\ClicksPal\ClicksPal.exe' 'C:\Users\YOU\AppData\Local\Programs\ClicksPal\resources\mcp.cjs'
```


**Check:** Start a new Claude Code session; `claude mcp list` should show `clickspal`.

### Codex

**One click:** in ClicksPal, open **MCP** in the sidebar and press **Add** next to your agent. If you move the app, press **Update**.

**Or run** this once. On Windows, replace `YOU` with your Windows user name, or copy your exact command from ClicksPal’s MCP page.

Mac:

```bash
codex mcp add clickspal --env ELECTRON_RUN_AS_NODE=1 -- /Applications/ClicksPal.app/Contents/MacOS/ClicksPal /Applications/ClicksPal.app/Contents/Resources/mcp.cjs
```


Windows (replace YOU with your Windows user name):

```bash
codex mcp add clickspal --env ELECTRON_RUN_AS_NODE=1 -- 'C:\Users\YOU\AppData\Local\Programs\ClicksPal\ClicksPal.exe' 'C:\Users\YOU\AppData\Local\Programs\ClicksPal\resources\mcp.cjs'
```


**Check:** Start a new Codex session; `codex mcp list` should show `clickspal`.

### OpenCode

**One click:** in ClicksPal, open **MCP** in the sidebar and press **Add** next to your agent. If you move the app, press **Update**.

**Or merge** this config into the file below, keeping existing servers. Use the path where ClicksPal is installed.

Mac:

```json
{
  "mcp": {
    "clickspal": {
      "type": "local",
      "command": [
        "/Applications/ClicksPal.app/Contents/MacOS/ClicksPal",
        "/Applications/ClicksPal.app/Contents/Resources/mcp.cjs"
      ],
      "environment": {
        "ELECTRON_RUN_AS_NODE": "1"
      },
      "enabled": true
    }
  }
}
```


Windows (replace YOU with your Windows user name):

```json
{
  "mcp": {
    "clickspal": {
      "type": "local",
      "command": [
        "C:\\Users\\YOU\\AppData\\Local\\Programs\\ClicksPal\\ClicksPal.exe",
        "C:\\Users\\YOU\\AppData\\Local\\Programs\\ClicksPal\\resources\\mcp.cjs"
      ],
      "environment": {
        "ELECTRON_RUN_AS_NODE": "1"
      },
      "enabled": true
    }
  }
}
```


**Check:** Start a new session and check `opencode mcp list`.

### Cursor

**One click:** in ClicksPal, open **MCP** in the sidebar and press **Add** next to your agent. If you move the app, press **Update**.

**Or merge** this config into the file below, keeping existing servers. Use the path where ClicksPal is installed.

Mac:

```json
{
  "mcpServers": {
    "clickspal": {
      "command": "/Applications/ClicksPal.app/Contents/MacOS/ClicksPal",
      "args": [
        "/Applications/ClicksPal.app/Contents/Resources/mcp.cjs"
      ],
      "env": {
        "ELECTRON_RUN_AS_NODE": "1"
      }
    }
  }
}
```


Windows (replace YOU with your Windows user name):

```json
{
  "mcpServers": {
    "clickspal": {
      "command": "C:\\Users\\YOU\\AppData\\Local\\Programs\\ClicksPal\\ClicksPal.exe",
      "args": [
        "C:\\Users\\YOU\\AppData\\Local\\Programs\\ClicksPal\\resources\\mcp.cjs"
      ],
      "env": {
        "ELECTRON_RUN_AS_NODE": "1"
      }
    }
  }
}
```


**Check:** Open Cursor Settings → MCP and check that `clickspal` is enabled.

### Claude Desktop

**One click:** in ClicksPal, open **MCP** in the sidebar and press **Add** next to your agent. If you move the app, press **Update**.

**Or merge** this config into the file below, keeping existing servers. Use the path where ClicksPal is installed.

Mac:

```json
{
  "mcpServers": {
    "clickspal": {
      "command": "/Applications/ClicksPal.app/Contents/MacOS/ClicksPal",
      "args": [
        "/Applications/ClicksPal.app/Contents/Resources/mcp.cjs"
      ],
      "env": {
        "ELECTRON_RUN_AS_NODE": "1"
      }
    }
  }
}
```


Windows (replace YOU with your Windows user name):

```json
{
  "mcpServers": {
    "clickspal": {
      "command": "C:\\Users\\YOU\\AppData\\Local\\Programs\\ClicksPal\\ClicksPal.exe",
      "args": [
        "C:\\Users\\YOU\\AppData\\Local\\Programs\\ClicksPal\\resources\\mcp.cjs"
      ],
      "env": {
        "ELECTRON_RUN_AS_NODE": "1"
      }
    }
  }
}
```


**Check:** Quit and reopen Claude Desktop, then start a new chat.

### Windsurf

**One click:** in ClicksPal, open **MCP** in the sidebar and press **Add** next to your agent. If you move the app, press **Update**.

**Or merge** this config into the file below, keeping existing servers. Use the path where ClicksPal is installed.

Mac:

```json
{
  "mcpServers": {
    "clickspal": {
      "command": "/Applications/ClicksPal.app/Contents/MacOS/ClicksPal",
      "args": [
        "/Applications/ClicksPal.app/Contents/Resources/mcp.cjs"
      ],
      "env": {
        "ELECTRON_RUN_AS_NODE": "1"
      }
    }
  }
}
```


Windows (replace YOU with your Windows user name):

```json
{
  "mcpServers": {
    "clickspal": {
      "command": "C:\\Users\\YOU\\AppData\\Local\\Programs\\ClicksPal\\ClicksPal.exe",
      "args": [
        "C:\\Users\\YOU\\AppData\\Local\\Programs\\ClicksPal\\resources\\mcp.cjs"
      ],
      "env": {
        "ELECTRON_RUN_AS_NODE": "1"
      }
    }
  }
}
```


**Check:** Reload Windsurf and check its MCP server list.

### Other apps

**Open** the MCP configuration in your agent.

**Or merge** this config into the file below, keeping existing servers. Use the path where ClicksPal is installed.

Mac:

```json
{
  "mcpServers": {
    "clickspal": {
      "command": "/Applications/ClicksPal.app/Contents/MacOS/ClicksPal",
      "args": [
        "/Applications/ClicksPal.app/Contents/Resources/mcp.cjs"
      ],
      "env": {
        "ELECTRON_RUN_AS_NODE": "1"
      }
    }
  }
}
```


Windows (replace YOU with your Windows user name):

```json
{
  "mcpServers": {
    "clickspal": {
      "command": "C:\\Users\\YOU\\AppData\\Local\\Programs\\ClicksPal\\ClicksPal.exe",
      "args": [
        "C:\\Users\\YOU\\AppData\\Local\\Programs\\ClicksPal\\resources\\mcp.cjs"
      ],
      "env": {
        "ELECTRON_RUN_AS_NODE": "1"
      }
    }
  }
}
```


**Check:** Use a client that supports local stdio MCP servers, then start a new session.

## Workflows

- Check setup: `setup_status` → `settings_get` → `site_get`

- Inspect a website: `status` → `site_get` → `setup_run` → `wait` → `site_get`

- Run an SEO audit: `audit_full` → `wait` → `audits_list` → `audit_get`

- Choose calendar work: `pipeline_candidates` → `pipeline_enqueue` → `calendar_get`

- Build a task: `job_run` → `wait` → `job_get`

- Answer a blocker: `job_get` → `job_feedback` → `wait` → `job_get`

- Publish reviewed work: `pipeline_ship` → `wait` → `today_get`

- Check AI usage: `ai_usage_get` → `settings_get`

## Tools

### status

Read

Start here. Every website with its id, running work, latest audit, task counts and open questions, plus connections, provider quota and recent activity.

```json
{
  "type": "object",
  "description": "",
  "properties": {},
  "required": [],
  "additionalProperties": false
}
```

### wait

Read

Wait until work starts, finishes, blocks or asks a question, or the time runs out. Returns status. Use between long-running tool calls instead of polling.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "seconds": {
      "type": "integer",
      "description": "Longest wait; default 30, at most 50."
    }
  },
  "required": [],
  "additionalProperties": false
}
```

### setup_templates

Read

Connected websites whose public page templates can be reused. The same optional choices as Website settings; nothing is selected automatically. Select with site_save templateSiteId, or clear it with an empty string.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Target website id from status; omit while adding a website."
    }
  },
  "required": [],
  "additionalProperties": false
}
```

### site_get

Read

A website’s full settings: contract directories, commands, agents, build setup (references, components, questions), decisions and day run.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### pipeline_list

Read

The Content pipeline list for one day, as the window shows it: now (building), next (today: in the exact order Autopilot builds them, stopped tasks it retries first; another day: what is scheduled) and done (built or live that day). Questions and stopped builds are in status needsYou. Omit siteId for every workspace.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "day": {
      "type": "string",
      "description": "Day, YYYY-MM-DD in the Mac’s local time; default today."
    }
  },
  "required": [],
  "additionalProperties": false
}
```

### calendar_get

Read

The content calendar, past days included: per day how many tasks were assigned and how many got built, and the tasks themselves. A task missed on a day is listed there with movedTo. Plus tasks on no day and tasks needing attention.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "from": {
      "type": "string",
      "description": "First day, YYYY-MM-DD in the Mac’s local time; default today. Use an earlier day to read history."
    },
    "days": {
      "type": "integer",
      "description": "Days to return; default 14, at most 90."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### published_get

Read

What ClicksPal has published, as the Published pages screen shows it: every live page per workspace grouped by type, plus pages added and pages updated per day (new pages vs changes and repairs), totals, and built pages not published yet. Omit siteId for every workspace.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "days": {
      "type": "integer",
      "description": "Days of history; default 30, at most 365."
    }
  },
  "required": [],
  "additionalProperties": false
}
```

### today_get

Read

What is happening now, as Today shows it. Omit siteId for every workspace, audit and pipeline readiness, combined counts and task lists. Pass siteId for one website’s build step, queue, pause, questions, attention, built pages and execution/audit models.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    }
  },
  "required": [],
  "additionalProperties": false
}
```

### jobs_list

Read

Tasks, filtered. Compact rows; job_get has the detail.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "status": {
      "type": "string",
      "description": "One status, or active (planning, building, checking, shipping).",
      "enum": [
        "planned",
        "queued",
        "needs-input",
        "researching",
        "building",
        "checking",
        "ready",
        "publishing",
        "live",
        "blocked",
        "failed",
        "cancelled",
        "active"
      ]
    },
    "format": {
      "type": "string",
      "description": "Content type.",
      "enum": [
        "article",
        "alternatives",
        "listicle",
        "tool",
        "marketing",
        "programmatic",
        "repair"
      ]
    },
    "day": {
      "type": "string",
      "description": "Scheduled day, YYYY-MM-DD in the Mac’s local time."
    },
    "search": {
      "type": "string",
      "description": "Text in the title or keyword."
    },
    "limit": {
      "type": "integer",
      "description": "Rows to return; default 50, at most 500."
    },
    "offset": {
      "type": "integer",
      "description": "Rows to skip."
    }
  },
  "required": [],
  "additionalProperties": false
}
```

### job_get

Read

One task in full: the facts an owner sees (keyword, volume, difficulty, what gets built), brief, plan, questions, checks, review, events, worktree path, branch and changed files. File contents are in the worktree; includeArtifacts returns stored contents for tasks without one.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "id": {
      "type": "string",
      "description": "Task id from jobs_list or calendar_get."
    },
    "events": {
      "type": "integer",
      "description": "Latest events to return; default 30."
    },
    "includeArtifacts": {
      "type": "boolean",
      "description": "Return stored file contents."
    },
    "full": {
      "type": "boolean",
      "description": "Do not shorten long check and review output."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}
```

### audits_list

Read

A website’s saved SEO audits, oldest first.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### audit_get

Read

An audit’s overview: scores per dimension, the five conclusions, research progress per content type, organic baseline, competitors and limitations. Latest audit unless auditId is given.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "auditId": {
      "type": "string",
      "description": "Audit id; omit for the latest."
    },
    "include": {
      "type": "array",
      "description": "Bulky sections to add.",
      "items": {
        "type": "string",
        "description": "",
        "enum": [
          "topicMap",
          "patterns",
          "daily"
        ]
      }
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### audit_keywords

Read

An audit’s keyword opportunities with measured volume and difficulty, filtered and sorted. detail adds the brief, evidence and secondary keywords. Unknown volume is null, never zero.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "auditId": {
      "type": "string",
      "description": "Audit id; omit for the latest."
    },
    "lane": {
      "type": "string",
      "description": "Content type.",
      "enum": [
        "marketing",
        "tool",
        "alternatives",
        "listicle",
        "article",
        "programmatic"
      ]
    },
    "disposition": {
      "type": "string",
      "description": "Research verdict; default validated and low-data.",
      "enum": [
        "validated",
        "low-data",
        "rejected",
        "all"
      ]
    },
    "status": {
      "type": "string",
      "description": "Owner decision.",
      "enum": [
        "suggested",
        "approved",
        "deferred",
        "rejected",
        "producing"
      ]
    },
    "fit": {
      "type": "string",
      "description": "Product fit.",
      "enum": [
        "direct",
        "adjacent",
        "weak"
      ]
    },
    "search": {
      "type": "string",
      "description": "Text in the keyword, title or secondary keywords."
    },
    "minVolume": {
      "type": "integer",
      "description": "Lowest monthly searches."
    },
    "maxDifficulty": {
      "type": "integer",
      "description": "Highest difficulty, 0–100."
    },
    "sort": {
      "type": "string",
      "description": "Order; default priority.",
      "enum": [
        "priority",
        "volume",
        "difficulty"
      ]
    },
    "ids": {
      "type": "array",
      "description": "Return exactly these audit keyword ids.",
      "items": {
        "type": "string",
        "description": ""
      }
    },
    "detail": {
      "type": "boolean",
      "description": "Full records."
    },
    "limit": {
      "type": "integer",
      "description": "Rows to return; default 50, at most 500."
    },
    "offset": {
      "type": "integer",
      "description": "Rows to skip."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### audit_findings

Read

An audit’s technical findings grouped by root cause, worst first. detail adds evidence, the repair brief and every affected URL.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "auditId": {
      "type": "string",
      "description": "Audit id; omit for the latest."
    },
    "severity": {
      "type": "string",
      "description": "Only this severity.",
      "enum": [
        "error",
        "warning",
        "info"
      ]
    },
    "detail": {
      "type": "boolean",
      "description": "Full records."
    },
    "limit": {
      "type": "integer",
      "description": "Rows to return; default 50, at most 500."
    },
    "offset": {
      "type": "integer",
      "description": "Rows to skip."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### audit_pages

Read

The website’s existing pages from an audit: type, indexability, inbound links and observed Search Console clicks and impressions. Null traffic means not observed, not zero.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "auditId": {
      "type": "string",
      "description": "Audit id; omit for the latest."
    },
    "lane": {
      "type": "string",
      "description": "Page type.",
      "enum": [
        "marketing",
        "tool",
        "alternatives",
        "listicle",
        "article",
        "programmatic",
        "other"
      ]
    },
    "search": {
      "type": "string",
      "description": "Text in the URL or title."
    },
    "limit": {
      "type": "integer",
      "description": "Rows to return; default 50, at most 500."
    },
    "offset": {
      "type": "integer",
      "description": "Rows to skip."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### pipeline_candidates

Read

Audit work that can go on the calendar: keyword opportunities and findings with priority and whether a task already exists. sourceId feeds pipeline_enqueue.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "unscheduledOnly": {
      "type": "boolean",
      "description": "Hide work that already has a task; default true."
    },
    "format": {
      "type": "string",
      "description": "Content type.",
      "enum": [
        "article",
        "alternatives",
        "listicle",
        "tool",
        "marketing",
        "programmatic",
        "repair"
      ]
    },
    "limit": {
      "type": "integer",
      "description": "Rows to return; default 50, at most 500."
    },
    "offset": {
      "type": "integer",
      "description": "Rows to skip."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### opportunities_list

Read

Workspace opportunities: the owner’s decisions on audit keywords plus ones added by hand or from Search Console and AI answers.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "status": {
      "type": "string",
      "description": "Decision.",
      "enum": [
        "suggested",
        "approved",
        "deferred",
        "rejected",
        "producing"
      ]
    },
    "source": {
      "type": "string",
      "description": "Origin.",
      "enum": [
        "manual",
        "agent",
        "dataforseo",
        "audit",
        "gsc",
        "visibility"
      ]
    },
    "format": {
      "type": "string",
      "description": "Content type.",
      "enum": [
        "article",
        "alternatives",
        "listicle",
        "tool",
        "marketing",
        "programmatic",
        "repair"
      ]
    },
    "search": {
      "type": "string",
      "description": "Text in the keyword or title."
    },
    "detail": {
      "type": "boolean",
      "description": "Do not shorten the rationale."
    },
    "limit": {
      "type": "integer",
      "description": "Rows to return; default 50, at most 500."
    },
    "offset": {
      "type": "integer",
      "description": "Rows to skip."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### crawl_get

Read

The latest technical crawl: health score, checks, page speed, crawler access and its issues.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "includeResolved": {
      "type": "boolean",
      "description": "Include resolved issues."
    },
    "includePages": {
      "type": "boolean",
      "description": "Include every crawled page."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### search_performance

Read

Search Console clicks, impressions, CTR and average position from the latest saved report, grouped by query, page or date.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "groupBy": {
      "type": "string",
      "description": "Grouping; default query.",
      "enum": [
        "query",
        "page",
        "date"
      ]
    },
    "search": {
      "type": "string",
      "description": "Text in the query or page."
    },
    "limit": {
      "type": "integer",
      "description": "Rows to return; default 50, at most 500."
    },
    "offset": {
      "type": "integer",
      "description": "Rows to skip."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### visibility_get

Read

AI visibility: the measured buyer-question panel, and what ChatGPT and Gemini answered — whether the product was mentioned or cited, and which competitors were.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "includeAnswers": {
      "type": "boolean",
      "description": "Return full answer text."
    },
    "limit": {
      "type": "integer",
      "description": "Rows to return; default 50, at most 500."
    },
    "offset": {
      "type": "integer",
      "description": "Rows to skip."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### spend_get

Read

Paid research spend: totals per month and endpoint against the saved budgets, and the latest ledger rows.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Only this website."
    },
    "limit": {
      "type": "integer",
      "description": "Rows to return; default 50, at most 500."
    },
    "offset": {
      "type": "integer",
      "description": "Rows to skip."
    }
  },
  "required": [],
  "additionalProperties": false
}
```

### ai_usage_get

Read

ClicksPal AI calls and reported tokens for today and the last seven days, plus actual provider quota windows. Unknown token usage remains unknown.

```json
{
  "type": "object",
  "description": "",
  "properties": {},
  "required": [],
  "additionalProperties": false
}
```

### setup_status

Read

First-run connection and website readiness, using the same checklist as the window.

```json
{
  "type": "object",
  "description": "",
  "properties": {},
  "required": [],
  "additionalProperties": false
}
```

### settings_get

Read

App defaults, research budgets, which accounts are connected (never the credentials), and every AI provider with its models, efforts and remaining quota.

```json
{
  "type": "object",
  "description": "",
  "properties": {},
  "required": [],
  "additionalProperties": false
}
```

### activity_list

Read

The app’s activity log, newest last: what started, finished and failed.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "limit": {
      "type": "integer",
      "description": "Entries; default 40, at most 300."
    }
  },
  "required": [],
  "additionalProperties": false
}
```

### autopilot_get

Read

Autopilot as its page shows it: settings, next run time, the task it will build next, what is running, why it is waiting (provider quota, other work), each workspace with tasks due, built pages waiting and whether its publishing schedule is due, the last runs, and the progress of AI answering questions (asks).

```json
{
  "type": "object",
  "description": "",
  "properties": {},
  "required": [],
  "additionalProperties": false
}
```

### playbooks_get

Read

The standards build agents follow. Without a name: the list. With a name: the built-in text and the owner’s additions.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "name": {
      "type": "string",
      "description": "Playbook name."
    }
  },
  "required": [],
  "additionalProperties": false
}
```

### site_save

Write

Connect a website or change its settings. Pass id to edit; then only the fields you send change. New websites need url and repoPath.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "id": {
      "type": "string",
      "description": "Existing website id. Omit to connect a new website."
    },
    "site": {
      "type": "object",
      "description": "Website settings.",
      "properties": {
        "name": {
          "type": "string",
          "description": "Display name."
        },
        "url": {
          "type": "string",
          "description": "Public website URL."
        },
        "repoPath": {
          "type": "string",
          "description": "Absolute path to the root of the website’s local Git repository."
        },
        "templateSiteId": {
          "type": "string",
          "description": "Optional connected website id from setup_templates whose public templates the agent may reuse. Empty clears it. Never copies its product facts, credentials or publishing settings."
        },
        "description": {
          "type": "string",
          "description": "What the product is."
        },
        "audience": {
          "type": "string",
          "description": "Who it is for."
        },
        "productFacts": {
          "type": "string",
          "description": "Verified product facts agents may state."
        },
        "articlesDir": {
          "type": "string",
          "description": "Repository directory for articles."
        },
        "toolsDir": {
          "type": "string",
          "description": "Repository directory for free tools."
        },
        "pagesDir": {
          "type": "string",
          "description": "Repository directory for marketing pages."
        },
        "repairDirs": {
          "type": "array",
          "description": "Shared code directories agents may edit.",
          "items": {
            "type": "string",
            "description": ""
          }
        },
        "allowedSupportingFiles": {
          "type": "array",
          "description": "Exact supporting files agents may edit.",
          "items": {
            "type": "string",
            "description": ""
          }
        },
        "toolApiDir": {
          "type": "string",
          "description": "The one public endpoint directory free tools may add to, e.g. app/api/tools. Empty clears it."
        },
        "validateCommand": {
          "type": "string",
          "description": "Command that validates the website, e.g. npm run build."
        },
        "publishCommand": {
          "type": "string",
          "description": "Deploy command used by pipeline_ship, e.g. git push."
        },
        "articlePublishCommand": {
          "type": "string",
          "description": "For a blog stored in a database table: command that publishes one article draft file, e.g. node scripts/publish-article.mjs. The draft path is appended. Article tasks then write one draft in the articles directory and ship without a commit or deploy."
        },
        "provider": {
          "type": "string",
          "description": "Executor provider.",
          "enum": [
            "claude",
            "codex",
            "opencode",
            "ollama"
          ]
        },
        "model": {
          "type": "string",
          "description": "Executor model; empty uses the provider default."
        },
        "effort": {
          "type": "string",
          "description": "Executor effort."
        },
        "managerProvider": {
          "type": "string",
          "description": "SEO audit provider; empty means same provider as execution."
        },
        "managerModel": {
          "type": "string",
          "description": "SEO audit model. Builds never use this model."
        },
        "managerEffort": {
          "type": "string",
          "description": "SEO audit reasoning effort."
        },
        "publicationPolicy": {
          "type": "string",
          "description": "Publication policy.",
          "enum": [
            "review",
            "auto"
          ]
        },
        "monthlyBudgetUsd": {
          "type": "number",
          "description": "Monthly research budget for this website."
        },
        "countryCode": {
          "type": "integer",
          "description": "DataForSEO location code, e.g. 2840 for the United States."
        },
        "languageCode": {
          "type": "string",
          "description": "Language code, e.g. en."
        },
        "keywords": {
          "type": "array",
          "description": "Seed keywords.",
          "items": {
            "type": "string",
            "description": ""
          }
        },
        "visibilityPrompts": {
          "type": "array",
          "description": "Buyer questions measured in AI answers.",
          "items": {
            "type": "string",
            "description": ""
          }
        }
      },
      "required": [],
      "additionalProperties": false
    }
  },
  "required": [
    "site"
  ],
  "additionalProperties": false
}
```

### site_remove

Write · Destructive

Disconnect a website and delete its audits, tasks and measurements from ClicksPal. The repository is untouched.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "id": {
      "type": "string",
      "description": "Website id from status."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}
```

### site_inspect

Write

Re-read the repository to detect its framework and fill empty product facts.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### audit_full

Write · Background

Run the full SEO audit: crawl, existing pages, and keyword research for every content type. Spends the saved DataForSEO budget; cached measurements are reused. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "agent": {
      "type": "object",
      "description": "Model for this audit. Omit to use this website’s saved audit model, falling back to its execution model.",
      "properties": {
        "provider": {
          "type": "string",
          "description": "Provider; check status for remaining quota.",
          "enum": [
            "claude",
            "codex",
            "opencode",
            "ollama"
          ]
        },
        "model": {
          "type": "string",
          "description": "Model id from settings_get; empty for the account default."
        },
        "effort": {
          "type": "string",
          "description": "Reasoning effort; empty for the default."
        }
      },
      "required": [
        "provider"
      ],
      "additionalProperties": false
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### audit_cancel

Write

Stop the running SEO audit and keep the research finished so far.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### audit_conclusions

Write · Background

Write the five overview conclusions for a finished audit. No-op when they already exist. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "auditId": {
      "type": "string",
      "description": "Audit id from audits_list."
    }
  },
  "required": [
    "siteId",
    "auditId"
  ],
  "additionalProperties": false
}
```

### audit_search_history

Write · Background

Fetch the daily clicks and impressions chart for an audit. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "auditId": {
      "type": "string",
      "description": "Audit id from audits_list."
    }
  },
  "required": [
    "siteId",
    "auditId"
  ],
  "additionalProperties": false
}
```

### audit_schedule

Write

Turn the monthly audit rerun on or off.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "enabled": {
      "type": "boolean",
      "description": "true reruns the audit every 30 days while the app is open."
    }
  },
  "required": [
    "siteId",
    "enabled"
  ],
  "additionalProperties": false
}
```

### audit_export

Write

Write an audit and its task list to a JSON file. Use this instead of paging audit_keywords when you need everything.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "auditId": {
      "type": "string",
      "description": "Audit id; omit for the latest."
    },
    "path": {
      "type": "string",
      "description": "Absolute .json path in an existing folder."
    }
  },
  "required": [
    "siteId",
    "path"
  ],
  "additionalProperties": false
}
```

### audit_resolve

Write

Mark a technical-crawl issue resolved or open.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "issueId": {
      "type": "string",
      "description": "Issue id from crawl_get."
    },
    "resolved": {
      "type": "boolean",
      "description": "true resolves it."
    }
  },
  "required": [
    "issueId",
    "resolved"
  ],
  "additionalProperties": false
}
```

### audit_run

Write · Background

Run only the technical crawl (older flow; audit_full includes it). Results are in crawl_get. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### audit_repair

Write · Background

Have an agent repair chosen technical-crawl issues in an isolated worktree. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "issueIds": {
      "type": "array",
      "description": "Issue ids from crawl_get.",
      "items": {
        "type": "string",
        "description": ""
      }
    }
  },
  "required": [
    "siteId",
    "issueIds"
  ],
  "additionalProperties": false
}
```

### audit_repair_all

Write · Background

Have an agent repair every open error and warning from the technical crawl. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### pipeline_enqueue

Write

Put audit tasks on the content calendar. Validated work is scheduled automatically; use this for the rest. Existing bookings are kept.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "sourceIds": {
      "type": "array",
      "description": "sourceId values from pipeline_candidates.",
      "items": {
        "type": "string",
        "description": ""
      }
    },
    "startDate": {
      "type": "string",
      "description": "First day to fill, YYYY-MM-DD in the Mac’s local time; today or later."
    },
    "batch": {
      "type": "boolean",
      "description": "Group up to 10 alternatives, comparison or marketing pages into one day."
    }
  },
  "required": [
    "siteId",
    "sourceIds",
    "startDate"
  ],
  "additionalProperties": false
}
```

### pipeline_move

Write

Move a calendar task to a day, or pause it by omitting day. Moving a paused task resumes it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "id": {
      "type": "string",
      "description": "Task id from jobs_list or calendar_get."
    },
    "day": {
      "type": "string",
      "description": "YYYY-MM-DD in the Mac’s local time; omit to pause."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}
```

### pipeline_reconcile

Write

Re-sync the calendar with saved audits and decisions.

```json
{
  "type": "object",
  "description": "",
  "properties": {},
  "required": [],
  "additionalProperties": false
}
```

### pipeline_run_day

Write · Background

Build all of a day’s tasks one after another with the execution model, including planning and review. The audit model stays unchanged. Nothing touches the website repository until pipeline_ship. A provider limit or a dropped connection pauses the run (today_get → pause); calling this again continues each task from its last finished step. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "day": {
      "type": "string",
      "description": "YYYY-MM-DD in the Mac’s local time; omit for today."
    },
    "executor": {
      "type": "object",
      "description": "Model for all build steps, saved as the website’s execution model. Omit to keep the saved one.",
      "properties": {
        "provider": {
          "type": "string",
          "description": "Provider; check status for remaining quota.",
          "enum": [
            "claude",
            "codex",
            "opencode",
            "ollama"
          ]
        },
        "model": {
          "type": "string",
          "description": "Model id from settings_get; empty for the account default."
        },
        "effort": {
          "type": "string",
          "description": "Reasoning effort; empty for the default."
        }
      },
      "required": [
        "provider"
      ],
      "additionalProperties": false
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### pipeline_run_workspaces

Write · Background

Build today across selected workspaces, or all workspaces when siteIds is omitted. Runs one workspace after another, preserving each website’s day run. Empty and busy workspaces are skipped with reasons in activity_list. Use today_get without siteId for the combined view. Builds never publish. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteIds": {
      "type": "array",
      "description": "Website ids from status; omit for all workspaces.",
      "items": {
        "type": "string",
        "description": "Website id from status."
      }
    },
    "day": {
      "type": "string",
      "description": "YYYY-MM-DD in the Mac’s local time; omit for today."
    },
    "executor": {
      "type": "object",
      "description": "Execution model saved for each workspace that starts. Omit to keep each workspace’s saved execution model. Audit models stay unchanged.",
      "properties": {
        "provider": {
          "type": "string",
          "description": "Provider; check status for remaining quota.",
          "enum": [
            "claude",
            "codex",
            "opencode",
            "ollama"
          ]
        },
        "model": {
          "type": "string",
          "description": "Model id from settings_get; empty for the account default."
        },
        "effort": {
          "type": "string",
          "description": "Reasoning effort; empty for the default."
        }
      },
      "required": [
        "provider"
      ],
      "additionalProperties": false
    }
  },
  "required": [],
  "additionalProperties": false
}
```

### pipeline_stop_day

Write

Stop the day run after the task it is on.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### pipeline_ship

Write · Background · Destructive

Commit every built task to the website repository in build order, run the deploy command and verify each page live. Changes the live website: only when the owner asked to ship. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### autopilot_save

Write

Change Autopilot: on/off, how often it builds one task (intervalHours), which workspaces take part (excludedSiteIds; new workspaces take part), when built pages publish (publish: immediate, batch after batchSize built changes or once the day is done, whichever comes first, dayDone when a workspace has built all of today’s tasks, manual), macOS notifications and whether an agent answers open questions first. Only the fields you send change. Autopilot runs one build at a time and only when nothing else is building. A stopped task is tried again automatically up to 3 times, at least an hour apart (timeouts as is, other stops after an AI decision), before it waits in Needs you. Read it with autopilot_get.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "settings": {
      "type": "object",
      "description": "Autopilot settings.",
      "properties": {
        "enabled": {
          "type": "boolean",
          "description": "true turns Autopilot on; the first task starts within a minute when nothing else is building."
        },
        "intervalHours": {
          "type": "number",
          "description": "Hours between tasks: 0.25, 0.5, 1, 2, 4, 6 (0.25 = 15 minutes, 0.5 = 30 minutes)."
        },
        "excludedSiteIds": {
          "type": "array",
          "description": "Website ids from status that do not take part. Replaces the saved list.",
          "items": {
            "type": "string",
            "description": ""
          }
        },
        "publish": {
          "type": "string",
          "description": "When built pages go live. A workspace whose publication policy is review never publishes automatically.",
          "enum": [
            "immediate",
            "batch",
            "dayDone",
            "manual"
          ]
        },
        "batchSize": {
          "type": "integer",
          "description": "Built changes a workspace collects before batch publishing, 1–50."
        },
        "notify": {
          "type": "object",
          "description": "macOS notifications.",
          "properties": {
            "built": {
              "type": "boolean",
              "description": "A page or tool was built."
            },
            "published": {
              "type": "boolean",
              "description": "Pages were published, or publishing failed."
            },
            "needsYou": {
              "type": "boolean",
              "description": "A task needs an answer or stopped."
            }
          },
          "required": [],
          "additionalProperties": false
        },
        "answerQuestions": {
          "type": "boolean",
          "description": "true lets an agent answer or dismiss open questions (as asks_resolve) before each task."
        }
      },
      "required": [],
      "additionalProperties": false
    }
  },
  "required": [
    "settings"
  ],
  "additionalProperties": false
}
```

### autopilot_run_now

Write · Background

Have Autopilot build its next task now (autopilot_get → next), then publish what its schedule says is due. Refused while anything else is building. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {},
  "required": [],
  "additionalProperties": false
}
```

### pipeline_triage

Write · Background

Let AI plan eligible unbuilt tasks that sit on no day. Deferred, rejected and evidence-blocked ideas stay off the calendar until their audit decision or evidence changes: an agent with each website’s model puts each one back on the calendar from today, in value order, or removes it (cancelled, reason in skipped). Decisions are recorded in each task’s events. Progress is in status → triage. Only when the owner asked you to let AI plan the calendar. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status; omit for every workspace."
    }
  },
  "required": [],
  "additionalProperties": false
}
```

### asks_resolve

Write · Background

Let AI handle the questions waiting on the owner: an agent with each website’s execution model answers every open task and setup question (picking an offered option), or dismisses a task it cannot build truthfully. Answered tasks are queued for today; dismissed tasks are cancelled with the reason in skipped. Decisions are recorded in each task’s events. Progress is in autopilot_get → asks. Only when the owner asked you to let AI answer. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status; omit for every workspace."
    }
  },
  "required": [],
  "additionalProperties": false
}
```

### setup_run

Write · Background

Have the execution model read the repository and save reference pages, shared components, decisions and owner questions. Runs once before the first build; rerun after large repository changes. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### setup_cancel

Write

Stop a running website setup inspection and cancel builds waiting for it. Other websites, audits and completed work are untouched. Run setup_run or job_run again when ready.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### setup_answer

Write

Answer build-setup questions (site_get → buildSetup.questions).

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "answers": {
      "type": "array",
      "description": "One answer per open question key.",
      "items": {
        "type": "object",
        "description": "",
        "properties": {
          "key": {
            "type": "string",
            "description": "Question key."
          },
          "answer": {
            "type": "string",
            "description": "The answer; pick one of the offered options when they fit."
          }
        },
        "required": [
          "key",
          "answer"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "siteId",
    "answers"
  ],
  "additionalProperties": false
}
```

### setup_reference

Write

Choose the page later work of one content type starts from. An empty path clears it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "kind": {
      "type": "string",
      "description": "Content type.",
      "enum": [
        "marketing",
        "tool",
        "article"
      ]
    },
    "path": {
      "type": "string",
      "description": "Page file path relative to the repository root."
    }
  },
  "required": [
    "siteId",
    "kind",
    "path"
  ],
  "additionalProperties": false
}
```

### decision_save

Write

Save a settled answer every later agent treats as authority for this website.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "key": {
      "type": "string",
      "description": "Short identifier, e.g. tool-ai-provider."
    },
    "question": {
      "type": "string",
      "description": "What was decided."
    },
    "answer": {
      "type": "string",
      "description": "The decision."
    }
  },
  "required": [
    "siteId",
    "key",
    "question",
    "answer"
  ],
  "additionalProperties": false
}
```

### decision_remove

Write

Delete a saved website decision.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "key": {
      "type": "string",
      "description": "Decision key from site_get."
    }
  },
  "required": [
    "siteId",
    "key"
  ],
  "additionalProperties": false
}
```

### playbook_save

Write

Save owner additions to a build standard; they win over the built-in text. Empty content removes them.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "name": {
      "type": "string",
      "description": "Playbook name from playbooks_get."
    },
    "content": {
      "type": "string",
      "description": "Markdown additions, under 20,000 characters."
    },
    "siteId": {
      "type": "string",
      "description": "Unused; standards apply to every website."
    }
  },
  "required": [
    "name",
    "content"
  ],
  "additionalProperties": false
}
```

### job_create

Write

Create a build task from your own brief. It is not on the calendar; start it with job_run.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "title": {
      "type": "string",
      "description": "Task title."
    },
    "keyword": {
      "type": "string",
      "description": "Target keyword; may be empty for repair."
    },
    "format": {
      "type": "string",
      "description": "Content type.",
      "enum": [
        "article",
        "alternatives",
        "listicle",
        "tool",
        "marketing",
        "programmatic",
        "repair"
      ]
    },
    "brief": {
      "type": "string",
      "description": "What to build and why, with acceptance criteria."
    },
    "opportunityId": {
      "type": "string",
      "description": "Workspace opportunity this task produces, from opportunities_list."
    }
  },
  "required": [
    "siteId",
    "title",
    "keyword",
    "format",
    "brief"
  ],
  "additionalProperties": false
}
```

### job_update

Write

Edit a task that is not running or published. A changed brief resets it to planned.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "id": {
      "type": "string",
      "description": "Task id from jobs_list or calendar_get."
    },
    "title": {
      "type": "string",
      "description": "New title."
    },
    "brief": {
      "type": "string",
      "description": "New brief."
    },
    "scheduledAt": {
      "type": "string",
      "description": "ISO date for tasks outside the calendar; empty clears. Calendar tasks move with pipeline_move."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}
```

### job_run

Write · Background

Build one task now: the execution model plans, edits an isolated worktree and reviews, with website checks from the host. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "id": {
      "type": "string",
      "description": "Task id from jobs_list or calendar_get."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}
```

### job_answer

Write · Background

Save answers to a task’s open questions (job_get → questions), even while another task builds. Once all are answered, resume it or queue it if the repository is busy. A queued response says whether it will join a pending workspace run or needs the next explicit Build today. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "id": {
      "type": "string",
      "description": "Task id from jobs_list or calendar_get."
    },
    "answers": {
      "type": "array",
      "description": "One answer per open question key.",
      "items": {
        "type": "object",
        "description": "",
        "properties": {
          "key": {
            "type": "string",
            "description": "Question key."
          },
          "answer": {
            "type": "string",
            "description": "The answer; pick one of the offered options when they fit."
          }
        },
        "required": [
          "key",
          "answer"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "id",
    "answers"
  ],
  "additionalProperties": false
}
```

### job_feedback

Write · Background

Give a blocked or paused build concrete instructions, a missing answer or a correction, then retry the same task. Replies always save while other tasks build; a busy repository queues this retry, with queued:true and an explanation instead of claiming it started. Your comment remains in job_get. Never put credentials in feedback; configure them in the website environment. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "id": {
      "type": "string",
      "description": "Task id from jobs_list or calendar_get."
    },
    "feedback": {
      "type": "string",
      "description": "What the agent should do or the missing context, in plain words."
    }
  },
  "required": [
    "id",
    "feedback"
  ],
  "additionalProperties": false
}
```

### job_cancel

Write

Stop a task that is planning, building, checking or shipping.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "id": {
      "type": "string",
      "description": "Task id from jobs_list or calendar_get."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}
```

### job_revise

Write

Request changes to a page that is already live. Creates a new task that edits the same page from the owner’s feedback; start it with job_run and ship it like any build.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "id": {
      "type": "string",
      "description": "Task id from jobs_list or calendar_get."
    },
    "feedback": {
      "type": "string",
      "description": "What should change on the live page, in plain words."
    }
  },
  "required": [
    "id",
    "feedback"
  ],
  "additionalProperties": false
}
```

### job_revalidate

Write · Background

Re-run the website’s checks on a built task. On a task that was committed but not verified live, checks the live page again without rebuilding or deploying. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "id": {
      "type": "string",
      "description": "Task id from jobs_list or calendar_get."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}
```

### job_publish

Write · Background · Destructive

Commit and deploy one built task and verify it live. Changes the live website: only when the owner asked to publish. Prefer pipeline_ship for calendar tasks. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "id": {
      "type": "string",
      "description": "Task id from jobs_list or calendar_get."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}
```

### preview_open

Write

Open a built task’s preview window in the ClicksPal app for the owner to look at.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "id": {
      "type": "string",
      "description": "Task id from jobs_list or calendar_get."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}
```

### opportunity_save

Write

Add or edit a workspace opportunity. Demand numbers are never accepted from callers; research_run measures them.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "id": {
      "type": "string",
      "description": "Existing opportunity id. Omit to add."
    },
    "opportunity": {
      "type": "object",
      "description": "Opportunity fields.",
      "properties": {
        "title": {
          "type": "string",
          "description": "Title."
        },
        "keyword": {
          "type": "string",
          "description": "Target keyword."
        },
        "format": {
          "type": "string",
          "description": "Content type.",
          "enum": [
            "article",
            "alternatives",
            "listicle",
            "tool",
            "marketing",
            "programmatic",
            "repair"
          ]
        },
        "intent": {
          "type": "string",
          "description": "Search intent."
        },
        "rationale": {
          "type": "string",
          "description": "Why this is worth building."
        },
        "source": {
          "type": "string",
          "description": "Where it was observed.",
          "enum": [
            "manual",
            "gsc",
            "visibility"
          ]
        },
        "sources": {
          "type": "array",
          "description": "Evidence URLs. For gsc and visibility they must come from this website’s saved report or AI answers.",
          "items": {
            "type": "string",
            "description": ""
          }
        },
        "existingUrl": {
          "type": "string",
          "description": "Existing page to improve instead of creating a new one."
        }
      },
      "required": [
        "title",
        "keyword",
        "format"
      ],
      "additionalProperties": false
    }
  },
  "required": [
    "siteId",
    "opportunity"
  ],
  "additionalProperties": false
}
```

### opportunity_status

Write

Keep, defer or reject an opportunity. The calendar follows the decision.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "id": {
      "type": "string",
      "description": "opportunityId from audit_keywords, or id from opportunities_list."
    },
    "status": {
      "type": "string",
      "description": "Decision.",
      "enum": [
        "suggested",
        "approved",
        "deferred",
        "rejected"
      ]
    }
  },
  "required": [
    "id",
    "status"
  ],
  "additionalProperties": false
}
```

### opportunity_build

Write · Background

Create a task from a workspace opportunity and start building it. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "id": {
      "type": "string",
      "description": "Opportunity id from opportunities_list."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}
```

### opportunities_discover

Write · Background

Have an agent propose opportunities outside an audit, then measure them (older flow; audit_full is the main path). Spends the saved DataForSEO budget; cached measurements are reused. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### research_run

Write · Background

Measure search volume and difficulty for keywords. Spends the saved DataForSEO budget; cached measurements are reused. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "keywords": {
      "type": "array",
      "description": "Up to 200 keywords; omit to measure the website’s saved keywords.",
      "items": {
        "type": "string",
        "description": ""
      }
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### visibility_discover

Write · Background

Generate and measure a keyword panel (search) or buyer-question panel in ChatGPT and Gemini (ai). Spends the saved DataForSEO budget; cached measurements are reused. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "channel": {
      "type": "string",
      "description": "Which panel.",
      "enum": [
        "search",
        "ai"
      ]
    }
  },
  "required": [
    "siteId",
    "channel"
  ],
  "additionalProperties": false
}
```

### visibility_run

Write · Background

Ask ChatGPT and Gemini the saved buyer questions and record mentions and citations. Spends the saved DataForSEO budget; cached measurements are reused. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### visibility_import

Write

Record an AI answer you observed yourself as manual evidence.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "prompt": {
      "type": "string",
      "description": "The question asked."
    },
    "answer": {
      "type": "string",
      "description": "The full answer text."
    },
    "citations": {
      "type": "array",
      "description": "URLs the answer cited.",
      "items": {
        "type": "string",
        "description": ""
      }
    },
    "competitors": {
      "type": "array",
      "description": "Competitor names the answer mentioned.",
      "items": {
        "type": "string",
        "description": ""
      }
    }
  },
  "required": [
    "siteId",
    "prompt",
    "answer",
    "citations",
    "competitors"
  ],
  "additionalProperties": false
}
```

### search_sync

Write · Background

Pull the latest finalized 28 days of query and page performance from Google Search Console. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    }
  },
  "required": [
    "siteId"
  ],
  "additionalProperties": false
}
```

### search_import

Write

Import a Search Console performance CSV.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "siteId": {
      "type": "string",
      "description": "Website id from status."
    },
    "csv": {
      "type": "string",
      "description": "CSV text with query, page, clicks, impressions, ctr and position columns."
    },
    "startDate": {
      "type": "string",
      "description": "Report start, YYYY-MM-DD."
    },
    "endDate": {
      "type": "string",
      "description": "Report end, YYYY-MM-DD."
    }
  },
  "required": [
    "siteId",
    "csv",
    "startDate",
    "endDate"
  ],
  "additionalProperties": false
}
```

### settings_save

Write

Change app-wide defaults and research budgets. Only the fields you send change.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "settings": {
      "type": "object",
      "description": "Settings.",
      "properties": {
        "provider": {
          "type": "string",
          "description": "Default provider.",
          "enum": [
            "claude",
            "codex",
            "opencode",
            "ollama"
          ]
        },
        "model": {
          "type": "string",
          "description": "Default model."
        },
        "effort": {
          "type": "string",
          "description": "Default effort."
        },
        "maxConcurrentJobs": {
          "type": "integer",
          "description": "1–4."
        },
        "reserveQuotaPercent": {
          "type": "number",
          "description": "Provider quota to leave unused, 0–90."
        },
        "monthlyBudgetUsd": {
          "type": "number",
          "description": "Monthly DataForSEO budget."
        },
        "keywordRequestLimitUsd": {
          "type": "number",
          "description": "Cap per keyword request."
        },
        "visibilityRequestLimitUsd": {
          "type": "number",
          "description": "Cap per AI-answer request."
        },
        "ollamaUrl": {
          "type": "string",
          "description": "Loopback Ollama URL."
        },
        "providerChoices": {
          "type": "object",
          "description": "Per-provider {model, effort}."
        },
        "secondaryAgent": {
          "type": "object",
          "description": "Explicit backup for capacity limits.",
          "properties": {
            "provider": {
              "type": "string",
              "description": "Provider; check status for remaining quota.",
              "enum": [
                "claude",
                "codex",
                "opencode",
                "ollama"
              ]
            },
            "model": {
              "type": "string",
              "description": "Model id from settings_get; empty for the account default."
            },
            "effort": {
              "type": "string",
              "description": "Reasoning effort; empty for the default."
            }
          },
          "required": [
            "provider"
          ],
          "additionalProperties": false
        },
        "disableSecondaryAgent": {
          "type": "boolean",
          "description": "Clear the backup provider."
        },
        "setupComplete": {
          "type": "boolean",
          "description": "First-run checklist was completed."
        }
      },
      "required": [],
      "additionalProperties": false
    }
  },
  "required": [
    "settings"
  ],
  "additionalProperties": false
}
```

### credentials_save

Write

Store DataForSEO or Google OAuth client credentials in the Mac’s encrypted storage. Write-only: saved values are never returned. An empty string deletes one.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "dataforseoLogin": {
      "type": "string",
      "description": "DataForSEO login."
    },
    "dataforseoPassword": {
      "type": "string",
      "description": "DataForSEO password."
    },
    "gscClientId": {
      "type": "string",
      "description": "Google OAuth client id."
    },
    "gscClientSecret": {
      "type": "string",
      "description": "Google OAuth client secret."
    }
  },
  "required": [],
  "additionalProperties": false
}
```

### gsc_connect

Write · Background

Start Google sign-in for Search Console in the owner’s browser. The owner finishes it; settings_get shows the result. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {},
  "required": [],
  "additionalProperties": false
}
```

### gsc_service_account_import

Write · Background

Connect Search Console with a Google service-account key file. The key is stored encrypted and checked against the API first. Returns as soon as the work starts. Call wait, then status, to follow it.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "path": {
      "type": "string",
      "description": "Absolute path to the service-account .json key."
    }
  },
  "required": [
    "path"
  ],
  "additionalProperties": false
}
```

### providers_refresh

Write

Re-detect installed AI providers, their models and remaining quota. A newly connected provider is asked a tiny test question; settings_get → providers[].test shows the result.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "retestOld": {
      "type": "boolean",
      "description": "Also re-test providers whose last passed test is over 30 days old."
    }
  },
  "required": [],
  "additionalProperties": false
}
```

### providers_test

Write

Ask one connected provider a tiny test question with a model and reasoning level. Only a passed test (providers[].test.state ok in settings_get) makes it Ready. OpenCode with no model tries one model per account (Go, other accounts, then the Console's free model, never a paid one) and saves the first that answers as its model (providers[].test.model). Returns at once; the test takes up to two minutes. Ollama has none.

```json
{
  "type": "object",
  "description": "",
  "properties": {
    "provider": {
      "type": "string",
      "description": "Provider.",
      "enum": [
        "claude",
        "codex",
        "opencode",
        "ollama"
      ]
    },
    "model": {
      "type": "string",
      "description": "Model id; omit for the saved choice, empty for the provider default."
    },
    "effort": {
      "type": "string",
      "description": "Reasoning level; omit for the saved choice."
    }
  },
  "required": [
    "provider"
  ],
  "additionalProperties": false
}
```

## Troubleshooting

### The app needs activation

Open ClicksPal and activate your license in the window. License keys are never passed through MCP.

### The agent cannot see the tools

Start a new agent session. Check its MCP server list and use **Add** on ClicksPal’s MCP page.

### It stopped after moving or reinstalling the app

Open **MCP** in ClicksPal and press **Update** next to your agent to replace the old path.

### A job is waiting

Read `status` and `job_get` to see open questions or blockers. Use `wait` to follow running work.

### The AI provider reached a limit

Check `ai_usage_get` and `settings_get`. A secondary provider is opt-in; a partially executed writable turn pauses rather than being replayed.

### The build passed but the page is not live

Read the publication result. Building and publishing are separate; shipping needs the website’s configured deploy command.
