Local rankings, map grids, reviews and citations in BrightLocal, worked by your agent.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
How to work in an app by clicking in the user's Cloud Browser with Cotlet's browser tools: which browser to use for this workspace and the sign-in link, the method step by step, the app's screens, menus and actions, notes, and the app's dedicated tools when Cotlet has them. Call it before the first browser step in an app. Works for any web app; one outside Cotlet's catalog gets the general method. Free, no browser session.
The app's name or Cotlet slug. Default: BrightLocal.
What the user wants done in the app, in their words.
Pick your client. Values in capitals, like YOUR_TOKEN, are yours to fill in.
Run in a terminal
claude mcp add --transport http brightlocal https://cotlet.dev/mcp/v1/brightlocal/connect
How to work in an app by clicking in the user's Cloud Browser with Cotlet's browser tools: which browser to use for this workspace and the sign-in link, the method step by step, the app's screens, menus and actions, notes, and the app's dedicated tools when Cotlet has them. Call it before the first browser step in an app. Works for any web app; one outside Cotlet's catalog gets the general method. Free, no browser session.
| Argument | Type | Description |
|---|---|---|
| app | string | The app's name or Cotlet slug. Default: BrightLocal. |
| task | string | What the user wants done in the app, in their words. |
{
"type": "object",
"properties": {
"app": {
"type": "string",
"maxLength": 120,
"description": "The app's name or Cotlet slug. Default: BrightLocal."
},
"task": {
"type": "string",
"maxLength": 500,
"description": "What the user wants done in the app, in their words."
}
},
"additionalProperties": false
}The apps of the user's workspace and whether each works now: the app account in the user's Cloud Browser (connected, signed out, signed in but not connected), and the one step the user has to take, with the console link. Free. Needs the user's Cotlet API key or sign-in.
| Argument | Type | Description |
|---|---|---|
| app | string | Only this app, e.g. skool. |
{
"type": "object",
"properties": {
"app": {
"type": "string",
"description": "Only this app, e.g. skool."
}
},
"additionalProperties": false
}Clicks element `element`, or point `x`, `y` of the screenshot; `double` double-clicks, `button: right` right-clicks. Answers the page after it: the elements and text in view, with the same numbers. Says when nothing changed. A link that would open a new tab opens in this one. Buttons that pay or buy, and sign-in and account pages, are refused.
| Argument | Type | Description |
|---|---|---|
| x | number | Instead of `element`: pixels from the left of the screenshot. |
| y | number | With `x`: pixels from the top of the screenshot. |
| button | string | right opens the page's own context menu. Default: left. |
| dialog | string | How to answer a native dialog (confirm, prompt, 'leave this page?') this step opens: accept presses OK, dismiss presses Cancel. Default: OK for an alert, Cancel for every other dialog. |
| double | boolean | Double-click. |
| element | integer | The element's number from the last read or step answer. |
| dialog_text | string | Text for a prompt dialog this step opens; implies accept. |
{
"type": "object",
"properties": {
"x": {
"type": "number",
"minimum": 0,
"description": "Instead of `element`: pixels from the left of the screenshot."
},
"y": {
"type": "number",
"minimum": 0,
"description": "With `x`: pixels from the top of the screenshot."
},
"button": {
"enum": [
"left",
"right"
],
"type": "string",
"description": "right opens the page's own context menu. Default: left."
},
"dialog": {
"enum": [
"accept",
"dismiss"
],
"type": "string",
"description": "How to answer a native dialog (confirm, prompt, 'leave this page?') this step opens: accept presses OK, dismiss presses Cancel. Default: OK for an alert, Cancel for every other dialog."
},
"double": {
"type": "boolean",
"description": "Double-click."
},
"element": {
"type": "integer",
"minimum": 1,
"description": "The element's number from the last read or step answer."
},
"dialog_text": {
"type": "string",
"maxLength": 1000,
"description": "Text for a prompt dialog this step opens; implies accept."
}
},
"additionalProperties": false
}Ends the browser session when the task is done: the browser keeps its cookies and sleeps, and the per-minute charge stops. Answers the session's minutes and credits.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}Gets the file that clicking `element` (a download link or button) or opening `url` starts: answers its name, type, size and a link valid 15 minutes; CSV, JSON and other text files also as text.
| Argument | Type | Description |
|---|---|---|
| url | string | A public http or https address, e.g. https://example.com. |
| element | integer | The element's number from the last read or step answer. |
{
"type": "object",
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "A public http or https address, e.g. https://example.com."
},
"element": {
"type": "integer",
"minimum": 1,
"description": "The element's number from the last read or step answer."
}
},
"additionalProperties": false
}Drags from one element or point to another: a card between columns, a piece on a board, a slider's handle. Answers the page after it: the elements and text in view, with the same numbers.
| Argument | Type | Description |
|---|---|---|
| to* | object | An element number, or x and y of the screenshot. |
| from* | object | An element number, or x and y of the screenshot. |
| dialog | string | How to answer a native dialog (confirm, prompt, 'leave this page?') this step opens: accept presses OK, dismiss presses Cancel. Default: OK for an alert, Cancel for every other dialog. |
| dialog_text | string | Text for a prompt dialog this step opens; implies accept. |
{
"type": "object",
"required": [
"from",
"to"
],
"properties": {
"to": {
"type": "object",
"properties": {
"x": {
"type": "number",
"minimum": 0,
"description": "Instead of `element`: pixels from the left of the screenshot."
},
"y": {
"type": "number",
"minimum": 0,
"description": "With `x`: pixels from the top of the screenshot."
},
"element": {
"type": "integer",
"minimum": 1,
"description": "The element's number from the last read or step answer."
}
},
"description": "An element number, or x and y of the screenshot.",
"additionalProperties": false
},
"from": {
"type": "object",
"properties": {
"x": {
"type": "number",
"minimum": 0,
"description": "Instead of `element`: pixels from the left of the screenshot."
},
"y": {
"type": "number",
"minimum": 0,
"description": "With `x`: pixels from the top of the screenshot."
},
"element": {
"type": "integer",
"minimum": 1,
"description": "The element's number from the last read or step answer."
}
},
"description": "An element number, or x and y of the screenshot.",
"additionalProperties": false
},
"dialog": {
"enum": [
"accept",
"dismiss"
],
"type": "string",
"description": "How to answer a native dialog (confirm, prompt, 'leave this page?') this step opens: accept presses OK, dismiss presses Cancel. Default: OK for an alert, Cancel for every other dialog."
},
"dialog_text": {
"type": "string",
"maxLength": 1000,
"description": "Text for a prompt dialog this step opens; implies accept."
}
},
"additionalProperties": false
}Runs a JavaScript function body on the page and answers what it returns, as JSON. Use it to extract data the page holds (a table, a list, attributes); act with the other tools. It cannot send requests, click, submit, or read cookies or storage; a filled field's value reads [hidden by Cotlet]. Example: return [...document.querySelectorAll('h2')].map(h => h.innerText)
| Argument | Type | Description |
|---|---|---|
| script* | string | A function body that returns. |
{
"type": "object",
"required": [
"script"
],
"properties": {
"script": {
"type": "string",
"maxLength": 20000,
"description": "A function body that returns."
}
},
"additionalProperties": false
}Fills several fields in one step: text fields take text, drop-downs an option's label, checkboxes, radios and switches true or false. Stops at the first field that fails and names those filled. Does not send the form: click its button after. Answers the page after it: the elements and text in view, with the same numbers.
| Argument | Type | Description |
|---|---|---|
| dialog | string | How to answer a native dialog (confirm, prompt, 'leave this page?') this step opens: accept presses OK, dismiss presses Cancel. Default: OK for an alert, Cancel for every other dialog. |
| fields* | array | The fields in the order a person fills them. |
| dialog_text | string | Text for a prompt dialog this step opens; implies accept. |
{
"type": "object",
"required": [
"fields"
],
"properties": {
"dialog": {
"enum": [
"accept",
"dismiss"
],
"type": "string",
"description": "How to answer a native dialog (confirm, prompt, 'leave this page?') this step opens: accept presses OK, dismiss presses Cancel. Default: OK for an alert, Cancel for every other dialog."
},
"fields": {
"type": "array",
"items": {
"type": "object",
"required": [
"element",
"value"
],
"properties": {
"value": {
"type": [
"string",
"boolean"
],
"description": "Text, option, or true/false."
},
"element": {
"type": "integer",
"minimum": 1,
"description": "The element's number from the last read or step answer."
}
},
"additionalProperties": false
},
"maxItems": 30,
"minItems": 1,
"description": "The fields in the order a person fills them."
},
"dialog_text": {
"type": "string",
"maxLength": 1000,
"description": "Text for a prompt dialog this step opens; implies accept."
}
},
"additionalProperties": false
}Finds `text` on the whole current page, frames included: the elements whose label holds it, with their numbers, and each line of text that holds it. Use it instead of reading or scrolling a long page for one thing.
| Argument | Type | Description |
|---|---|---|
| kind | string | Only elements of this kind. Default: any. |
| text* | string | Words to look for, any case. |
{
"type": "object",
"required": [
"text"
],
"properties": {
"kind": {
"enum": [
"link",
"button",
"field",
"any"
],
"type": "string",
"description": "Only elements of this kind. Default: any."
},
"text": {
"type": "string",
"maxLength": 200,
"description": "Words to look for, any case."
}
},
"additionalProperties": false
}Rests the pointer on an element or a point, to open a hover menu, a tooltip or a preview. Answers the page after it: the elements and text in view, with the same numbers.
| Argument | Type | Description |
|---|---|---|
| x | number | Instead of `element`: pixels from the left of the screenshot. |
| y | number | With `x`: pixels from the top of the screenshot. |
| element | integer | The element's number from the last read or step answer. |
{
"type": "object",
"properties": {
"x": {
"type": "number",
"minimum": 0,
"description": "Instead of `element`: pixels from the left of the screenshot."
},
"y": {
"type": "number",
"minimum": 0,
"description": "With `x`: pixels from the top of the screenshot."
},
"element": {
"type": "integer",
"minimum": 1,
"description": "The element's number from the last read or step answer."
}
},
"additionalProperties": false
}Opens `url` in the current tab, or goes `history` back or forward. Answers the page after it: the elements and text in view, with the same numbers.
| Argument | Type | Description |
|---|---|---|
| url | string | A public http or https address, e.g. https://example.com. |
| dialog | string | How to answer a native dialog (confirm, prompt, 'leave this page?') this step opens: accept presses OK, dismiss presses Cancel. Default: OK for an alert, Cancel for every other dialog. |
| history | string | Instead of `url`. |
| dialog_text | string | Text for a prompt dialog this step opens; implies accept. |
{
"type": "object",
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "A public http or https address, e.g. https://example.com."
},
"dialog": {
"enum": [
"accept",
"dismiss"
],
"type": "string",
"description": "How to answer a native dialog (confirm, prompt, 'leave this page?') this step opens: accept presses OK, dismiss presses Cancel. Default: OK for an alert, Cancel for every other dialog."
},
"history": {
"enum": [
"back",
"forward"
],
"type": "string",
"description": "Instead of `url`."
},
"dialog_text": {
"type": "string",
"maxLength": 1000,
"description": "Text for a prompt dialog this step opens; implies accept."
}
},
"additionalProperties": false
}Starts the user's BrightLocal Cloud Browser (a real Chrome on Cotlet, signed in to BrightLocal as the user; use it for what the BrightLocal tools do not cover) and opens `url`. Call it first. Only BrightLocal pages open. Answers the page after it: the elements and text in view, with the same numbers.
| Argument | Type | Description |
|---|---|---|
| url | string | A public http or https address, e.g. https://example.com. |
{
"type": "object",
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "A public http or https address, e.g. https://example.com."
}
},
"additionalProperties": false
}Presses a key on the focused element: Enter to send, Tab to the next field, Escape to close a pop-up, arrows in a list or slider, or one character (a site's shortcut). Answers the page after it: the elements and text in view, with the same numbers.
| Argument | Type | Description |
|---|---|---|
| key* | string | One of Enter, Tab, Shift+Tab, Escape, Backspace, Delete, Space, ArrowDown, ArrowUp, ArrowLeft, ArrowRight, PageDown, PageUp, Home, End, or one character such as a or 5. |
| dialog | string | How to answer a native dialog (confirm, prompt, 'leave this page?') this step opens: accept presses OK, dismiss presses Cancel. Default: OK for an alert, Cancel for every other dialog. |
| repeat | integer | Times to press it. Default 1. |
| dialog_text | string | Text for a prompt dialog this step opens; implies accept. |
{
"type": "object",
"required": [
"key"
],
"properties": {
"key": {
"type": "string",
"anyOf": [
{
"enum": [
"Enter",
"Tab",
"Shift+Tab",
"Escape",
"Backspace",
"Delete",
"Space",
"ArrowDown",
"ArrowUp",
"ArrowLeft",
"ArrowRight",
"PageDown",
"PageUp",
"Home",
"End"
]
},
{
"pattern": "^[ -~]$"
}
],
"description": "One of Enter, Tab, Shift+Tab, Escape, Backspace, Delete, Space, ArrowDown, ArrowUp, ArrowLeft, ArrowRight, PageDown, PageUp, Home, End, or one character such as a or 5."
},
"dialog": {
"enum": [
"accept",
"dismiss"
],
"type": "string",
"description": "How to answer a native dialog (confirm, prompt, 'leave this page?') this step opens: accept presses OK, dismiss presses Cancel. Default: OK for an alert, Cancel for every other dialog."
},
"repeat": {
"type": "integer",
"maximum": 20,
"minimum": 1,
"description": "Times to press it. Default 1."
},
"dialog_text": {
"type": "string",
"maxLength": 1000,
"description": "Text for a prompt dialog this step opens; implies accept."
}
},
"additionalProperties": false
}The whole current page: its text (up to 20,000 characters) and a numbered list of its links, buttons, fields and other controls, open dialogs first. Use it on a new page or when a step's answer is not enough; `element` reads only inside one element (a dialog, a form, a list). Never returns field values, cookies or storage.
| Argument | Type | Description |
|---|---|---|
| element | integer | Read only inside this element. |
{
"type": "object",
"properties": {
"element": {
"type": "integer",
"minimum": 1,
"description": "Read only inside this element."
}
},
"additionalProperties": false
}A JPEG of the visible part of the page. Use it for boards, canvases, maps, charts and layout that the text does not show, then click or drag by `x`, `y` of the image.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}Scrolls with the mouse wheel: `down` or `up` by `screens`, to `top` or `bottom`, until `element` is in view, or inside a panel or list (`inside`). Content that loads on scroll appears. Answers the page after it: the elements and text in view, with the same numbers.
| Argument | Type | Description |
|---|---|---|
| inside | integer | Scroll inside this element, not the page. |
| element | integer | Scroll until this element is in view. |
| screens | number | Viewport heights, for down and up. Default: 0.8. |
| direction | string | Default: down. |
{
"type": "object",
"properties": {
"inside": {
"type": "integer",
"minimum": 1,
"description": "Scroll inside this element, not the page."
},
"element": {
"type": "integer",
"minimum": 1,
"description": "Scroll until this element is in view."
},
"screens": {
"type": "number",
"maximum": 10,
"description": "Viewport heights, for down and up. Default: 0.8.",
"exclusiveMinimum": 0
},
"direction": {
"enum": [
"down",
"up",
"top",
"bottom"
],
"type": "string",
"description": "Default: down."
}
},
"additionalProperties": false
}Chooses `option` (its label as listed, or its value) in drop-down `element`. For a home-made drop-down, click it, then click the option. Answers the page after it: the elements and text in view, with the same numbers.
| Argument | Type | Description |
|---|---|---|
| dialog | string | How to answer a native dialog (confirm, prompt, 'leave this page?') this step opens: accept presses OK, dismiss presses Cancel. Default: OK for an alert, Cancel for every other dialog. |
| option* | string | The option. |
| element* | integer | The element's number from the last read or step answer. |
| dialog_text | string | Text for a prompt dialog this step opens; implies accept. |
{
"type": "object",
"required": [
"element",
"option"
],
"properties": {
"dialog": {
"enum": [
"accept",
"dismiss"
],
"type": "string",
"description": "How to answer a native dialog (confirm, prompt, 'leave this page?') this step opens: accept presses OK, dismiss presses Cancel. Default: OK for an alert, Cancel for every other dialog."
},
"option": {
"type": "string",
"maxLength": 300,
"description": "The option."
},
"element": {
"type": "integer",
"minimum": 1,
"description": "The element's number from the last read or step answer."
},
"dialog_text": {
"type": "string",
"maxLength": 1000,
"description": "Text for a prompt dialog this step opens; implies accept."
}
},
"additionalProperties": false
}Types `text` into field `element`, replacing what it held; `submit` presses Enter after it. For several fields use fill_form. Without `element` the text goes where the focus is, as a person types after clicking: for spreadsheet cells and editors that read does not number (Google Sheets, Docs), click the place first; there a tab in `text` presses Tab and a line break Enter, so one call fills a table. Answers the page after it: the elements and text in view, with the same numbers. Password, card and one-time code fields are refused: the user types them.
| Argument | Type | Description |
|---|---|---|
| text* | string | The text to type. |
| dialog | string | How to answer a native dialog (confirm, prompt, 'leave this page?') this step opens: accept presses OK, dismiss presses Cancel. Default: OK for an alert, Cancel for every other dialog. |
| slowly | boolean | Key by key, for a search or address field whose suggestions do not appear. |
| submit | boolean | Press Enter after typing, e.g. to search. |
| element | integer | The field's number from the last read. Leave it out to type where the focus is. |
| dialog_text | string | Text for a prompt dialog this step opens; implies accept. |
{
"type": "object",
"required": [
"text"
],
"properties": {
"text": {
"type": "string",
"maxLength": 5000,
"description": "The text to type."
},
"dialog": {
"enum": [
"accept",
"dismiss"
],
"type": "string",
"description": "How to answer a native dialog (confirm, prompt, 'leave this page?') this step opens: accept presses OK, dismiss presses Cancel. Default: OK for an alert, Cancel for every other dialog."
},
"slowly": {
"type": "boolean",
"description": "Key by key, for a search or address field whose suggestions do not appear."
},
"submit": {
"type": "boolean",
"description": "Press Enter after typing, e.g. to search."
},
"element": {
"type": "integer",
"minimum": 1,
"description": "The field's number from the last read. Leave it out to type where the focus is."
},
"dialog_text": {
"type": "string",
"maxLength": 1000,
"description": "Text for a prompt dialog this step opens; implies accept."
}
},
"additionalProperties": false
}Puts files into file field or upload button `element`: each file is {"url": "https://..."} or {"file_id": "..."} of a file uploaded to Cotlet; up to 10 files, 20 MB each. Answers the page after it: the elements and text in view, with the same numbers.
| Argument | Type | Description |
|---|---|---|
| files* | array | The files. |
| element* | integer | The element's number from the last read or step answer. |
{
"type": "object",
"required": [
"element",
"files"
],
"properties": {
"files": {
"type": "array",
"items": {
"type": "object",
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "A public file URL."
},
"file_id": {
"type": "string",
"description": "A file uploaded to Cotlet."
}
},
"additionalProperties": false
},
"maxItems": 10,
"minItems": 1,
"description": "The files."
},
"element": {
"type": "integer",
"minimum": 1,
"description": "The element's number from the last read or step answer."
}
},
"additionalProperties": false
}Waits until `text` shows on the page (at most `seconds`, default 5, up to 20), or just `seconds`: for results that load slowly. Says whether the text appeared. Answers the page after it: the elements and text in view, with the same numbers.
| Argument | Type | Description |
|---|---|---|
| text | string | Text to wait for. |
| seconds | number | At most. |
{
"type": "object",
"properties": {
"text": {
"type": "string",
"maxLength": 200,
"description": "Text to wait for."
},
"seconds": {
"type": "number",
"maximum": 20,
"description": "At most.",
"exclusiveMinimum": 0
}
},
"additionalProperties": false
}Status of an earlier Cotlet call, by its call_id: pending (waits for the owner's approval in the Cotlet console), approved, running, success, rejected, expired, blocked or failed. For a call that answered with status pending or running.
| Argument | Type | Description |
|---|---|---|
| call_id* | string | call_id from the earlier call |
{
"type": "object",
"required": [
"call_id"
],
"properties": {
"call_id": {
"type": "string",
"description": "call_id from the earlier call"
}
},
"additionalProperties": false
}Sends a report to the Cotlet team: a tool that failed or returned wrong data, an error you could not get past, or a step the browser could not do, with the page, the step and what you saw. A missing dedicated tool is not a problem to report: do the task in the browser. A feature the user asks for goes as feature_request. A report promises nothing: tell the user it was sent, never that something will be built or fixed, or when. The report carries the error text and call_id when there is one, never passwords or tokens. Needs the user's Cotlet API key or sign-in.
| Argument | Type | Description |
|---|---|---|
| app | any | App slug the report is about, e.g. 'skool', or for a site in the web browser its host, e.g. 'app.example.com'. |
| kind* | string | bug: a tool did the wrong thing or returned wrong data. error: a call failed or returned an error you could not get past. feature_request: something new the user asked for. missing_feature: a step the task needed that you tried and could not do, in the browser or with a tool. other: anything else. |
| tool | any | Tool or endpoint name, e.g. 'skool_list_members'. |
| title* | string | One line, e.g. 'skool_list_members stops after 50 members'. |
| client | any | Agent or tool sending this, e.g. 'Claude Code'. |
| call_id | any | call_id of the call that went wrong, if any. |
| description* | string | What the user asked for, what you tried, what you expected and what happened, with the error text if there was one. No passwords, tokens or other secrets. |
{
"type": "object",
"title": "AgentReportCreate",
"required": [
"kind",
"title",
"description"
],
"properties": {
"app": {
"anyOf": [
{
"type": "string",
"maxLength": 80
},
{
"type": "null"
}
],
"title": "App",
"default": null,
"description": "App slug the report is about, e.g. 'skool', or for a site in the web browser its host, e.g. 'app.example.com'."
},
"kind": {
"enum": [
"bug",
"error",
"feature_request",
"missing_feature",
"other"
],
"type": "string",
"title": "Kind",
"description": "bug: a tool did the wrong thing or returned wrong data. error: a call failed or returned an error you could not get past. feature_request: something new the user asked for. missing_feature: a step the task needed that you tried and could not do, in the browser or with a tool. other: anything else."
},
"tool": {
"anyOf": [
{
"type": "string",
"maxLength": 160
},
{
"type": "null"
}
],
"title": "Tool",
"default": null,
"description": "Tool or endpoint name, e.g. 'skool_list_members'."
},
"title": {
"type": "string",
"title": "Title",
"maxLength": 200,
"minLength": 3,
"description": "One line, e.g. 'skool_list_members stops after 50 members'."
},
"client": {
"anyOf": [
{
"type": "string",
"maxLength": 80
},
{
"type": "null"
}
],
"title": "Client",
"default": null,
"description": "Agent or tool sending this, e.g. 'Claude Code'."
},
"call_id": {
"anyOf": [
{
"type": "string",
"format": "uuid"
},
{
"type": "null"
}
],
"title": "Call Id",
"default": null,
"description": "call_id of the call that went wrong, if any."
},
"description": {
"type": "string",
"title": "Description",
"maxLength": 5000,
"minLength": 10,
"description": "What the user asked for, what you tried, what you expected and what happened, with the error text if there was one. No passwords, tokens or other secrets."
}
},
"description": "Body of POST /api/v1/reports and the arguments of the MCP tool cotlet_report_issue.",
"additionalProperties": false
}Requests access to apps for the user's workspace, as Request access in the console: every app is granted at once. Not needed to work in an app: the user's AI works in any web app in their Web browser with cotlet_app_guide. An app with dedicated tools gets them after the user signs in to it in their Cloud Browser. Access says nothing about whether a task works there: check that in the browser. Takes app slugs as listed at https://cotlet.dev/api/v1/apps. Free. Needs the user's Cotlet API key or sign-in.
| Argument | Type | Description |
|---|---|---|
| apps* | array | App slugs, e.g. ["skool", "substack"]. |
| use_case | string | What the user wants the agent to do in these apps, in their words. |
{
"type": "object",
"required": [
"apps"
],
"properties": {
"apps": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 10,
"minItems": 1,
"description": "App slugs, e.g. [\"skool\", \"substack\"]."
},
"use_case": {
"type": "string",
"maxLength": 1000,
"description": "What the user wants the agent to do in these apps, in their words."
}
},
"additionalProperties": false
}Returns a one-time upload_url and a file_id for a local file (an image for a post, an attachment). The file is sent to upload_url with an HTTP PUT; an argument that takes a file accepts {"file_id": "..."}. Up to 25 MB, the URL works once. Free. Needs the user's Cotlet API key or sign-in.
| Argument | Type | Description |
|---|---|---|
| name | string | File name, e.g. photo.jpg. |
| content_type | string | MIME type, e.g. image/jpeg. |
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "File name, e.g. photo.jpg."
},
"content_type": {
"type": "string",
"description": "MIME type, e.g. image/jpeg."
}
},
"additionalProperties": false
}The Cotlet account this connection acts as: email, workspace, access status, the API key or OAuth client in use with its scope, the apps the workspace may call and its credit balance. Free. Needs the user's Cotlet API key or sign-in.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}Read a Citation Tracker report: where the business is listed, missing, or listed with wrong NAP data. Returns the top-site coverage and citation score, name, address, postcode and phone accuracy counts, the competitors' citation counts and the citations themselves: site, type, authority, whether the business is listed and with which name, address and phone, the fields that do not match, duplicates and whether Citation Builder can submit to that site. Top sites first, then by authority.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Most citations returned, default 100. |
| filter | string | Which citations to return. Default all. |
| report_id* | integer | report_id from list_citation_tracker_reports. |
{
"type": "object",
"required": [
"report_id"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 500,
"minimum": 1,
"description": "Most citations returned, default 100."
},
"filter": {
"enum": [
"all",
"listed",
"not_listed",
"nap_issues",
"top_sites_missing"
],
"type": "string",
"description": "Which citations to return. Default all."
},
"report_id": {
"type": "integer",
"minimum": 1,
"description": "report_id from list_citation_tracker_reports."
}
},
"additionalProperties": false
}Read a location's Google Business Profile Audit: profile data, NAP check, local ranking factors. Returns the audited Google Business Profile (name, address, phone, website, category, description, verified, rating, reviews, photos, hours) and what changed since the last run, how the profile's name, address, postcode and phone match the location, local ranking factors, duplicates, recent reviews and, per keyword, the location's local rank with the top competitors. A location without a Google Business Profile has no audit: `audit` is null and `note` says what to set up.
| Argument | Type | Description |
|---|---|---|
| location_id* | integer | location_id from list_locations. |
{
"type": "object",
"required": [
"location_id"
],
"properties": {
"location_id": {
"type": "integer",
"minimum": 1,
"description": "location_id from list_locations."
}
},
"additionalProperties": false
}Read a location's Local Search Grid: the Google Maps rank at each grid point, and competitors. Returns the grid (size, points, distance, center), the average rank over all keywords, each keyword's latest run (average rank, points ranked 1-3, 4-10, 11+), and for one keyword and run (the first keyword and the latest run unless given) the rank at every grid point and the top 10 competitors. A location without a Google Business Profile has no grid: `report` is null and `note` says what to set up.
| Argument | Type | Description |
|---|---|---|
| run_id | string | A run from the keyword's `runs`. Default: the latest. |
| keyword | string | A keyword of the report. Default: the first. |
| location_id* | integer | location_id from list_locations. |
{
"type": "object",
"required": [
"location_id"
],
"properties": {
"run_id": {
"type": "string",
"maxLength": 64,
"description": "A run from the keyword's `runs`. Default: the latest."
},
"keyword": {
"type": "string",
"maxLength": 200,
"description": "A keyword of the report. Default: the first."
},
"location_id": {
"type": "integer",
"minimum": 1,
"description": "location_id from list_locations."
}
},
"additionalProperties": false
}Read one location's business details: name, address, phone, website, category, hours, descriptions. Returns the record BrightLocal compares citations and listings against (NAP): business name, address, phones, website, category, contact person, short and long description, year founded, employees, payment methods, services and opening hours.
| Argument | Type | Description |
|---|---|---|
| location_id* | integer | location_id from list_locations. |
{
"type": "object",
"required": [
"location_id"
],
"properties": {
"location_id": {
"type": "integer",
"minimum": 1,
"description": "location_id from list_locations."
}
},
"additionalProperties": false
}Read a Rank Tracker report: each keyword's position on Google, Maps and the local pack, with changes. Returns one run of the report (the latest unless run_id is given) against the run before it: per keyword the search volume and, per search engine, the rank (null = not in the top 50), previous rank, change and ranking URL; the keywords up, down, gained and lost; the competitors tracked. `runs` lists every run.
| Argument | Type | Description |
|---|---|---|
| run_id | integer | A run from `runs`. Default: the latest. |
| report_id* | integer | report_id from list_rank_tracker_reports. |
| location_id* | integer | location_id of the report, from list_rank_tracker_reports. |
{
"type": "object",
"required": [
"report_id",
"location_id"
],
"properties": {
"run_id": {
"type": "integer",
"minimum": 1,
"description": "A run from `runs`. Default: the latest."
},
"report_id": {
"type": "integer",
"minimum": 1,
"description": "report_id from list_rank_tracker_reports."
},
"location_id": {
"type": "integer",
"minimum": 1,
"description": "location_id of the report, from list_rank_tracker_reports."
}
},
"additionalProperties": false
}Read a location's star rating and review counts overall and per review site. Returns the average star rating and total reviews over all tracked sites, the count per star rating, and per site with a listing: its rating, total, new reviews, reviews in the last 30 days, this and last month and this year, and the profile link. A location without a Reputation Manager report (BrightLocal Grow plan) answers zeros and a note.
| Argument | Type | Description |
|---|---|---|
| location_id* | integer | location_id from list_locations. |
{
"type": "object",
"required": [
"location_id"
],
"properties": {
"location_id": {
"type": "integer",
"minimum": 1,
"description": "location_id from list_locations."
}
},
"additionalProperties": false
}List Active Sync alerts: changes found on a location's listings on other sites. Each alert is a field (name, address, phone, website, category, description) whose value on an external listing (Google Business Profile, Facebook, Bing, Apple Maps, Yelp) differs from the location's data in BrightLocal. Alerts appear only for locations with Active Sync connections. new_alerts counts the unseen ones.
| Argument | Type | Description |
|---|---|---|
| query | string | Location name to search for. |
| cursor | string | next_cursor from the previous call. |
{
"type": "object",
"properties": {
"query": {
"type": "string",
"maxLength": 100,
"description": "Location name to search for."
},
"cursor": {
"type": "string",
"description": "next_cursor from the previous call."
}
},
"additionalProperties": false
}List Citation Builder campaigns with their status, from Saved to Submitting To Sites and Complete. One row per campaign: location, status (Saved, Reviewing Data, On Hold, Submitting To Sites, Live Listing Checks, Complete), payment date, number of listings ordered, data aggregators and alerts. Saved campaigns are not paid or submitted yet. location_id filters each page after BrightLocal returns it, so a page can come back short while next_cursor continues; total counts all campaigns.
| Argument | Type | Description |
|---|---|---|
| cursor | string | next_cursor from the previous call. |
| status | string | Only campaigns in this status. |
| location_id | integer | Only campaigns of this location. |
{
"type": "object",
"properties": {
"cursor": {
"type": "string",
"description": "next_cursor from the previous call."
},
"status": {
"enum": [
"Saved",
"Reviewing Data",
"On Hold",
"Submitting To Sites",
"Live Listing Checks",
"Complete"
],
"type": "string",
"description": "Only campaigns in this status."
},
"location_id": {
"type": "integer",
"minimum": 1,
"description": "Only campaigns of this location."
}
},
"additionalProperties": false
}List Citation Tracker reports with their last run, live citations and competitor citations. One row per report: location, reference, schedule, last run, the number of live citations (found and indexed by Google) and of competitor citations (sites your competitors are listed on). Read a report with get_citation_tracker_report. 20 per page. location_id filters each page after BrightLocal returns it, so a page can come back short while next_cursor continues.
| Argument | Type | Description |
|---|---|---|
| cursor | string | next_cursor from the previous call. |
| location_id | integer | Only reports of this location. |
{
"type": "object",
"properties": {
"cursor": {
"type": "string",
"description": "next_cursor from the previous call."
},
"location_id": {
"type": "integer",
"minimum": 1,
"description": "Only reports of this location."
}
},
"additionalProperties": false
}List Local Search Grid reports: keywords, grid size and the average Google Maps rank across the grid. One row per report: location, keywords, schedule, last run, status, grid size and points, average rank over all keywords and its change, credits a manual re-run costs. Local Search Grid needs the location's Google Business Profile, so locations without one have no rows. location_id filters each page after BrightLocal returns it, so a page can come back short while next_cursor continues. Read a grid with get_local_search_grid_report.
| Argument | Type | Description |
|---|---|---|
| cursor | string | next_cursor from the previous call. |
| location_id | integer | Only reports of this location. |
{
"type": "object",
"properties": {
"cursor": {
"type": "string",
"description": "next_cursor from the previous call."
},
"location_id": {
"type": "integer",
"minimum": 1,
"description": "Only reports of this location."
}
},
"additionalProperties": false
}List the locations in the account with their rank, citation and review metrics, as on All Locations. Returns each location with its location_id, name, reference, city, status (active or ad_hoc) and the metrics of the All Locations page: average Google position and its change, rankings up, down and new, Local Search Grid average, citation score, live citations, star rating, total and recent reviews, Active Sync alerts. `reports` says which tools have a report on the location. 50 per page.
| Argument | Type | Description |
|---|---|---|
| query | string | Business name, reference or zip code to search for. |
| cursor | string | next_cursor from the previous call. |
| status | string | Only locations in this state. Default: active and ad_hoc. |
{
"type": "object",
"properties": {
"query": {
"type": "string",
"maxLength": 100,
"description": "Business name, reference or zip code to search for."
},
"cursor": {
"type": "string",
"description": "next_cursor from the previous call."
},
"status": {
"enum": [
"active",
"ad_hoc",
"archived"
],
"type": "string",
"description": "Only locations in this state. Default: active and ad_hoc."
}
},
"additionalProperties": false
}List Rank Tracker reports with their latest run and average Google position. One row per report: location, schedule (ad_hoc, weekly, monthly), date of the latest run, status, average Google position and its change, keywords and positions moved. average_google_position is null when no keyword ranks in the top 50. location_id filters each page after BrightLocal returns it, so a page can come back short while next_cursor continues; total counts all reports. Read a report with get_rank_tracker_report and its location_id.
| Argument | Type | Description |
|---|---|---|
| cursor | string | next_cursor from the previous call. |
| location_id | integer | Only reports of this location. |
{
"type": "object",
"properties": {
"cursor": {
"type": "string",
"description": "next_cursor from the previous call."
},
"location_id": {
"type": "integer",
"minimum": 1,
"description": "Only reports of this location."
}
},
"additionalProperties": false
}List a location's reviews from all tracked review sites, newest first, with rating, text and status. Returns reviews Reputation Manager collected for the location: date, star rating, reviewer, site, text, status (unread, action_required, do_not_respond, manually_responded, auto_responded, pending_removal, successfully_removed, removal_failed) and whether BrightLocal can post a reply (can_reply, needs a connected Google Business Profile or Facebook page). Filter by rating and site. A location without a Reputation Manager report (BrightLocal Grow plan, with the Google Business Profile or Facebook page connected) answers an empty list and a note.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Reviews per page, default 25. |
| cursor | string | next_cursor from the previous call. |
| rating | array | Only reviews with these star ratings, e.g. [1, 2]. |
| source | string | Only this review site, e.g. google, yelp, facebook. |
| location_id* | integer | location_id from list_locations. |
{
"type": "object",
"required": [
"location_id"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "Reviews per page, default 25."
},
"cursor": {
"type": "string",
"description": "next_cursor from the previous call."
},
"rating": {
"type": "array",
"items": {
"type": "integer",
"maximum": 5,
"minimum": 1
},
"maxItems": 5,
"description": "Only reviews with these star ratings, e.g. [1, 2]."
},
"source": {
"type": "string",
"maxLength": 50,
"description": "Only this review site, e.g. google, yelp, facebook."
},
"location_id": {
"type": "integer",
"minimum": 1,
"description": "location_id from list_locations."
}
},
"additionalProperties": false
}Run one of a location's reports now, as the Re-run button does. Starts a manual run of the location's report of that type, as the Re-run button does. A manual run uses one of the account's ad-hoc run credits; a Local Search Grid run also uses grid credits. After a trial ends BrightLocal stops runs. local_search_grid and gbp_audit need the location's Google Business Profile, reputation_manager needs Reputation Manager (Grow plan); without them the call is refused with the reason. The run takes minutes; read the report afterwards.
| Argument | Type | Description |
|---|---|---|
| location_id* | integer | location_id from list_locations. |
| report_type* | string | Which of the location's reports to run. |
{
"type": "object",
"required": [
"location_id",
"report_type"
],
"properties": {
"location_id": {
"type": "integer",
"minimum": 1,
"description": "location_id from list_locations."
},
"report_type": {
"enum": [
"rank_tracker",
"citation_tracker",
"local_search_grid",
"reputation_manager",
"gbp_audit"
],
"type": "string",
"description": "Which of the location's reports to run."
}
},
"additionalProperties": false
}Post a public reply to a review on Google or Facebook through BrightLocal. Publishes the text as the business's reply under the review on its site and marks the review Manually Responded. Only reviews with can_reply true in list_reviews accept a reply: the location needs a connected Google Business Profile or Facebook page. The reviewer and anyone reading the review see it. The review must be among the location's latest 1000. Waits for the owner's approval.
| Argument | Type | Description |
|---|---|---|
| text* | string | The public reply. |
| review_id* | integer | review_id from list_reviews. |
| location_id* | integer | location_id from list_locations. |
{
"type": "object",
"required": [
"location_id",
"review_id",
"text"
],
"properties": {
"text": {
"type": "string",
"maxLength": 4000,
"minLength": 1,
"description": "The public reply."
},
"review_id": {
"type": "integer",
"minimum": 1,
"description": "review_id from list_reviews."
},
"location_id": {
"type": "integer",
"minimum": 1,
"description": "location_id from list_locations."
}
},
"additionalProperties": false
}Add or remove keywords tracked by a location's Rank Tracker report. Changes the keyword list of the location's Rank Tracker report and saves the report with its other settings unchanged. Up to 100 keywords per report. Keywords already tracked are not added twice. New keywords get positions on the next scheduled run, or now with rerun_report.
| Argument | Type | Description |
|---|---|---|
| add | array | Keywords to start tracking. |
| remove | array | Keywords to stop tracking. |
| location_id* | integer | location_id of the Rank Tracker report. |
{
"type": "object",
"required": [
"location_id"
],
"properties": {
"add": {
"type": "array",
"items": {
"type": "string",
"maxLength": 150,
"minLength": 1
},
"maxItems": 100,
"description": "Keywords to start tracking."
},
"remove": {
"type": "array",
"items": {
"type": "string",
"maxLength": 150,
"minLength": 1
},
"maxItems": 100,
"description": "Keywords to stop tracking."
},
"location_id": {
"type": "integer",
"minimum": 1,
"description": "location_id of the Rank Tracker report."
}
},
"minProperties": 2,
"additionalProperties": false
}We read every tool's name, description and inputs the way the model will, looking for instructions hidden from you. A clean result means no warning signs, not a guarantee. Scanned Nov 9, 2026.