Mark
Server Details
Mark runs your content, marketing, and advertising flexibly. Use Mark from your favorite AI assistant or on the platform.
- Status
- Healthy
- Uptime
- 100.0% over 23 days
- OAuth
- Works in Glama
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
TDQS
Scored across 104 tools
Several clusters overlap, especially the many get_* reporting tools (get_ai_visibility, get_buyer_question_answers, get_competitor_ai_detail, get_competitor_scorecard, get_search_performance, get_page_detail, get_performance_overview, get_content_performance) and the post lifecycle tools. Descriptions are exceptionally detailed and cross-reference related tools, which mitigates but does not eliminate misselection risk.
All tool names use snake_case with a consistent verb_noun structure (add_asset, get_post, save_claim, delete_strategy_item). Minor deviations like approve_post_from_preview or set_up_market are still readable and follow the same style.
104 tools is far beyond the typical 3–15 range and exceeds the 50+ threshold for an extreme mismatch. While the platform's domain is broad, the sheer number makes it unwieldy for an agent to navigate.
The surface covers an impressive breadth: posts (create, edit, submit, approve, review, schedule, publish, archive, delete, unpublish), assets, claims/sources, keywords, competitors, AI visibility, CMS, brand profile, strategy items, ideas, connections, and analytics. No obvious functional gaps for the stated content-marketing/SEO/AI-visibility purpose.
Available Tools
108 toolsadd_assetAdd AssetAInspect
Adds an image, video or PDF to the library from a public URL, or starts a file upload. A PDF becomes kind document and attaches to LinkedIn posts only. For a public https URL, pass source url plus url. For a local file, pass source upload to get a one-time token; after the file is in storage, call again with source upload plus blobUrl, mime and size. Related: search_assets, save_post.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Public https URL when source is url. | |
| mime | No | MIME type when registering an upload. | |
| name | No | Optional display name. | |
| size | No | Byte size when registering an upload. | |
| width | No | Pixel width when registering an uploaded image or video. | |
| height | No | Pixel height when registering an uploaded image or video. | |
| source | Yes | url imports a public file; upload returns a one-time client token. | |
| blobUrl | No | After a client upload, the private Blob URL to register. | |
| fileName | No | Original file name when source is upload. | |
| durationMs | No | Duration in milliseconds when registering an uploaded video. |
Output Schema
| Name | Required | Description |
|---|---|---|
| asset | No | |
| upload | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the write/non-idempotent/open-world profile; the description adds genuinely useful behavioral context the annotations lack - the one-time token returned by the upload step, the required second call after the file reaches storage, and the constraint that PDFs become documents attachable to LinkedIn posts only. Missing details like token expiry or size limits keep it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then the mode-specific rules, then related tools - three tight sentences with no filler. Dense but every clause carries information; only slight comma-heavy phrasing costs a point.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 10-parameter mutation with an output schema (so return values need no explanation), the description covers the required two-step flow, mode selection, and the PDF restriction. Remaining gaps (auth requirements, size/type limits, token lifetime) are minor.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description goes beyond the field-by-field schema text by explaining cross-parameter sequencing: which fields go together for each source value and that blobUrl/mime/size are supplied on the second call. This adds conditional logic the schema does not express.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Adds an image, video or PDF to the library') and immediately distinguishes the two operational modes (public URL import vs. upload start). An agent can tell what this tool does without opening the schema, and it names search_assets and save_post as related siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says which parameters apply to which mode ('For a public https URL, pass source url plus url'; 'For a local file, pass source upload...'), including the two-phase upload sequence. It does not, however, state when to prefer this over update_asset or search_assets, so routing against siblings remains partly inferential.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_sourceAdd SourceAInspect
Adds a source to the Claims & sources page: pasted text (call notes, an audit, a spec sheet) with an optional link to the original. Claims quote a source's text, so body is required. Returns the source id. Use it as sourceId in save_claim, or as overlay evidence in update_brand_profile. To add a claim and its source in one call, pass source to save_claim instead. Related: save_claim, list_claims, update_brand_profile.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Link to the original, optional. | |
| body | Yes | The pasted text. Claim quotes are checked against it. | |
| title | Yes | What the source is, such as 'Q3 audit'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| source | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, destructiveHint=false, idempotentHint=false, so the safety profile is covered. The description adds that body is required because claim quotes are checked against it, and that the tool returns a source id used downstream. It doesn't discuss failure modes (e.g., rejecting ambiguous text) but adds meaningful write-behavior context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose, then the return value, then the routing and cross-references. Nothing is repeated; every sentence, including the Related line, earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Complete for a 3-param mutation tool with a 100% coverage schema and an output schema. The description covers purpose, required inputs, return value, and integration points without over-explaining.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is already 100%, so the schema documents url, body, and title. The description reinforces that body is required and enumerates example content types, but adds no syntax or format constraints beyond what the schema provides. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Adds a source to the Claims & sources page') and clarifies the domain concept by describing what a source is (pasted text like call notes, an audit, a spec sheet). An agent can distinguish this from save_claim, update_source, and delete_source without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing: use the returned id as sourceId in save_claim or as overlay evidence in update_brand_profile; to add a claim and its source in one call, pass source to save_claim. It names the alternatives and the conditions that select them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
analyze_domainAnalyze DomainARead-onlyIdempotentInspect
Looks up any domain (yours or a competitor's): view = overview | top_pages | page_keywords | backlinks. overview, top_pages and page_keywords fetch fresh data from the provider, 1 domain per call. For backlinks, refresh: true fetches a fresh snapshot; otherwise it returns the latest one. Related: research_keywords, get_rankings.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Required for page_keywords: the page URL. | |
| view | Yes | Which cut of the domain to return. | |
| domain | Yes | example.com or a full URL. | |
| siteId | No | Workspace site id for the backlinks view. | |
| refresh | No | For backlinks, fetch a fresh snapshot. | |
| languageCode | No | Language code. Defaults to the priority market. | |
| locationCode | No | DataForSEO location. Defaults to the priority market. |
Output Schema
| Name | Required | Description |
|---|---|---|
| view | Yes | |
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the bar is lower; the description still adds real value by disclosing that overview/top_pages/page_keywords hit the provider for fresh data, that only 1 domain is processed per call, and that backlinks returns a cached snapshot unless refresh:true.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the core purpose and view enumeration, followed by the two behavioral caveats. No filler, though the view list is largely mirrored by the enum.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be described; the description covers view behavior, freshness semantics, and related tools. It leaves minor gaps on location/language defaults and the siteId prerequisite, but is otherwise complete for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema by explaining what each view value does and how refresh interacts with backlinks specifically. It does not clarify languageCode/locationCode defaults beyond the schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Looks up any domain, yours or a competitor's') and enumerates the four views, so the agent knows exactly what the tool returns. It stops short of sharply distinguishing itself from siblings beyond listing 'Related' tools, so 4 rather than 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context: use for domain lookups with one of four view modes, and the refresh semantics for backlinks. It names related tools (research_keywords, get_rankings) but does not say when to prefer those over this one, so no exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
approve_post_from_previewApprove From PreviewADestructiveInspect
Approves one post at an exact rev. Only the Approve button in Mark's post preview calls this, after a person clicks it. Agents never call it: to approve, use approve_posts, and only when the user has explicitly asked. Related: approve_posts, get_post.
| Name | Required | Description | Default |
|---|---|---|---|
| rev | Yes | Exact rev the preview showed. | |
| postId | Yes | Post id. |
Output Schema
| Name | Required | Description |
|---|---|---|
| post | Yes | |
| approval | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, readOnlyHint=false and idempotentHint=false, covering the safety profile. The description adds valuable non-annotation context — that this is a human-clicked UI path, not an agent path — but says nothing about blast radius, reversibility, or auth requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose, then the restriction, then the alternative route — a logical order with no filler sentences. Mild redundancy in the trailing 'Related: approve_posts, get_post' line, since approve_posts was already named above.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need no explanation. The description fully covers purpose, the negative routing case, and the correct alternative, so an agent has everything needed to decide not to call it and what to call instead.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, with both parameters documented ('Post id', 'Exact rev the preview showed'). The description restates the exact-rev constraint but adds no syntax, format, or retrieval guidance beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with scope: 'Approves one post at an exact rev.' It explicitly distinguishes itself from the sibling approve_posts by noting this variant is only reachable via a UI button, so an agent can tell them apart without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-not guidance ('Agents never call it') and routes to the correct alternative ('to approve, use approve_posts, and only when the user has explicitly asked'). The condition that selects the sibling is spelled out, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
approve_postsApprove PostsADestructiveInspect
Approves the exact revisions given ([{postId, rev}], where rev comes from get_post/search_posts). There is no separate publish step. For website channels the result names the next CMS step (queued at a time, or a CMS draft that does not go live). An approved social post reads approved for a few seconds while Mark hands it to the publisher, then scheduled, and publishes at its scheduled time; confirm with get_post. An approved email stays approved: Mark doesn't send email yet. An approved LinkedIn Article stays approved with handoff publish_by_hand (publish_now once its slot time passes) until someone records its live URL with record_post_published. Each approved outcome carries handoff: handing_off, or stuck with the reason and fix when the post can't go (no scheduled time, no connected account for the channel, or Mark couldn't start the handoff), so you don't have to wait to learn it. A post whose handoff couldn't start can still read handing_off on get_post for up to 5 minutes after approval; trust this result. A stale rev is refused. On a channel set to admins only, only workspace admins can approve; anyone else gets those posts back skipped. Only use it when the user has explicitly asked to approve. Related: get_post, search_posts, review_post.
| Name | Required | Description | Default |
|---|---|---|---|
| posts | Yes | Pairs of postId and rev to approve. |
Output Schema
| Name | Required | Description |
|---|---|---|
| outcomes | Yes | |
| submitted | Yes | |
| lifecycleWarnings | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations already declaring destructiveHint=true and idempotentHint=false, the description still adds substantial behavioral context beyond them: there is no separate publish step, outcomes vary by channel (social goes scheduled, email stays approved, LinkedIn Article waits on publish_by_hand), stale revs are refused, admins-only channels return skipped posts, and the handoff/stuck result is authoritative even if get_post lags 5 minutes. This is unusually rich disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but it is front-loaded with the action and scope, then proceeds through channel-specific outcomes and failure modes in roughly descending importance. Some of the per-channel outcome enumeration overlaps with what the existing output schema would convey, which keeps it short of a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter mutation tool with annotations and an output schema already present, the description covers everything an agent needs: input provenance, the no-publish-step model, per-channel end states, permission constraints, staleness handling, and where to verify results. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already documents postId, rev, and their provenance. The description's only parameter-level addition is that a stale rev is refused; otherwise the single param is fully covered by the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Approves the exact revisions given') and immediately scopes the input to [{postId, rev}]. It is readily distinguishable from siblings like review_post, submit_post, and get_post, which are called out by name as the source of rev and as related tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear precondition/exclusion: 'Only use it when the user has explicitly asked to approve,' and states that rev must come from get_post or search_posts. It falls just short of 5 because it doesn't explicitly route the agent to an alternative action (e.g., submit_post) when approval isn't requested.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
archive_postArchive PostAIdempotentInspect
Takes a post out of the publish path so it will not go live. The post stays in the workspace; this is not a delete. Posts that are already live, queued to publish, or approved cannot be archived — they stay as they are. Archiving a post that is not a draft (in review, sent back, failed or missed) rejects it, so on a channel set to admins only (approverRole: approver) only workspace admins can archive it; drafts stay open to everyone. Calling it again on a post that will not publish is a no-op. Archiving a website post that sent a preview to its CMS deletes that preview draft when Mark may; otherwise cmsPreview says it is still in the CMS, where, and why, and so does the post's review note. Related: delete_post, review_post, search_posts.
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | Optional reason stored on the post. | |
| postId | Yes | The post to archive. |
Output Schema
| Name | Required | Description |
|---|---|---|
| postId | Yes | |
| status | Yes | |
| outcome | Yes | |
| cmsPreview | No | The post's preview draft in the website CMS: removed (Mark deleted it), or left_in_cms with its previewUrl and why (cannot_delete: Mark's API key may not delete it; edited: changed in the CMS; linked: a page that was in the CMS before Mark used it; live: a live page; unreachable: the CMS did not answer). Absent when the post had no preview. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=true), and the description adds substantial context beyond them: the post is retained in the workspace, re-calling is a no-op, non-draft posts are rejected, and CMS preview drafts may be deleted as a side effect. Minor tension worth noting: it discloses a genuine deletion ('deletes that preview draft') while destructiveHint=false, though that applies to the primary resource, so it does not rise to a contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core action and the not-a-delete distinction, then layers preconditions and edge cases. The length is defensible given the mutation semantics, permissions, and CMS interaction it must cover, though the CMS-preview sentence is dense and could be tightened.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, yet the description still explains the cmsPreview/review-note failure path, which is the piece an agent most needs to interpret a partial outcome. Combined with permission rules, idempotency, and preconditions, nothing needed to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with only two parameters, so the schema already carries the full parameter burden. The description adds a little meaning by referencing the post's 'review note' and the cmsPreview output field, but gives no additional syntax or constraint for note or postId beyond the schema text. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Takes a post out of the publish path') and immediately disambiguates from the most confusable sibling by saying 'this is not a delete.' The named related tools (delete_post, review_post, search_posts) let an agent place it in the toolset without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly enumerates when the tool will NOT act ('already live, queued to publish, or approved cannot be archived'), states the permission precondition for restricted channels (approverRole: approver), and names alternatives. This is as close to a decision rule as a description gets.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_ai_assistant_trackingCheck AI Assistant TrackingARead-onlyIdempotentInspect
Checks whether ChatGPT, Perplexity and other AI assistants are tracked on a site (probe plus PostHog). Takes up to about 30 seconds. Related: list_sites, get_ai_visibility.
| Name | Required | Description | Default |
|---|---|---|---|
| siteId | Yes | Site id from list_sites. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| snapshot | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnly, idempotent, non-destructive and openWorld, so the lower bar applies. The description adds genuinely useful context beyond them: the ~30 second runtime (latency expectation) and that the check combines a live probe with PostHog data.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences, zero filler. The core purpose is front-loaded and the runtime plus related-tool pointers follow as supporting detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be explained, annotations cover the safety profile, and the description supplies latency and method. What is only loosely covered is the boundary with get_ai_visibility, but the definition is otherwise sufficient to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With a single parameter and 100% schema description coverage, the schema already explains siteId ('Site id from list_sites'). The description adds no further parameter meaning, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (checks) and a precise object (whether ChatGPT, Perplexity and other AI assistants are tracked on a site), plus the mechanism (probe plus PostHog). This is clearly distinguishable from siblings like get_ai_visibility or check_site_readiness.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'Related: list_sites, get_ai_visibility' note implies list_sites supplies the siteId and that get_ai_visibility is the adjacent tool, but it never states when to prefer this tool versus get_ai_visibility or what preconditions apply. Usage is inferable rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_draftCheck DraftARead-onlyIdempotentInspect
Runs Mark's content checks on draft text without saving it (six on every channel, plus two on a competitor_page): exclusion (phrases this workspace blocks or warns on), char_limit, required_meta, ai_fluff (generic AI-sounding words), unsourced_number (percentages, money and multipliers no active claim states), and placeholder (a marker left for the writer, such as [needs source], [TBD] or a bare TODO, ignored inside code, link targets and URLs; it fails). A competitor_page also gets table (a markdown table; it fails, use headings and lists) and open_placeholder (a [confirm: …] fact left to confirm; it fails), and its unsourced_number fails instead of warning. Each result is pass, warn or fail with the matched text, field and position; exclusion matches carry the rule's reason. A fail is what submit_post refuses on a draft; warnings never block. For an X thread, pass assetIds to check each post's media too. Uses this workspace's active exclusions and claims. Writes nothing. Related: save_post, get_channel_rules, get_brand_context, list_claims.
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | Draft body / caption. | |
| meta | No | Channel-specific fields from get_channel_rules. | |
| channel | Yes | Channel id such as linkedin or blog. | |
| assetIds | No | X threads: the asset ids save_post would get, so required_meta checks each post's media (4 images, or 1 video, or 1 GIF) with meta.threadMedia. |
Output Schema
| Name | Required | Description |
|---|---|---|
| checks | Yes | Mark's content checks on the saved content: exclusion, char_limit, required_meta, ai_fluff, unsourced_number, placeholder, and on a competitor_page also table and open_placeholder. On a draft, a fail stops submit_post; warn never does. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint/non-destructive, and the description reinforces this with 'Writes nothing' while adding genuine context: the per-channel composition of checks, the fail-vs-warn distinction and its blocking consequence, competitor_page-specific failures, and that exclusion matches carry the rule's reason. This goes well beyond the structured safety hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose and non-saving behavior are front-loaded, and the trailing 'Related:' line is efficient. The dense parenthetical enumerations of checks are information-rich but heavy; a slightly tighter structure would read better, though little is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not describe return shapes, and it still covers result states, matched-text/field/position, workspace exclusion and claim sourcing, and cross-channel differences. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: it explains the assetIds usage condition (X thread media validated as 4 images / 1 video / 1 GIF) and ties meta to required_meta and get_channel_rules. That exceeds what the schema text alone conveys.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Runs Mark's content checks on draft text without saving it') and enumerates exactly what is checked per channel, which cleanly separates it from write-oriented siblings like save_post and submit_post. An agent can distinguish this from save_post without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It tells the agent the outcome matters for submission ('A fail is what submit_post refuses on a draft; warnings never block'), and it names related tools (save_post, get_channel_rules, get_brand_context, list_claims), plus a condition for assetIds on X threads. It stops short of an explicit 'use this before calling submit_post instead of X' statement, so it is clear context but not a full when/when-not rulebook.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_keyword_audienceCheck Keyword AudienceARead-onlyIdempotentInspect
Looks at who currently ranks for a keyword, to judge whether its searchers match your audience. Each call is 1 search: it fetches the current Google top 10. Pass a savedKeywordId from list_saved_keywords, or a plain keyword to look it up before saving: that saves and tracks nothing. A plain keyword uses the priority market unless you pass both locationCode and languageCode. Related: save_keywords, research_keywords.
| Name | Required | Description | Default |
|---|---|---|---|
| keyword | No | A keyword to look up without saving it. | |
| languageCode | No | Language code, with keyword only. Defaults to the priority market. | |
| locationCode | No | DataForSEO location, with keyword only. Defaults to the priority market. | |
| savedKeywordId | No | Saved keyword id. Pass this or keyword, not both. |
Output Schema
| Name | Required | Description |
|---|---|---|
| summary | Yes | |
| checkedAt | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, openWorld. The description adds value beyond them: 'Each call is 1 search' discloses a per-call cost, and 'that saves and tracks nothing' explicitly disambiguates the side-effect-free plain-keyword path.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with the core purpose front-loaded, followed by a compressed related-tools line. Efficient overall, though the bare 'Related:' prefix lists tool names without explaining the relationship, which slightly weakens the closing line.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need no explanation, and annotations carry the safety profile. The description covers both input paths, market defaults, and side effects, leaving only the explicit this-vs-siblings routing gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds real meaning: savedKeywordId should come from list_saved_keywords, and a plain keyword uses the priority market unless both locationCode and languageCode are supplied. That interaction is not fully spelled out in the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: it fetches who currently ranks for a keyword and judges whether those searchers match the audience. The scope ('current Google top 10') is concrete, and it names related tools (save_keywords, research_keywords) so the agent can place it among siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit behavioral routing between the two input modes: pass a savedKeywordId from list_saved_keywords, or a plain keyword to look it up without saving/tracking. However, 'Related: save_keywords, research_keywords' does not state the condition under which the agent should prefer this tool over those alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_site_readinessCheck Site ReadinessBRead-onlyIdempotentInspect
Re-scans a site for AI-agent readiness (robots, llms.txt, structured data, speed). Related: list_sites, get_ai_visibility.
| Name | Required | Description | Default |
|---|---|---|---|
| siteId | Yes | Site id from list_sites. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| reason | No | |
| report | Yes | |
| outcome | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true and destructiveHint=false, so safety and repeatability are covered. The description usefully adds which signals are evaluated, but says nothing about whether the rescan is synchronous, slow, or rate-limited — a real concern for a scan-triggering tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose and the scan scope in a single tight sentence; the 'Related:' sentence is short and adds some navigational value. Minimal waste, though the related-tools line is the least load-bearing part.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the scope of the scan is stated. What is missing is differentiation from run_site_audit/get_site_audit, which an agent selecting among readiness tools genuinely needs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter with 100% schema description coverage ('Site id from list_sites'), so the schema fully carries parameter meaning. The description contributes nothing beyond it, which is the baseline case.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (re-scans), resource (site), and enumerates the readiness dimensions checked (robots, llms.txt, structured data, speed). That is enough to distinguish it in kind from siblings, though it never contrasts itself with the similarly-named run_site_audit or get_site_audit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'Related: list_sites, get_ai_visibility' line implies the siteId source and a neighboring visibility tool, and 're-scans' implies use after changes. But there is no explicit when-to-use/when-not, and no routing guidance against run_site_audit, the closest alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
comment_on_postComment on PostAInspect
Adds a review comment to a post's current revision, visible to your team in Mark. Does not change the post's status. Related: get_post, review_post.
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | The comment, under 5000 characters. | |
| postId | Yes | Post id. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| postId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly=false, destructive=false, idempotent=false. The description usefully adds that the post's status is unaffected and that the comment is visible to the team, but it omits whether repeated calls stack duplicate comments or what permissions are needed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the action and its scope, then the key constraint and related tools. No filler or restated title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and full annotation coverage, the description only needs to carry purpose, scope, and routing, which it does. Minor gaps remain around non-idempotent duplicate behavior, but nothing essential for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both parameters (postId, body) are fully described in the schema, including the length bound. The description adds no syntax, format, or targeting detail beyond what the schema already provides, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Adds a review comment to a post's current revision') and even scopes it to the current revision and team visibility. It names related siblings (get_post, review_post), so an agent can distinguish it without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a clear negative condition ('Does not change the post's status') and points to related tools, which steers the agent away from misusing it as a status-change tool. It stops short of an explicit 'use this when...' rule or a named alternative for status changes.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
compare_buyer_question_answersCompare Buyer Question AnswersARead-onlyIdempotentInspect
Two stored check runs of one buyer question in one market, side by side per engine: each side's answer text, whether it cited or named you (youNamed: your current business name in the text), which tracked competitors it named or cited, and its cited pages with their stored titles; plus the pages cited in After and not Before (added), the reverse (dropped), and a count cited in both. Pages match ignoring www., case of the host and a trailing slash. By default After is the newest run and Before is the last run before the question's live answer page was last published or pushed to the CMS (else the previous run); defaultReason says which. Lists every completed or partial run you can pass, same-week reruns included. Reads stored checks only. Related: get_buyer_question_answers, get_ai_visibility.
| Name | Required | Description | Default |
|---|---|---|---|
| market | No | Active market id or exact name. Defaults to the market Performance > AI answers shows. | |
| question | Yes | Active buyer question id, or its exact text (case and outer spaces ignored). | |
| afterRunId | No | A run id from runs. Defaults to the newest. Before newer than After swaps them. | |
| beforeRunId | No | A run id from runs. Unknown or failed ids fall back to the default. |
Output Schema
| Name | Required | Description |
|---|---|---|
| found | Yes | |
| appUrl | Yes | |
| reason | Yes | |
| comparison | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safe read-only, idempotent profile, yet the description adds substantial behavior: the default After/Before selection logic and defaultReason, the page-matching normalization (ignoring www., host case, trailing slash), and the fact that completed or partial runs including same-week reruns are all listed. This is well beyond what the annotations convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in the first clause and the dense paragraph carries real content (default logic, matching rules, output fields). It is somewhat run-on and long, but nearly every clause earns its place rather than padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be fully spelled out, yet the description still characterizes the compared fields (answer text, youNamed, competitors, cited pages, added/dropped/both). Combined with the default-resolution rules, an agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema by explaining the default Before run (last run before the live answer page was last published/pushed to the CMS, else the previous run) and the swap behavior. It reinforces rather than merely repeats the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (compare) and resource (two stored check runs of one buyer question in one market) and scopes it per engine. It is clearly distinguishable from the singular sibling get_buyer_question_answers and from get_ai_visibility, which it explicitly names as related.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The clause 'Reads stored checks only' implicitly routes the agent away from run_answer_engine_check and other run-triggering tools, and the default Before/After selection rules give concrete context. However it never states explicitly when to prefer this over get_buyer_question_answers or get_ai_visibility, listing them only as 'Related'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_assetsDelete AssetsADestructiveInspect
Permanently deletes assets. With removeFromDrafts: true, it also removes them from editable posts; published posts keep their copy. This cannot be undone. Related: get_asset, search_assets.
| Name | Required | Description | Default |
|---|---|---|---|
| assetIds | Yes | Asset ids to delete. | |
| removeFromDrafts | No | If true, also detach from drafts and changes-requested posts. |
Output Schema
| Name | Required | Description |
|---|---|---|
| results | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=false, and readOnlyHint=false, so safety is covered structurally. The description adds genuine value beyond them: 'cannot be undone' plus the precise blast radius of removeFromDrafts ('published posts keep their copy'), which is behavior the annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, no filler, with the destructive/permanent nature and the key flag behavior front-loaded ahead of the related-tool pointers. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described. For a two-parameter destructive mutation, the description covers permanence, the conditional side effect, and related tools, leaving nothing an agent needs in order to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3 for the two documented parameters. The description goes slightly beyond the schema by spelling out the consequence of removeFromDrafts on drafts versus published content, adding semantic meaning the schema text does not fully convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Permanently deletes') and resource ('assets'), with the permanence qualifier front-loaded. The 'assets' resource is clearly distinguishable from sibling delete tools (delete_post, delete_site, delete_strategy_item), so an agent can route without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description names related tools ('Related: get_asset, search_assets') and explains what removeFromDrafts does, which implies when the flag matters. However, it never states when to use this tool versus the sibling deletes, nor any preconditions or exclusions, leaving usage context implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_postDelete PostADestructiveInspect
Permanently deletes a post: a draft, one in review, one approved or scheduled, or a published one. An unpublished post's Zernio post is canceled and deleted first (for a website post, its pending CMS publish is withdrawn); if that fails, nothing changes. Its review history, comments and performance logs are deleted with it; tracking links stay and keep their clicks. External posts cannot be deleted. A website post's preview draft in its CMS is deleted first when Mark may; otherwise cmsPreview says it is still in the CMS, where, and why, so you can delete it there. Published posts are admins only; anyone else is refused. By default a published post is removed from Mark only and stays live (takenDown left_live with its liveUrl). With takeDown: true, Mark first deletes it from LinkedIn, X, Facebook, YouTube or Pinterest, or unpublishes a website page in its CMS and then deletes the page when Mark's key may (otherwise takenDown left_in_cms says where the draft stays). Instagram and TikTok posts can't be taken down by apps: takeDown is refused for them, so remove them in the app and delete with takeDown false. A failed take-down changes nothing: the post stays in Mark, still published, and the error names the platform and the fix. This cannot be undone. Related: archive_post, search_posts, save_post.
| Name | Required | Description | Default |
|---|---|---|---|
| postId | Yes | The post to delete. Published posts need a workspace admin. | |
| takeDown | No | Published posts only: also take it down from the platform or CMS first. Default false (remove from Mark only; it stays live). Refused for Instagram and TikTok. |
Output Schema
| Name | Required | Description |
|---|---|---|
| postId | Yes | |
| status | Yes | |
| outcome | Yes | |
| takenDown | No | A published post only: taken_down (deleted from the platform, or its CMS page deleted), left_in_cms (unpublished, but the page stays in the CMS as a draft at previewUrl, for the same reasons as cmsPreview), or left_live (removed from Mark only; still live at liveUrl). |
| cmsPreview | No | The post's preview draft in the website CMS: removed (Mark deleted it), or left_in_cms with its previewUrl and why (cannot_delete: Mark's API key may not delete it; edited: changed in the CMS; linked: a page that was in the CMS before Mark used it; live: a live page; unreachable: the CMS did not answer). Absent when the post had no preview. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Far exceeds the annotations, which only mark it destructive/non-idempotent. It discloses what gets destroyed (review history, comments, performance logs; tracking links survive), the Zernio/CMS cancellation sequence, per-platform takeDown behavior, the Instagram/TikTok refusal, and the all-or-nothing failure semantics. This is exactly the irreversible-mutation context an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core action and the irreversible warning, and every paragraph maps to a distinct behavior (default delete, CMS preview, takeDown, failures). It is long and dense, but the length is justified by the tool's cross-platform complexity, with little filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, cross-platform tool with an output schema, the description covers the remaining burden: permissions, the takeDown matrix, failure modes and their error reporting, and the preview-draft edge case. Nothing an agent needs to invoke it safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents both parameters (baseline 3). The description adds real meaning beyond the schema: the default false behavior with the liveUrl outcome, the per-platform unpublish/delete sequence, and which platforms are refused.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Permanently deletes a post') and immediately enumerates the valid post states, so an agent knows exactly what it operates on. It also explicitly contrasts with archive_post, so it is distinguishable from its closest sibling without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use conditions (admin-only for published posts), when-not (external posts cannot be deleted; Instagram and TikTok cannot be taken down), and names alternatives (archive_post). The Related list routes the agent to the right siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_siteDelete SiteADestructiveInspect
Permanently removes a website and its audits and readiness history. This cannot be undone. Related: list_sites, save_site.
| Name | Required | Description | Default |
|---|---|---|---|
| siteId | Yes | Site id from list_sites. |
Output Schema
| Name | Required | Description |
|---|---|---|
| siteId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false, so the safety profile is covered. The description adds genuinely new behavioral context: the deletion is permanent, cannot be undone, and cascades to audits and readiness history. It stops short of naming auth requirements or a confirmation step.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action and its permanence, with zero filler. Every sentence earns its place: what it does, that it is irreversible, and related tools.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be described, and the description covers the destructive cascade and irreversibility for a single-param tool. It leaves mild ambiguity about whether other workspace resources (posts, keywords) are also removed, which matters for a permanent delete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single parameter with 100% schema description coverage ('Site id from list_sites'), so the schema carries the semantics. The description adds nothing beyond it, making the baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Permanently removes a website') and scopes the blast radius to audits and readiness history, which distinguishes it from siblings like delete_post, delete_assets, and archive_post. An agent can identify the target of this tool without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the irreversible deletion semantics; there is no explicit when-to-use statement or comparison against alternatives such as archiving or removing only the site's assets. The 'Related: list_sites, save_site' tail is a weak pointer rather than guidance on when this tool is the right choice.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_sourceDelete SourceADestructiveInspect
Deletes a pasted note (a source with type note) from the Claims & sources page. It also leaves the source picker. Cannot be undone. Refused while any claim quotes the note, active or retired (list_claims shows claims per source), or while brand profile evidence cites it (update_brand_profile). Other source types cannot be deleted here. Related: list_claims, update_source.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The note's id from list_claims. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| deletedId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing irreversibility ('Cannot be undone'), a side effect the annotations do not capture ('leaves the source picker'), and two server-side refusal preconditions with the tools that verify them. This is exactly the extra context destructiveHint alone cannot supply.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the verb and object, followed by refusals and a Related line. Dense but every sentence carries information; the trailing 'Related:' list is the only mildly extraneous element.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be explained, and the description covers the preconditions, irreversibility, and side effects an agent needs before invoking a destructive single-parameter tool. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the sole parameter's description already says 'The note's id from list_claims', which the tool description merely echoes. No new syntax, format, or sourcing detail is added, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (deletes) and a narrowly-scoped resource (a pasted note, i.e. a source with type note), and explicitly excludes other source types. This distinguishes it from siblings like delete_post, delete_assets, and delete_site without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete when-not conditions: refusal while any claim quotes the note or brand profile evidence cites it, and states other source types cannot be deleted here. It points to list_claims and update_brand_profile as the places to check those conditions, but does not name where non-note sources are deleted.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_strategy_itemDelete Strategy ItemADestructiveInspect
Permanently deletes a persona, pillar, angle, market or KPI target. Buyer questions can only be retired (save_strategy_item with active: false). This cannot be undone. An item still in use is refused: a persona or pillar that angles use (the error names them, so delete or move those angles first), anything posts use, or a market that answer-engine checks or monthly AI-visibility results use. To retire an item that is in use, call save_strategy_item with its id and active: false. Related: save_strategy_item, get_brand_context.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The item id from get_brand_context. | |
| kind | Yes | Kind to delete. Buyer questions cannot be deleted. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| kind | Yes | |
| appUrl | Yes | |
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and non-idempotent, but the description goes well beyond them: irreversibility ('This cannot be undone'), the referential-integrity refusal conditions (angles using a persona/pillar, posts, answer-engine checks, AI-visibility results), and the fact that the error message names the blockers. This is exactly the extra context annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the irreversible delete, then the refusal conditions, then the alternative — a sensible priority order with no filler. It is on the longer side and the refusal sentence is densely nested, but each clause carries distinct operational information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive tool with full schema coverage and an output schema (so return values need not be described), this covers everything an agent needs: irreversibility, the failure modes it will hit, the workaround, and the related tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters (id, kind with enum) are already documented, including the id source (get_brand_context) and the buyer-question exclusion on kind. The description adds no format or value semantics beyond that, so it sits at the baseline rewarded by a complete schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb ('Permanently deletes') and enumerates exactly which strategy item kinds are affected (persona, pillar, angle, market, KPI target), immediately carving out buyer questions as non-deletable. An agent can distinguish this from save_strategy_item and the other delete_* siblings without inspecting the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use and when-not: buyer questions can only be retired via save_strategy_item with active: false, and in-use items must be retired rather than deleted. It even names the remediation path (delete or move the dependent angles) when the refusal fires, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
disconnect_connectionDisconnect AccountADestructiveInspect
Disconnects an integration. With zernio (Social publishing) this disconnects every social account at once, not one channel, and no scheduled social post will publish until each account is reconnected in the Mark app. To see which social accounts would go, call list_channels first. For a website CMS, the reply names the provider and warns when channels are still mapped to it; leftover queued publishes then fail until those channels are mapped again. Connecting accounts cannot be done from the agent. Related: list_connections, list_channels, get_website_cms.
| Name | Required | Description | Default |
|---|---|---|---|
| connectionId | Yes | Provider from list_connections, e.g. zernio. |
Output Schema
| Name | Required | Description |
|---|---|---|
| connectionId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, but the description adds consequences they cannot express: zernio disconnection is all-or-nothing across every social account, scheduled posts stop publishing until each account is reconnected in the Mark app, and CMS disconnection leaves mapped channels with failing queued publishes. This is exactly the blast-radius detail an agent needs before invoking a destructive tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then the two provider-specific consequences, then related tools. Dense and mostly waste-free, though the provider-specific warnings are split awkwardly across paragraphs and could be tightened.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation. The description covers the destructive scope, the downstream effects on publishing, and the related tools to consult — everything needed to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is one parameter at 100% schema coverage, so the schema already documents connectionId as 'Provider from list_connections, e.g. zernio.' The description adds no new syntax, format, or constraint beyond that, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Disconnects an integration') and immediately scopes it against siblings by naming the affected provider (zernio) and the alternative tools (list_connections, list_channels, update_connection_settings). An agent can distinguish this from sync_connections or update_connection_settings without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent to call list_channels first to preview which social accounts would be removed, and states a hard boundary: 'Connecting accounts cannot be done from the agent.' That is a clear when-to-use, a pre-check alternative, and a when-not, all named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dismiss_ai_crawler_404Dismiss AI Crawler 404AIdempotentInspect
Hides one path from get_site_audit's aiCrawler404s and the Site health list for 90 days. Dismissing it again restarts the 90 days. If the path still answers 404 when the dismissal ends, it shows again. Changes only Mark, never the site. Related: get_site_audit.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | The path exactly as aiCrawler404s returns it. | |
| siteId | Yes | Site id from list_sites. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| expiresAt | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations present, the description still adds substantial lifecycle detail beyond them: a 90-day suppression window, restart-on-repeat semantics, the auto-resurface condition, and 'Changes only Mark, never the site' (which corroborates destructiveHint=false). Minor tension: repeat calls reset the clock, which nuances idempotentHint=true, but the disclosure is complete enough that an agent is not misled.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, zero filler, with the primary action and scope front-loaded before the edge-case behaviors. Every sentence carries information an agent needs to call it correctly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter mutation with an output schema and full annotation coverage, the description supplies what remains: mutation semantics, duration, reversibility, and the source of the path value. Only error handling (e.g., path not present in the list) is unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both schema descriptions are already strong ('exactly as aiCrawler404s returns it', 'Site id from list_sites'). The description's 'one path' clarifies per-call cardinality but adds little beyond the schema; baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (hides/dismisses) and a precisely scoped resource: one path in get_site_audit's aiCrawler404s and the Site health list, bounded to 90 days. The tool is unique among its siblings, and it explicitly names the related tool (get_site_audit) so an agent can place it in the audit workflow without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Establishes clear operating context: the path comes from aiCrawler404s output, re-dismissing restarts the window, and the entry resurfaces if it still 404s. 'Related: get_site_audit' points the agent back to the source workflow, though there is no explicit when-not-to-use or named alternative to skip.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
draft_competitor_pageDraft Competitor PageAIdempotentInspect
Drafts a comparison page for one tracked competitor as a competitor_page draft post: kind vs (" vs "), alternative (" alternative") or pricing (" pricing", what they charge and how you compare). One AI model call writes it from Mark's facts about them (price claims sourced on their own site, this week's AI answers that named them and not you, their ranked keywords). Each fact gets a numbered marker, and Mark adds a Sources section with each source and its checked date. A fact Mark has no source for is a [confirm: …] placeholder; every price is one when no price claim is sourced on their site (add one with add_source and save_claim). No tables. When that competitor already has a live (not archived) post of that kind, returns it and writes nothing; markAppUrl opens the editor, or the review page once it is past draft. Refuses an unknown or untracked competitor, and one whose name or domain matches a content exclusion. A blocked phrase in the generated text saves nothing. Never submits: open placeholders, tables and numbers no active claim states fail the content checks, so fix them, then call submit_post. Takes up to a minute. Related: list_competitors, get_competitor_scorecard, check_draft, save_post, submit_post.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | Yes | vs, alternative or pricing. | |
| competitorId | Yes | Competitor id from list_competitors. |
Output Schema
| Name | Required | Description |
|---|---|---|
| postId | Yes | |
| status | Yes | |
| created | Yes | |
| markAppUrl | Yes | |
| openPlaceholders | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare mutation and idempotency; the description adds substantial behavior beyond them: marker/placeholder conventions, the '[confirm: …]' and unsourced-price rules, blocked-phrase failure saving nothing, no tables, content-check failure modes, refusal conditions, and an expected latency ('up to a minute'). The 'returns it and writes nothing' clause concretely explains the idempotentHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The behavior is front-loaded and almost every clause carries information, but the middle section is a dense run of semicolon-linked rules with nested parentheticals that take effort to parse. Given the tool's complexity the length is defensible, but it is not maximally scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need no explanation, and the description covers everything else an agent needs: side effects, idempotent behavior, refusal cases, failure modes, follow-up tools, and timing. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline would be 3, but the description goes further by explaining what each enum value means (vs = '<you> vs <them>', alternative, pricing = what they charge and how you compare) and confirms competitorId comes from list_competitors. This adds real semantics beyond the bare enum list.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence gives a specific verb, resource, and output artifact: 'Drafts a comparison page for one tracked competitor as a competitor_page draft post,' then enumerates the three kinds with their meaning. An agent can distinguish this from list_competitors or check_draft without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states preconditions (competitor must be tracked/existing; refusal for unknown, untracked, or content-excluded competitors), a when-not path (if a live post of that kind exists, it returns it and writes nothing), and the next step (never submits – fix checks, then call submit_post). It also names related tools, including list_competitors as the source of competitorId.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
estimate_ai_volumeEstimate AI Search VolumeRead-onlyIdempotentInspect
Estimates how often each of 1 to 50 phrases is asked in AI assistants each month, in the priority market, without saving anything. Use it to vet a question before adding it as a buyer question. Results come back in input order; aiSearchVolume is null when the provider has no estimate. This is AI search volume, not the Google search volume research_keywords returns. If this refuses because the workspace is not set up, call get_setup_status and check its rows, including skipped ones. Add a phrase with save_strategy_item (kind buyer_question). Related: refresh_ai_volume, get_ai_visibility, set_up_market.
| Name | Required | Description | Default |
|---|---|---|---|
| phrases | Yes | One to 50 phrases, each up to 250 characters. |
Output Schema
| Name | Required | Description |
|---|---|---|
| scope | Yes | What the run checks. |
| market | Yes | |
| results | Yes |
export_context_packExport Context PackARead-onlyIdempotentInspect
Exports this workspace's context pack: four markdown files (company, customer, offer, voice) built from what is saved in Mark. company has positioning, differentiators, doctrine, company facts and entities; customer has the active personas with pains, jobs, objections and their words; offer has what is sold today, what is planned, pricing, promises and claims to avoid; voice has tone, do and don't lines and active content exclusions. Each file opens with the workspace name and export date, and marks a Brand section that is not confirmed. The files use the layout brand-interview reads, so they can seed another folder or workspace. Edits belong in Mark, not in the files. Does not change anything. Related: get_brand_context, update_brand_profile, save_strategy_item.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| files | Yes | |
| appUrl | Yes | |
| exportedAt | Yes | |
| workspaceName | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so 'Does not change anything' is largely redundant. The description earns credit beyond the annotations by disclosing the exact file layout, that each file carries the workspace name and export date, that the Brand section is marked unconfirmed, and that the layout is the one brand-interview reads.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The key fact (what is exported and in what shape) is front-loaded, and the closer 'Does not change anything' plus the Related line route the agent efficiently. It is a dense single paragraph and the per-file inventory is long, but nearly every clause carries information an agent needs; only the read-only restatement is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description does not need to describe return shape, yet it still pre-summarizes the file contents. Between the description, the empty-but-required schema, and the annotations, an agent has everything needed to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline of 4 applies. The description correctly spends no effort on argument semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (exports) and resource (this workspace's context pack) and enumerates exactly what the output contains: four markdown files (company, customer, offer, voice) with the subject matter of each. An agent can distinguish this from get_brand_context or get_workspace without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear usage context: the files 'can seed another folder or workspace' and 'Edits belong in Mark, not in the files,' which tells the agent this is a one-way export, not an editing surface. It lists related tools (get_brand_context, update_brand_profile, save_strategy_item) but never states the conditions under which one should be chosen over this export, so explicit alternatives are missing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_ai_visibilityGet AI VisibilityRead-onlyIdempotentInspect
Shows how AI assistants see you: buyer questions (each with answerPages: the website posts linked to it with save_post buyerQuestionIds, label, status, live URL; empty means no page answers it yet), suggestions from People Also Ask, Search Console question searches and Reddit threads Google showed for audience-checked saved keywords (redditSuggestions: question, url, subreddit, keywords, total), AI search volume, traffic: pages AI assistants' bots fetched (not referrals or citations), where each bot row's hits split into verified (IP on the vendor's published list), checkable minus verified (failed the check) and hits minus checkable (no list, list not loaded, or no IP), and paths are the top 10 pages without fonts, images, styles or scripts, each with lastStatus: the HTTP status of Mark's latest daily check of that path on the primary site (404 means AI assistants can't find it; see get_site_audit aiCrawler404s), or null when unchecked or unknown; traffic.state is ready, no-posthog, no-signal (PostHog has received no events yet) or failed, and a failed read has reason: busy means PostHog didn't answer in time (it runs 3 queries at once per project and queues the rest), so try again in a minute; the PostHog connection is fine. error is any other failure, such as lost access, so check the PostHog connection. verificationSetup: the last result of Mark installing its IP check in your PostHog project (status ok or failed, reason limit, access or error, checkedAt; null before the first run or with no project), readiness, and AI answers: for the priority market's latest weekly check, how often ChatGPT, Gemini, AI Overview, AI Mode, Claude and Perplexity named or cited you (Claude and Perplexity are asked through their APIs with web search on, not the consumer apps, so their answers can differ from what people see in the apps), the top domains they cited, and up to 5 suggested competitors from the third-party sites they cite most (null with a reason when there is nothing yet), plus shareOfVoice: your share of mentions among you and your tracked competitors per engine in that run, and your share over the last 12 weekly runs, and nextAnswerCheck: how many checks the next weekly AI answer check sends (active questions × markets with a location and language × engines), the line Settings > Workspace shows. Does not change anything. Add any suggestion with save_strategy_item (kind buyer_question, fields.question). Related: refresh_ai_volume, save_strategy_item, check_site_readiness.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| traffic | Yes | |
| readiness | Yes | |
| suggestions | Yes | |
| answerEngine | Yes | |
| buyerQuestions | Yes | |
| nextAnswerCheck | Yes | What a new weekly AI answer check sends now. Counts what it would ask even while AI answer checks are off. |
| redditSuggestions | Yes | |
| verificationSetup | Yes | |
| answerEngineReason | Yes | |
| searchConsoleSuggestions | Yes |
get_assetGet AssetARead-onlyIdempotentInspect
Opens one asset: preview URL, details, and which posts use it. Related: search_assets, update_asset, delete_assets.
| Name | Required | Description | Default |
|---|---|---|---|
| assetId | Yes | Asset id from search_assets. |
Output Schema
| Name | Required | Description |
|---|---|---|
| asset | Yes | |
| usage | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive behavior, so the safety profile is covered. The description still adds something the annotations do not: the shape of what comes back, including the cross-reference to posts that use the asset, which helps an agent judge whether this call answers its question.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, zero filler, with the payload description front-loaded and the routing hint second. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter getter with full annotations and an output schema, the description covers identity, scope, and payload without needing to restate return values. Only the absence of explicit when-to-use guidance keeps it short of complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single parameter with 100% schema description coverage ('Asset id from search_assets'), so the schema already carries the semantics. The description adds no format, sourcing, or error guidance beyond what is there, making 3 the correct baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Opens') and resource ('one asset'), and enumerates the payload (preview URL, details, which posts use it). The singular 'one asset' contrasts cleanly with the sibling search_assets, so an agent can route without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'Related:' line lists search_assets, update_asset, and delete_assets, which implies the read-one-by-id use case, but it never states when to choose this over search_assets or what the prerequisites are. Usage is inferred rather than instructed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_asset_thumbnailsAsset ThumbnailsRead-onlyIdempotentInspect
Signed URLs, valid one hour, for image assets in this workspace. Only Mark's calendar widget calls this to draw thumbnails. Agents never call it. Related: get_calendar.
| Name | Required | Description | Default |
|---|---|---|---|
| assetIds | Yes | Image asset ids. |
Output Schema
| Name | Required | Description |
|---|---|---|
| urls | Yes | Asset id to signed URL. Ids not found or not images are left out. |
get_brand_contextGet Brand ContextARead-onlyIdempotentInspect
Returns everything that shapes content: the Brand page's four sections (profile.voice, profile.visual, profile.overlay for entities and evidence, profile.offer for what is sold today, what is planned, pricing, promises and claims to avoid; profile.voiceError, visualError, overlayError or offerError explains a stored section that needs repair), personas (with wants, convincedBy, objections, pains, jobs and language: the customer's own words), pillars, angles, markets, buyer questions, KPI targets (for their actuals and progress, call get_content_performance), and active content exclusions. Call it before drafting or reviewing. brandReview says, per Brand section, whether a person has confirmed it (confirmed, confirmedAt) or it needs repair; tell the person which sections still need their review. claims lists the active claims (id, text, category, sourceQuote, sourceId, sourceTitle): the only facts drafts may state as certifications, prices, lead times or specs. Retired claims are left out; for them and for search, call list_claims. sources lists the Claims & sources entries (id, title, url) that overlay evidence and claims cite by sourceId. profile.visual.logoAssetId is an asset id; call get_asset for the image. organizationJsonLd is the ready-to-paste Organization JSON-LD script built from the saved primary entity, company site, sameAs and Wikidata ids (null when there are no sameAs URLs or Wikidata ids), plus logo when the Brand logo was imported from a public URL (uploaded and Drive logos have no public URL, so logo is left out); it goes in the head of the person's home page. Personas, pillars, angles and markets include inactive rows (active: false). Each angle is one persona × pillar pair: it carries personaId and pillarId plus personaName and pillarName, so group angles by those to see which pairs have one. People edit personas, pillars and angles at /settings/messaging, and markets at /settings/markets. A market with null locationCode or languageCode has no search location, so AI search volume and answer-engine checks skip it. Does not change anything. Related: update_brand_profile, save_strategy_item, save_content_exclusion, list_claims, save_claim, get_channel_rules.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| angles | Yes | |
| appUrl | Yes | |
| claims | Yes | |
| markets | Yes | |
| pillars | Yes | |
| profile | Yes | |
| sources | Yes | |
| personas | Yes | |
| exclusions | Yes | |
| kpiTargets | Yes | |
| brandReview | Yes | |
| buyerQuestions | Yes | |
| organizationJsonLd | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so 'Does not change anything' adds little. However, the description discloses non-obvious behavior: inactive rows are included, null locationCode/languageCode markets are skipped by search checks, organizationJsonLd is null under specific conditions, and claims are the only facts drafts may assert. That is meaningful context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The first sentence is well front-loaded, but the body is very long and dense with parenthetical field enumerations that largely restate what an existing output schema would carry. 'Does not change anything' is also redundant against readOnlyHint, so not every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter read tool with full annotations and an output schema, the description is more than sufficient — it covers section semantics, error fields, active/inactive handling and inter-tool handoffs. Some of that overlap with the output schema is the only surplus.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so per the rubric the baseline is 4. There is no input surface for the description to clarify, and it correctly adds none.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence names a specific verb (Returns) and resource (everything that shapes content), then enumerates the concrete sections (profile.voice, visual, overlay, offer) and related entities. It is clearly distinguishable from siblings like list_claims and get_content_performance, which it names explicitly as adjacent tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States the trigger plainly ('Call it before drafting or reviewing') and routes the agent to alternatives for specific needs: get_content_performance for KPI actuals, list_claims for retired claims and search, get_asset for the logo image. When-to-use and where-to-go-instead are both covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_buyer_question_answersGet Buyer Question AnswersARead-onlyIdempotentInspect
One buyer question's stored AI answers for one market and week: its answer pages (website posts linked to the question, whether each is live, and which engines cited it that week), per engine (ChatGPT, Gemini, AI Overview, AI Mode, Claude, Perplexity; Claude and Perplexity are asked through their APIs with web search on, not the consumer apps, so answers can differ from the apps) the answer text, whether it cited or named you (youNamed: your current business name in the text), which tracked competitors it named or cited (the names the app highlights in the answer), and the cited pages marked yours or a competitor's with their stored titles, plus each engine's baseline (its first answered check in this market). Also lists the weeks you can pick. Reads stored weekly checks only. Related: compare_buyer_question_answers, get_ai_visibility, get_competitor_ai_detail, save_wrong_answer.
| Name | Required | Description | Default |
|---|---|---|---|
| market | No | Active market id or exact name. Defaults to the market Performance > AI answers shows. | |
| weekKey | No | ISO week from weeks, like 2026-W40. Defaults to the newest. | |
| question | Yes | Active buyer question id, or its exact text (case and outer spaces ignored). |
Output Schema
| Name | Required | Description |
|---|---|---|
| found | Yes | |
| appUrl | Yes | |
| reason | Yes | |
| answers | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the bar is lower, and the description adds real behavioral context beyond them: results reflect stored weekly checks only, and Claude/Perplexity answers come from APIs with web search rather than the consumer apps and may differ. It does not mention pagination or result limits, keeping it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose is delivered as one enormous run-on sentence with deeply nested parentheticals enumerating every return field (answer pages, youNamed, cited pages, baselines), which duplicates the existing output schema. Only the closing 'Also lists the weeks you can pick. Reads stored weekly checks only.' and Related line carry non-redundant value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations covering the safety profile, a 100%-covered schema, and a present output schema, the description is more than complete for correct invocation, and it adds the stored-only constraint. It is slightly over-complete on return values, which the output schema already handles.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all three parameters are already documented in the schema. The description reinforces that 'weekKey' comes from the listed weeks and that market defaults to the AI answers view, but adds little syntax or format detail beyond what the schema states, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('one buyer question's stored AI answers for one market and week') and enumerates the exact contents returned, so an agent knows precisely what this retrieves. The 'Related:' line names four siblings, letting the agent distinguish it from compare_buyer_question_answers and get_ai_visibility without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear usage boundary with 'Reads stored weekly checks only,' implying live checks come from run_answer_engine_check, and the Related line points at alternatives. However, it never explicitly states when to choose this over compare_buyer_question_answers or get_ai_visibility, so the routing is implied rather than spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_calendarGet CalendarARead-onlyIdempotentInspect
Shows the publishing calendar for one week: each day's scheduled and published posts in time order, the open posting slots to fill (each with its slot id and local date, which reschedule_post takes to fill it), and how many of each channel's slots are filled. An approved social post's card carries handoff, as in get_post: handing_off before it reads scheduled, or stuck with the reason and fix; an approved LinkedIn Article's reads publish_by_hand, or publish_now once its time has passed. Pass week as any date in it (YYYY-MM-DD). Times render in the workspace timezone, or in timezone if you pass an IANA name (render only; stored data does not change). Related: save_post, reschedule_post, update_posting_slots.
| Name | Required | Description | Default |
|---|---|---|---|
| from | No | Same as week, for older callers. | |
| week | No | Any date in the week to show (YYYY-MM-DD). Defaults to today. | |
| timezone | No | IANA zone to render times in. Does not change stored data. Defaults to the workspace timezone. |
Output Schema
| Name | Required | Description |
|---|---|---|
| calendar | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive/closed-world, but the description adds substantial context they can't: timezone is render-only and does not mutate stored data, and it discloses the handoff states (handing_off, stuck with reason and fix, publish_by_hand, publish_now) that appear on cards. This is behavioral detail well beyond structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core payload description before the handoff-state details, and each sentence carries information. It is dense rather than padded, though the handoff discussion is lengthy enough to slightly dilute the primary purpose statement.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only listing tool with an output schema present, the description need not define return shape; it nonetheless covers scope, timezone behavior, slot semantics, and related tools. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all three parameters are already documented, including the 'from' legacy alias and the timezone non-mutation note. The description largely reinforces 'week can be any date in it' and repeats the render-only timezone semantics, adding only marginal meaning over the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Shows the publishing calendar') plus the exact scope ('for one week') and enumerates what it returns: scheduled/published posts, open slots with slot ids, and per-channel fill counts. An agent can distinguish this from list_* or get_post siblings without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete invocation guidance ('Pass week as any date in it'), explains the timezone rendering option, and names related tools (save_post, reschedule_post, update_posting_slots), notably that reschedule_post consumes the slot id this returns. It stops short of explicit when-not-use or alternative-selection rules.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_channel_rulesGet Channel RulesARead-onlyIdempotentInspect
Gives the format rules for a channel (length limits, accepted media ratios, meta field names and types), from the same source Mark's in-app writer uses. For X it says that each link counts as 23. For email it gives subject (required) and preheader (the preview text, optional); Mark doesn't send email yet. For linkedin_article (a long-form LinkedIn Article) it gives title (required) and cover (optional) over a Markdown body; Mark doesn't publish Articles, a person does. For writing craft and this workspace's rules, call get_drafting_guide. For blog, faq, competitor_page and landing_page it also reports the website CMS mapping in force (collection, required fields, body format, cover rule, URL pattern), whether a CMS is connected, and whether approval saves a CMS draft or publishes live. Omit channel to list the supported channels. Related: list_channels, save_post, get_brand_context, get_website_cms.
| Name | Required | Description | Default |
|---|---|---|---|
| channel | No | Channel id such as linkedin or instagram. Omit to list supported channels. |
Output Schema
| Name | Required | Description |
|---|---|---|
| rules | No | |
| channels | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotent/non-destructive, so safety is covered. Beyond that the description discloses concrete per-channel behavior the schema cannot express: X counts each link as 23, email returns subject (required) and preheader (optional) while Mark doesn't send email yet, linkedin_article returns title/cover over a Markdown body and Mark doesn't publish Articles, and the CMS mapping fields reported for website channels. Only minor gap is it doesn't note caching/freshness, but the behavioral disclosure is rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose and the routing to get_drafting_guide are front-loaded, and the trailing Related list is compact. It is dense with channel-specific return detail (X/email/linkedin_article) that arguably duplicates the output schema, but each sentence carries usable signal and nothing is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-required-param read tool with an output schema and full annotations, the description supplies everything an agent needs: what varies per channel, how to list channels, and which sibling to use for craft rules. Return values are further detailed, if somewhat redundantly with the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single channel enum is fully documented with the omit-to-list behavior. The description reinforces the omit semantics but adds no syntax or format detail beyond the schema's own note, so the baseline 3 for a fully-covered single param is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('gives the format rules for a channel') and immediately scopes what those rules include (length limits, media ratios, meta field names/types). It explicitly distinguishes itself from get_drafting_guide on the craft-rules axis and from list_channels when no channel is given, so an agent can route without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the alternative explicitly ('For writing craft and this workspace's rules, call get_drafting_guide') and states the omit-channel branch that turns this into a listing tool. The condition selecting each behavior is spelled out rather than inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_competitor_ai_detailGet Competitor AI DetailARead-onlyIdempotentInspect
One tracked competitor against you in this week's AI answers, by engine (ChatGPT, Gemini, AI Overview, AI Mode, Claude, Perplexity; Claude and Perplexity are asked through their APIs with web search on, not the consumer apps): how often each is named and cited, the buyer questions where an AI named them and no AI named you (with the stored answers), and the sites AI cited for them in answers that cite none of your sites. Related: get_competitor_scorecard.
| Name | Required | Description | Default |
|---|---|---|---|
| competitorId | Yes | Competitor id from list_competitors. | |
| languageCode | No | Language code. Defaults to the priority market. | |
| locationCode | No | DataForSEO location. Defaults to the priority market. |
Output Schema
| Name | Required | Description |
|---|---|---|
| detail | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive, closed-world behavior, so the safety profile is covered. The description adds genuinely non-obvious data-provenance context: it enumerates the six engines and clarifies that Claude and Perplexity are queried through their APIs with web search, not the consumer apps, which affects how results should be interpreted. That is real disclosure beyond the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core (one competitor, this week's AI answers, by engine) is front-loaded and every clause maps to actual returned content. The heavy parenthetical engine list and the Claude/Perplexity caveat make it a dense single sentence, marginally harder to parse than ideal, but there is little outright waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be spelled out, yet the description still characterizes them; combined with full 100% schema coverage and complete annotations, an agent has enough to invoke it correctly. The main omission is the lack of any guidance on choosing this versus get_competitor_scorecard.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all three parameters (competitorId, languageCode, locationCode) are already documented in the schema, including defaults and the DataForSEO location type. The description adds no parameter-level syntax or format detail beyond that, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific resource (one tracked competitor's AI-answer detail), scopes it ('this week's AI answers, by engine'), and enumerates the concrete data returned (named/cited frequency, buyer questions where only the rival was named, rival-cited sites). It is far more than a restatement of the title. However, it only nods at the sibling with 'Related: get_competitor_scorecard' and never says how the two differ, so it falls short of clean sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'One tracked competitor' implies the prerequisite that the competitor must be tracked (echoed by the schema's 'from list_competitors'), which is a usable hint. But there is no explicit when-to-use, when-not, or condition distinguishing it from get_competitor_scorecard; the 'Related:' pointer names an alternative without saying which to pick. Usage is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_competitor_scorecardGet Competitor ScorecardARead-onlyIdempotentInspect
Your sites and each tracked competitor side by side for one market: how often this week's AI answers to your buyer questions name and cite each brand (count of answers), organic traffic and keywords, and monthly share of ChatGPT and AI Overview mentions. These cover your own buyer questions, not the whole market. Null means no answers or no data yet. nextComparisonPage is the comparison page to draft next ({ competitorId, name, kind, namedNotYou }, the Competitors page's card), or null when nothing is left: for this market, the tracked competitor (not one a content exclusion names) AI answers name most often instead of you, then the one ranking for the most keywords, kinds in vs, alternative, pricing order, pricing only once a price claim is sourced on their site. Related: get_competitor_ai_detail, list_competitors, draft_competitor_page.
| Name | Required | Description | Default |
|---|---|---|---|
| languageCode | No | Language code. Defaults to the priority market. | |
| locationCode | No | DataForSEO location. Defaults to the priority market. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| scorecard | Yes | |
| nextComparisonPage | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish this as a safe, read-only, idempotent, non-destructive read, so the safety burden is lifted. The description adds real behavioral context on top: null means 'no answers or no data yet', the nextComparisonPage payload shape, its ordering logic (named-not-you first, then most keywords ranked, kind ordering within vs/alternative/pricing, pricing gated on a sourced price claim), and the content-exclusion caveat. It does not discuss caching or latency, but that is minor here.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose sentence is well front-loaded, but the nextComparisonPage sentence is a single dense clause stacking ordering rules, kinds, and a pricing caveat that is hard to parse in one pass. The content largely earns its place, but the structure could be broken into shorter, list-like statements.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not explain return formats, yet it still clarifies the null semantics and nextComparisonPage semantics that an agent must interpret. Annotations, schema, and description together leave no obvious gap for correctly invoking this filtered read.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Both parameters (languageCode, locationCode) are fully documented in the schema at 100% coverage, including their priority-market defaults, so the schema carries the load. The description mentions 'one market' but adds no syntax or format detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a concrete verb (get/compare) and resource (your sites vs each tracked competitor for one market) and enumerates exactly what the scorecard reports: AI answer naming/citation counts, organic traffic and keywords, and monthly ChatGPT/AI Overview mention share. It also draws the boundary against related tools (get_competitor_ai_detail, list_competitors), so an agent can distinguish this market-level scorecard from the per-competitor detail tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
A 'Related:' line names get_competitor_ai_detail, list_competitors, and draft_competitor_page, and the scope note ('these cover your own buyer questions, not the whole market') implies when this view is appropriate. However, no explicit condition selects this tool over the alternatives, so the routing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_connect_linkGet Connect LinkARead-onlyIdempotentInspect
Returns the in-app URL to connect a provider (the same ids list_connections uses, or a channel such as linkedin). The link is for this workspace only and never includes tokens or secrets. Connecting accounts and pasting API keys still happens in the Mark app. After the user clicks the link, call sync_connections. For a social channel, list_channels then shows whether the account is connected. Related: list_channels, list_connections, get_setup_status, sync_connections.
| Name | Required | Description | Default |
|---|---|---|---|
| provider | Yes | connectionId from list_connections, or a channel such as linkedin. |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | |
| appUrl | Yes | |
| uiOnly | Yes | |
| provider | Yes | |
| connectionId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds genuinely new behavioral context: the link is workspace-scoped, never carries tokens or secrets, and is only a handoff into the Mark app rather than an in-API connection. That out-of-band workflow detail is exactly what annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the return value and its security constraint; the workflow sentence earns its place. The trailing 'Related:' list of four siblings is mildly redundant given several are already named inline, but it aids routing rather than bloating.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the description covers the one parameter, the security constraint, and the follow-up workflow. An agent has everything needed to call this correctly and interpret what happens next.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the parameter description already covers 'connectionId from list_connections, or a channel such as linkedin.' The prose restates the same semantics without adding format, validation, or example detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Returns the in-app URL to connect a provider') and immediately scopes what the provider argument can be. It distinguishes itself from siblings by referencing list_connections' ids and channel names, so the agent can route correctly without opening another schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use and what-comes-next guidance: the connection itself happens in the Mark app, then sync_connections should be called, and for social channels list_channels reveals connection state. It also names related tools, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_content_performanceGet Content PerformanceARead-onlyIdempotentInspect
Reports how published content performed over a period (reach, engagement, clicks by channel, post, pillar and angle), with period-over-period change. kpis is the Targets page (/settings/targets): every KPI target with its month (YYYY-MM), target, actual and progressPercent, computed the same way the page does. The actual counts posts published in the target's month, their latest checkpoint, and leads created in it, in the workspace time zone; it ignores from, to, pillarId and marketId. period is past, current (actual so far) or not_started (actual null). When there is no number, actual is { note } with the reason, such as a metric Mark doesn't track yet. engagement_rate values are percents (4.5 means 4.5%). Does not change anything. Related: save_strategy_item (kind kpi_target), delete_strategy_item, get_search_performance, get_calendar, search_posts.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Range end YYYY-MM-DD. | |
| from | No | Range start YYYY-MM-DD. Defaults to the last 28 settled days. | |
| marketId | No | Filter to one market. | |
| pillarId | No | Filter to one pillar. |
Output Schema
| Name | Required | Description |
|---|---|---|
| kpis | Yes | |
| appUrl | Yes | |
| performance | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile, yet the description adds substantive behavior: the kpis block ignores four of the input filters, actual is null vs { note } with a reason, period takes past/current/not_started, and engagement_rate values are percents. These are non-obvious traits an agent could not derive from annotations or schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core purpose in the first sentence and keeps every subsequent sentence information-bearing. The middle paragraph is a dense wall of text covering kpis semantics, which is justified by complexity but harder to scan than the rest.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return-value detail is not required, and annotations already carry the safety profile. Given the tool's complexity, the description still covers filter behavior, null handling, and value scales, leaving nothing essential for correct invocation unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents the four parameters (baseline 3). The description goes beyond it by explaining that from/to/pillarId/marketId are ignored in the kpis computation and by defining the semantics of a 'period' concept and the percent scale, though it leaves the exact interaction between the two modes somewhat implicit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Reports') and resource ('published content performed over a period') and enumerates the metric families returned (reach, engagement, clicks by channel, post, pillar, angle). It also names a sibling it relates to (save_strategy_item, get_search_performance), so an agent can distinguish it from other getters without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'Related:' line and the explanation that the kpis block mirrors the Targets page give clear context for when this tool applies, and the 'ignores from, to, pillarId and marketId' note warns the agent about a surprising interaction. However, it never states explicit exclusions (e.g. when to prefer get_search_performance or get_calendar instead), so routing is contextual rather than prescriptive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_drafting_guideGet Drafting GuideARead-onlyIdempotentInspect
Returns the drafting guide for one channel: the honesty rules every draft follows, the channel's craft, general writing craft (plus AEO/GEO writing on blog, faq, competitor_page and landing_page), this workspace's brand voice and content exclusions, and the platform limits. Check a draft against it before saving, then pass its guideVersion to save_post. Claims and sources are not in the guide: call get_brand_context for those. Does not change anything. Related: save_post, get_brand_context, get_channel_rules.
| Name | Required | Description | Default |
|---|---|---|---|
| surface | Yes | Channel to draft for, such as linkedin, x or blog. email and ad channels have no guide. |
Output Schema
| Name | Required | Description |
|---|---|---|
| limits | Yes | |
| surface | Yes | |
| sections | Yes | |
| guideVersion | Yes | Pass to save_post as guideVersion. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotent/non-destructive, and the description reinforces that with 'Does not change anything.' It adds genuinely new behavioral context: the full inventory of what the guide contains and the guideVersion handoff contract to save_post. It does not cover failure modes beyond the schema's channel note, so it stops short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose, then the content inventory, then the routing rules and exclusions in short declarative sentences. Every sentence carries information an agent needs; nothing is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value documentation is unnecessary, and the description still covers content, usage workflow, the save_post handoff, and the sibling exclusions. Nothing material is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and there is a single 'surface' parameter, so the schema already carries the meaning, including which channels lack a guide. The description only restates 'one channel' and adds no format or syntax detail beyond that, making the baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Returns the drafting guide for one channel') and then enumerates exactly what the guide contains (honesty rules, channel craft, writing craft, brand voice, platform limits). It explicitly differentiates itself from get_brand_context, which holds claims and sources, so an agent can pick correctly without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete workflow: 'Check a draft against it before saving, then pass its guideVersion to save_post.' It also names the exclusion — claims and sources live in get_brand_context — and lists related tools, so both when-to-use and when-not-to-use are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_ga4_organic_overviewGet GA4 Organic OverviewARead-onlyIdempotentInspect
Reports Google Analytics organic search sessions, active users, and key events for a date range against the same number of days just before it, plus the top organic landing pages. Requires a connected Google Analytics property. Does not change anything. Related: get_search_performance, get_content_performance.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Range end YYYY-MM-DD. | |
| from | No | Range start YYYY-MM-DD. Defaults to the last 28 settled days. |
Output Schema
| Name | Required | Description |
|---|---|---|
| rows | Yes | |
| appUrl | Yes | |
| current | Yes | |
| previous | Yes | |
| topLandingPages | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive behavior, so the safety profile is covered. The description adds genuinely useful context beyond that: the comparison of the range 'against the same number of days just before it' and the connectivity prerequisite. It does not, however, address freshness, sampling, or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences: the core capability and comparison behavior lead, followed by prerequisites, safety note, and related tools. No redundancy, every clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be spelled out, and annotations carry the safety profile. The description covers the prerequisite, scope, and comparison behavior an agent needs to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both from/to parameters (including the default of the last 28 settled days) are already fully documented. The description's mention of a date range and comparison period is framing rather than added parameter semantics, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Reports) and resource (Google Analytics organic search sessions, active users, key events, top organic landing pages) with a comparison window. It names related siblings (get_search_performance, get_content_performance) but never explains how this tool differs from them, so it falls short of full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context: 'Requires a connected Google Analytics property' and 'Does not change anything,' plus points to related tools. However, it never states the condition under which an agent should pick this over get_search_performance or get_content_performance, so there is context but no explicit when/when-not.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_page_detailGet Page DetailARead-onlyIdempotentInspect
Reports everything Mark knows about one page URL for a date range: Search Console clicks, impressions, CTR, position and top queries for that page; tracked keywords whose latest rank is that page; its issues in the latest site audit; Mark posts published at it or linking to it; first-touch leads that landed on it, with conversion rate and the Top pages Leak or Write more signal; and buyer questions whose AI answers cited it. Each block says why when it has no data. Pass the page URL exactly as get_search_performance returns it, scheme included, or Search Console may find no rows for it. The URL must be on this workspace's Search Console property, or on one of its sites with none. Does not change anything. Related: get_search_performance, get_site_audit, get_rankings, get_ai_visibility.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Range end YYYY-MM-DD. | |
| url | Yes | The page URL, as get_search_performance returns it. | |
| from | No | Range start YYYY-MM-DD. Defaults to the last 28 settled days. | |
| marketId | No | Filter Search Console to one active market's country, as the page view's market picker does. | |
| compareTo | No | Prior period end YYYY-MM-DD. Requires compareFrom. | |
| compareFrom | No | Prior period start YYYY-MM-DD. Requires compareTo. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | |
| appUrl | Yes | |
| blocks | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the description's 'Does not change anything' is largely redundant. What it adds is genuinely behavioral: each block explains why it is empty when it has no data, and the URL-format requirement warns that Search Console 'may find no rows' if the scheme or form is wrong.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose and the block inventory are front-loaded in a single dense sentence, followed by the URL-format warning and the related-tools list. Nothing is padding, though the block enumeration is long and could have been tightened without losing routing value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only aggregation tool with a full output schema, the description covers the data sources, the empty-block behavior, the URL prerequisite, and sibling routing, so an agent has what it needs to call it correctly. The only minor gap is what happens when the URL falls outside the property beyond 'may find no rows'.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description goes further on the critical url parameter by specifying the exact form ('scheme included') and the constraint that the URL must belong to the workspace's property. It leaves the date-range and compare parameters entirely to the schema, which is acceptable given full coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb and resource ('Reports everything Mark knows about one page URL for a date range') and enumerates the exact content blocks returned: Search Console metrics, tracked keywords, audit issues, posts, leads, buyer questions. This lets an agent distinguish it immediately from get_search_performance, get_site_audit, and get_rankings, which each cover only a slice of the same data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete prerequisite (the URL must be on this workspace's Search Console property or one of its sites) and tells the agent to pass the URL exactly as get_search_performance returns it, scheme included. It closes with a 'Related:' list for routing, but never states when to prefer a sibling over this tool or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_performance_overviewGet Performance OverviewRead-onlyIdempotentInspect
Reports the Performance page's Overview tab for a date range: one row per funnel stage, each the same number its tab shows. Visibility is Search Console impressions; Visits are Search Console clicks and PostHog site pageviews; AI answers is the Named rate per engine from the latest weekly check in the market (no compare, no target, never one blended number); Leads are first-touch leads Mark recorded, counted on the Pacific Time days Search Console reads. Each row has stage, metric, value, previous and changePercent (with compare), target, dataThrough, connection (ready, or why there is no number, such as not_connected, no_property, no-posthog, no-signal or failed) and appUrl, the tab it opens. A failed Site pageviews row has failure: busy means PostHog didn't answer in time (it runs 3 queries at once per project and queues the rest), so try again in a minute; the PostHog connection is fine. error is any other failure, such as lost access, so check the PostHog connection. target is { month, target, actual, progressPercent }, exactly as the Targets page and get_content_performance compute it, and only when from to to is one target month (a whole past month, or this month from the 1st to today); today only leads have a matching KPI metric. compare adds the window of the same length just before. Does not change anything. Related: get_search_performance, get_visitor_locations, get_ai_visibility, get_content_performance.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Range end YYYY-MM-DD. | |
| from | No | Range start YYYY-MM-DD. Defaults to the last 28 settled days. | |
| compare | No | Add the previous window of the same length. | |
| marketId | No | One active market: Search Console filters to its country and AI answers reads it. Defaults to all markets and the priority market. |
Output Schema
| Name | Required | Description |
|---|---|---|
| to | Yes | |
| from | Yes | |
| rows | Yes | |
| appUrl | Yes | |
| compareTo | Yes | |
| compareFrom | Yes | |
| showTargets | Yes | |
| targetMonth | Yes |
get_plan_usageGet Plan UsageRead-onlyIdempotentInspect
Shows this workspace's Mark plan (none, starter, growth, enterprise), subscription status, billing interval, trial end and current period end, and the 4 plan caps with used and limit: sites, trackedKeywords, aiPrompts (active buyer questions times configured active markets) and socialAccounts. limit is null when nothing limits that cap. These are the numbers Settings > Billing shows; the card on file shows only there. Starting a trial, paying, upgrading or changing the card happens only in the Mark app: billingUrl opens Settings > Billing, and upgradeUrl is set when a bigger plan is available. Does not change anything. Related: get_workspace.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| caps | Yes | |
| plan | Yes | |
| status | Yes | |
| billingUrl | Yes | |
| upgradeUrl | Yes | |
| trialEndsAt | Yes | |
| billingInterval | Yes | |
| currentPeriodEnd | Yes |
get_postGet PostRead-onlyIdempotentInspect
Use this when you need one post's details to act on it: to edit it, check its media or checks, approve or review it at its current rev, or read several posts for a task. It returns data and draws nothing; when the person wants to see or review a post themselves, use show_post. Returns one post: body, channel fields, media (asset ids and names; on an X thread, meta.thread holds the replies and meta.threadMedia the asset ids on each reply, in the same order, with post 1 holding the rest; a social post's images from the CMS are meta.cmsImages, and meta.mediaOrder, when set, is the order of post 1's media across both), schedule, status, updatedAt, claim flags, comments and approval history, who approved it (approvedBy: { id, name, at }; name is "Mark (automatic)" for auto-approval and the raw id when the name cannot be resolved; null unless the post is approved, scheduled or published), the live URL (externalUrl), the reason it failed or was not sent (reviewNote), the handoff of an approved social post to the publisher (handoff: { state: handing_off } for the few seconds before it reads scheduled, { state: stuck, reason } when it can't go, with the fix: no scheduled time, no connected account for the channel, or no progress 5 minutes after approval; on an approved LinkedIn Article { state: publish_by_hand, reason } before its scheduled time and { state: publish_now, reason } from it on; null on every other status and every website post), the buyer questions a website post answers (buyerQuestions: id, question), the idea it was made for (idea: id, title, archived; null when none), and, on a refresh of a live page Mark published, refresh: { text, pageUrl } with the reason Mark queued it (null otherwise; approving updates that same page). Blog, FAQ and competitor posts also carry website: where the page goes, its delivery state (preview, queued, sent_to_cms, published, taken_down, failed, removed, conflict, out_of_sync), the page URL, the draft preview link on the tenant's site (previewUrl) with previewSentAt and previewStale for a pre-approval preview, previewLeftAt (set when the post was rejected or archived and Mark left that preview draft in the CMS; reviewNote says why), previewBlocked (why send_cms_preview is refused, or null), a failed job id to pass to sync_connections retryJobId, a live retry error when the job is still pending, and the exact document Mark sends to the CMS. conflict means the CMS page changed since Mark last sent it and needs an explicit overwrite-or-keep choice; conflictDiff then lists each changed field with its CMS value (cms) and Mark's value (mark); choose with resolve_cms_conflict. checks runs Mark's six content checks on the current body and meta (exclusion, char_limit, required_meta, ai_fluff, unsourced_number, placeholder). revisionChecks are the results Mark stored for the current rev when it was sent to review, the ones the reviewer sees ([] at rev 0 or when Mark didn't check that revision). rev is the frozen revision. It advances on submit, and when save_post edits a post in review, approved or scheduled; saving a draft leaves it alone, and updatedAt confirms that save. Call this before approve_posts, review_post, or a save_post edit to a post in review, so you have the current rev. Optional timezone (IANA) renders scheduled and published times in that zone; it does not change stored data. Related: show_post, search_posts, save_post, approve_posts.
| Name | Required | Description | Default |
|---|---|---|---|
| postId | Yes | The post id from search_posts or save_post. | |
| timezone | No | IANA zone to render times in. Does not change stored data. Defaults to the workspace timezone. |
Output Schema
| Name | Required | Description |
|---|---|---|
| post | Yes |
get_rankingsGet RankingsARead-onlyIdempotentInspect
Shows tracked keyword positions now and over time, with winners and losers. Related: list_saved_keywords, save_keywords.
| Name | Required | Description | Default |
|---|---|---|---|
| siteId | No | Site to read. Defaults to the primary site. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| history | Yes | |
| overview | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the full safety profile (readOnly, idempotent, non-destructive, closed-world), so the bar is lower. The description adds useful signal that results are comparative across time ('winners and losers'), but says nothing about timeframe defaults, data freshness, or aggregation granularity.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the core purpose before the routing hint. Every clause earns its place, though the Related line is terse enough to be slightly ambiguous about intent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists and the single parameter is documented, so the description needn't explain return values. Combined with annotations covering safety, what's present is nearly sufficient for correct invocation; only the timeframe/scope defaults remain unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one optional parameter (siteId) with 100% schema description coverage, so the schema already carries the semantics and the description adds no further detail. Baseline 3 applies when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Shows') and resource ('tracked keyword positions') with the added scope 'now and over time, with winners and losers,' which tells an agent it returns a time-series comparison rather than a raw list. It nods at siblings via the Related line, but doesn't clearly distinguish itself from near-neighbors like get_search_performance or run_rank_check.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'Related: list_saved_keywords, save_keywords' line implies the surrounding workflow (view saved keywords, check their positions) but never states when to use this instead of get_search_performance or run_rank_check. Usage is inferable but not explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_search_performanceGet Search PerformanceARead-onlyIdempotentInspect
Reports Google Search Console results (queries, pages, clicks, impressions, position), including striking distance queries (positions 5–20) and anomalies. The text repeats totals and the top 10 pages, queries, striking distance rows and anomalies as markdown and as a fenced JSON block. Pass compareFrom and compareTo for prior-period totals. Requires a connected Search Console property. Related: inspect_url, list_saved_keywords.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Range end YYYY-MM-DD. | |
| from | No | Range start YYYY-MM-DD. Defaults to the last 28 settled days. | |
| compareTo | No | Prior period end YYYY-MM-DD. Requires compareFrom. | |
| compareFrom | No | Prior period start YYYY-MM-DD. Requires compareTo. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| exceptions | Yes | |
| performance | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive, closed-world behavior, so the safety profile is covered. The description adds real context beyond that: output is duplicated as markdown plus a fenced JSON block, is capped at the top 10 rows per section, and striking-distance analysis is limited to positions 5-20.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with purpose and contents before output format, parameters, and prerequisites. The output-format sentence is dense but every clause carries information; no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers prerequisites, parameter pairing, output shape, and related tools for a 4-param tool with an output schema. Since an output schema exists, return values need no further explanation; the remaining gap is the absence of routing guidance against similar reporting siblings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so 3 is the floor, but the description adds meaning the schema lacks: compareFrom/compareTo produce prior-period totals, and 'from' defaults to the last 28 settled days is reinforced with intent. It explains the purpose of the comparison parameters rather than just their format.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Reports) and resource (Google Search Console results) and enumerates the returned entities (queries, pages, clicks, impressions, position). It does not sharply distinguish itself from near-siblings like get_content_performance or get_ga4_organic_overview, though the 'Related' line names inspect_url and list_saved_keywords as adjacent tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a prerequisite ('Requires a connected Search Console property') and points at related tools, but never states when to choose this over get_content_performance or get_ga4_organic_overview, nor any when-not-to-use condition. Usage is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_setup_statusGet Setup StatusRead-onlyIdempotentInspect
The workspace's setup checklist, the same rows in the same order as the setup card on Home and the setup email: website, market, brand voice, web analytics, content sources, social accounts, buyer questions, posting times, connect an agent. Each row has state done, todo or skipped and an in-app action URL. gaps lists the todo rows, each fix naming the tool to call or the page to open. ready is true once every row is done or skipped, so it does not promise that drafting or research will work: a skipped market still blocks keyword research. Does not change anything. Related: skip_setup_step, set_up_market, save_site, get_connect_link, update_posting_slots.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| gaps | Yes | |
| rows | Yes | |
| ready | Yes | |
| appUrl | Yes |
get_site_auditGet Site AuditARead-onlyIdempotentInspect
Returns the latest site audit: score, issues by severity with affected pages, the prioritized fix plan, and aiCrawlerAccess: what the site's robots.txt says to each AI crawler (allowed, blocked, no rule, or unknown), not whether an edge or WAF lets it through. Each page carries render: how a crawler that runs no JavaScript reads it, as class js_heavy (needs JavaScript), static_html (pre-built HTML) or raw_html (content in the HTML, no sign it was pre-built), or null with why when its raw fetch failed, plus keyPage (homepage, pricing, compare, demo, contact and similar); a js_heavy key page is a fix candidate. Sites that serve AI bots pre-rendered HTML by user agent (dynamic rendering) still read as js_heavy, because Mark fetches with its own user agent. Four checks are recommendations that do not change the score: article_schema_incomplete (a post's Article JSON-LD lacks recommended fields such as a Person author), schema_only_after_js (JSON-LD that appears only after JavaScript runs), ai_crawler_blocked (robots.txt blocks an AI search or user-fetch bot) and hub_missing (the homepage header and footer miss one or more of these sections: features or services, pricing, compare, resources, and company; detail.missing lists them). Two site-structure checks do count: money_page_few_links (a pricing, feature, service, product or comparison page with fewer than 2 internal links; detail.inboundLinks) and standard_page_missing (no Privacy, Terms, or Contact or Support page, or the one found returns 4xx or 5xx or has under 50 words; detail.missing and detail.broken). agenticReadiness holds Google Lighthouse's experimental agentic browsing checks (Chrome 150+, may change), run through PageSpeed Insights on up to three pages: each check is pass, fail, na, informative or error (couldn't check), read as N of M passed over pass and fail only, never a score; llms.txt is Mark's own fetch by Lighthouse's rules; markdown (what Accept: text/markdown returns) and links (the homepage's Link header) are Mark's facts, not scored; a failing check is also an informational agentic_* issue. With saved identity links, the incomplete Organization schema finding points (appUrl) at the Brand page's Organization JSON-LD, which get_brand_context returns as organizationJsonLd. aiCrawler404s (primary site with PostHog connected, else empty) lists pages AI assistants can't find: paths assistants fetched 3+ times in 7 days, over 2+ days or from 2+ assistants, that answered 404 on Mark's daily check, each with hits, assistants, checkedAt and a recommendation: redirect (a 301 to url, with the matchedTerms), keep_404 (no confident match; redirecting to an unrelated page is a soft 404), no_audit (run an audit for a suggestion) or publish_file (robots.txt, a sitemap, llms.txt or /.well-known/: publish the file rather than redirect). Dismissed paths are left out. A site with no audit yet returns audit null when it has aiCrawler404s, and an error otherwise. Poll this after run_site_audit. Related: run_site_audit, check_site_readiness, get_brand_context, dismiss_ai_crawler_404.
| Name | Required | Description | Default |
|---|---|---|---|
| siteId | Yes | Site id from list_sites. |
Output Schema
| Name | Required | Description |
|---|---|---|
| audit | Yes | |
| appUrl | Yes | |
| aiCrawler404s | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent, non-destructive, closed-world), and the description still adds substantial behavioral context: the null-audit-vs-error behavior, that dismissed paths are excluded, that recommendations do not change the score, that agenticReadiness is reported as 'N of M passed, never a score', and that dynamic rendering is misread as js_heavy. That is real disclosure an agent cannot get from structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single unbroken block of roughly 500 words with no headings, lists, or paragraph breaks, mixing purpose, output semantics, edge cases and sibling pointers. Much of the return-value detail (render classes, check names, agenticReadiness states) restates what the existing output schema already encodes, and the density makes the important routing sentence ('Poll this after run_site_audit') easy to miss.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, the description is more than adequate: it covers the no-audit case, the error case, scoring vs non-scoring checks, and pointers into get_brand_context and dismiss_ai_crawler_404. Nothing an agent needs in order to call this one-parameter read tool correctly is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
One parameter with 100% schema description coverage ('Site id from list_sites.'), so the schema already carries full meaning and the baseline is 3. The description adds no format, source, or validation guidance for siteId, and none is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource: 'Returns the latest site audit', then enumerates the payload (score, issues by severity, fix plan, aiCrawlerAccess). An agent immediately knows this is a read of an existing audit rather than a trigger. It lists related siblings at the end but never states the decision rule that separates it from check_site_readiness or get_brand_context, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Poll this after run_site_audit' gives a concrete temporal trigger, and the 'Related:' line names run_site_audit, check_site_readiness, get_brand_context and dismiss_ai_crawler_404. However, it only lists the alternatives without saying when each is preferred or excluded, and the tie-in with dismiss_ai_crawler_404 is only implied by the 'Dismissed paths are left out' sentence.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_visitor_locationsGet Visitor LocationsRead-onlyIdempotentInspect
Where your site's visitors were over a period, by country, from your PostHog project: the Performance page's Visitors tab. A visitor is a PostHog person; countries are every located country, most visitors first, each with its ISO alpha-2 code, name, visitors and pageviews. unknown counts visitors PostHog couldn't place (GeoIP off, a reverse proxy that hides visitor IPs, or cookieless mode, where PostHog drops the IP); unknown.cookieless is how many of them came in cookieless mode. total sums the rows, so someone seen in two countries counts twice. state is ready, no-posthog (not connected), no-signal (PostHog has received no events yet) or failed, with reason: busy means PostHog didn't answer in time (it runs 3 queries at once per project and queues the rest), so try again in a minute; the PostHog connection is fine. error is any other failure, such as lost access, so check the PostHog connection. source ai_referral keeps only visits opened from an AI assistant's answer (ChatGPT, Perplexity, Claude, Gemini, Copilot and others), matched by referring domain or utm_source: the AI referrals card on the AI assistants tab. It is a floor: assistant clicks that arrive with no referrer and no utm_source can't be counted. Rank AI referrals by visitors, not pageviews: on a single-page site every pageview of the visit keeps the AI referrer, on a multi-page site only the first does. Does not change anything. Related: get_ai_visibility, get_content_performance, get_setup_status.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Range end YYYY-MM-DD. | |
| from | No | Range start YYYY-MM-DD. Defaults to the last 28 settled days. | |
| source | No | all (default): every visit. ai_referral: only visits from an AI assistant's answer. |
Output Schema
| Name | Required | Description |
|---|---|---|
| to | Yes | |
| from | Yes | |
| appUrl | Yes | |
| visitors | Yes |
get_website_cmsGet Website CMSRead-onlyIdempotentInspect
Reads every connected website CMS: provider, site URL, status, publish mode (draft or live), each channel's collection and field mapping (including which provider that channel publishes to), the collections and fields Mark discovered, and a suggested mapping for each unmapped channel. mediaCollections lists the media collections Mark can read (search_cms_media and save_post take any of them; a website cover takes only the collection its cover field accepts, else mediaDestination); mediaDestination is where Mark uploads a website post's Mark images when it publishes (null: Mark uploads nothing). The API key is never returned. Connecting (site URL and key) happens in the Mark app only. Related: update_website_cms, submit_post, approve_posts.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| cms | Yes | |
| appUrl | Yes |
get_weekly_briefGet Weekly BriefARead-onlyIdempotentInspect
The Monday weekly brief members get by email: posts waiting for review, the posts going out in the 7 days after it is sent (upcoming: approved and scheduled posts, those someone publishes by hand first, each with id, channel, title, scheduledAt and handoff, where a LinkedIn Article reads publish_by_hand; capped at 10, with totalCount and manualCount; the 7 days run from that Monday's 08:00 send time, so a mid-week read still lists posts whose time has passed), the last 7 settled Search Console days against the 7 before with tracked keywords that moved, the priority market's latest AI answer check (named and cited per engine, share of voice, wrong answers flagged that week), and up to 3 suggested next actions. A section with no data is null. weekOf picks the Search days; posts in review, tracked keywords and AI answers are always the current ones. Returns markdown and a fenced JSON block with app links. Does not change anything or send email. Related: get_search_performance, get_ai_visibility, search_posts.
| Name | Required | Description | Default |
|---|---|---|---|
| weekOf | No | The Monday the brief is for, YYYY-MM-DD. Defaults to this week's Monday in the workspace timezone. |
Output Schema
| Name | Required | Description |
|---|---|---|
| search | Yes | |
| weekOf | Yes | |
| waiting | Yes | |
| upcoming | Yes | |
| aiAnswers | Yes | |
| nextActions | Yes | |
| settingsUrl | Yes | |
| businessName | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive/closed-world, and the description adds real context beyond them: no email is sent, nothing is changed, empty sections return null, the upcoming list is capped at 10 with totalCount and manualCount, and the return shape is markdown plus a fenced JSON block with app links. It stops short of describing auth or workspace/timezone prerequisites.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The opening clause is well front-loaded and every detail is arguably load-bearing, but the body is one ~200-word sentence built from nested parentheticals, which makes it hard to parse and pushes key facts (the cap, null behavior) deep into the middle.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a composite digest tool with an output schema, the description covers section-by-section content, the 7-day window semantics, null handling, list caps, return format and the no-side-effect guarantee. An agent has everything needed to call it correctly with or without weekOf.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single weekOf param, so the schema baseline is 3. The description goes further by scoping the parameter's effect: weekOf selects only the Search Console comparison days while review posts, keywords and AI checks are always current, which the schema does not say.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific resource (the Monday weekly brief delivered by email) and enumerates its four sections plus the suggested actions, so an agent knows exactly what it returns. Differentiation from siblings is only gesture-level via the trailing 'Related:' list rather than a condition-based contrast with get_search_performance/get_ai_visibility.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: 'Related: get_search_performance, get_ai_visibility, search_posts' points at the component tools, and 'weekOf picks the Search days; posts in review, tracked keywords and AI answers are always the current ones' clarifies scope. But there is no explicit 'use this when you want the digest; use X instead when you want only…' routing, so the agent must infer when this digest beats its siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_workspaceGet WorkspaceARead-onlyIdempotentInspect
Shows which Mark workspace you're acting in: your role, timezone, members, sites, integrations, a short line per channel (connected account, approval mode), and what needs attention now (posts awaiting review, search exceptions, readiness issues). mcpUrl is this workspace's own MCP address, for adding it as a separate connector in clients like Claude that take each URL once. Use it first in a session, or when switching tasks, to see the workspace state. For which social accounts are connected and each channel's rules, call list_channels. For website posts (blog, FAQ, competitor pages), call get_website_cms. Does not change anything. Related: list_channels, get_brand_context, list_connections, search_posts, get_website_cms.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | |
| role | Yes | |
| orgId | Yes | |
| sites | Yes | |
| appUrl | Yes | |
| mcpUrl | Yes | |
| members | Yes | |
| channels | Yes | |
| timezone | Yes | |
| connections | Yes | |
| needsAttention | Yes | |
| businessAliases | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true and destructiveHint=false, so the safety profile is covered; the description reinforces it with 'Does not change anything.' It adds real value beyond annotations by disclosing the return payload and the mcpUrl connector nuance, though it says nothing about response size or cost.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded: the resource and its payload lead, then usage, then alternatives. The first sentence is long and parenthetical, but every clause earns its place and nothing is redundant filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, yet the description goes further and helps the agent interpret them. Combined with usage guidance, sibling routing and a no-side-effects statement, nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero input parameters, so the schema has nothing to describe and there is no risk of misuse. The description adds meaning by framing the parameterless call as a session-context snapshot. Baseline 4 applies for a no-parameter tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource (the Mark workspace) and enumerates the concrete contents an agent gets back (role, timezone, members, sites, integrations, channel status, attention items, mcpUrl). It also names the siblings it is not (list_channels, get_website_cms) and the conditions that select each.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use it ('first in a session, or when switching tasks') and routes alternative needs to specific siblings: list_channels for connected accounts/channel rules, get_website_cms for blog/FAQ/competitor pages. When-not guidance is implicit but the routing is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
inspect_urlInspect URLARead-onlyIdempotentInspect
Asks Google whether a page is indexed and why or why not (coverage, canonical, last crawl). Uses your Google quota. Related: get_search_performance, get_site_audit.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Absolute https URL on the workspace's connected Search Console property. The error names the property when the page is not on it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| inspection | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, openWorld and non-destructive, so the safety profile is covered. The description adds genuinely useful non-schema context: the operation consumes Google quota, which affects call budgeting.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with the core purpose front-loaded and the quota caveat and related-tool routing trailing. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return values need no explanation, and annotations carry the safety profile. The description supplies the quota context and sibling relations, leaving only explicit when-to-use guidance as a gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With a single parameter at 100% schema description coverage, the schema fully documents the 'url' argument including the property constraint. The description adds no syntax or format detail beyond what the schema already provides, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Asks Google whether a page is indexed and why or why not') and enumerates the returned facets (coverage, canonical, last crawl). It is clearly distinguishable from siblings like get_site_audit and submit_urls_to_indexnow.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names related tools (get_search_performance, get_site_audit) but never states when to prefer this tool over them or any exclusion conditions. The 'Uses your Google quota' note implies a cost consideration but does not guide tool selection explicitly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_channelsList ChannelsARead-onlyIdempotentInspect
Lists every social channel Mark publishes to (LinkedIn, Instagram, Facebook, X, TikTok, Pinterest, YouTube): whether an account is connected and which one, plus the channel's approval mode, active flag, and recurring posting slots (weekday, local time, UTC instant, slot id, workspace timezone), and appUrl: the channel's page in Mark, where people set its slots and rules. How often a channel posts is its posting slots (update_posting_slots). rulesSaved is false when the channel runs on Mark's default rules because none were saved. This is where to check whether a social account such as a LinkedIn page is connected. list_connections shows integrations instead, where all social accounts share one Social publishing row. Optional timezone (IANA) renders slot times in that zone; it does not change stored data. Does not change anything. For which Pinterest board new pins go to, call list_pinterest_boards. Related: get_connect_link, update_channel_settings, update_posting_slots, get_channel_rules, list_pinterest_boards.
| Name | Required | Description | Default |
|---|---|---|---|
| timezone | No | IANA zone to render slot times in. Does not change stored data. Defaults to the workspace timezone. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| channels | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so the safety profile is covered; the description usefully reinforces this ('Does not change anything'). It adds genuine behavioral context beyond annotations: rulesSaved semantics (false = running on Mark's default rules) and that the timezone parameter only affects rendering, not stored data.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core resource and its returned fields, then layers differentiation and routing. The parenthetical enumeration of slot fields (weekday, local time, UTC instant, slot id, workspace timezone) is somewhat verbose given an output schema exists, but overall the text is dense rather than padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, single-optional-param list tool with both annotations and an output schema, the description covers everything needed: returned fields, special-case semantics (rulesSaved), parameter side-effect profile, and routing to related tools. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single timezone parameter is fully documented in the schema (IANA zone, no data mutation, defaults to workspace timezone). The description restates this rather than adding new syntax or edge cases, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Lists every social channel Mark publishes to') and immediately distinguishes itself from the closest sibling ('list_connections shows integrations instead'). An agent can tell what this returns and how it differs from the alternatives without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names when to use it ('This is where to check whether a social account such as a LinkedIn page is connected'), names the alternative (list_connections), and routes to further siblings (list_pinterest_boards, get_connect_link, update_posting_slots). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_claimsList Claims and SourcesARead-onlyIdempotentInspect
Lists the Claims & sources page: claims (facts drafts may state, each backed by a quote from a source) and the sources they quote. Each claim has its text, category (cert, price, lead_time, spec), sourceQuote, and its source's id, title and url. Active claims are the ones Mark's drafting and post checks use. A retired claim is kept (retiredAt) because posts that cite it keep its wording; it is never active again. Sources carry their type (note is pasted text; drive_doc syncs from Google Drive), how many claims cite them (claims, active and retired; activeClaims), and hasText (a source without text cannot back a quote). query searches claim text, quotes and source titles, and source titles, links and text, like the page's search. Pass sourceId to see one source's full text (body) and only its claims, before quoting it in save_claim. Does not change anything. Related: save_claim, retire_claim, add_source, update_source, delete_source, get_brand_context.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Case-insensitive text to search for, as on the page. | |
| status | No | Which claims to list. Default all, active first. | |
| category | No | Only claims in this category. | |
| sourceId | No | Only this source and its claims, with the source's full text in body. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| claims | Yes | |
| counts | Yes | |
| sources | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the bar is lower, and the description still adds real domain behavior: retired claims are kept (retiredAt) because citing posts retain wording and a retired claim never reactivates, plus hasText meaning a textless source cannot back a quote. The line 'Does not change anything' only restates readOnlyHint, slightly diluting the added value.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded and the sentences are information-dense, each carrying distinct semantics about claims, sources, and filtering. It runs long relative to a simple list tool, but little is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values needn't be described, and the description still covers the data model (claim fields, source fields, active/retired lifecycle) and all filtering paths. An agent has everything needed to call and interpret it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description goes further: it says query searches claim text, quotes, source titles, links and body text, and that sourceId returns the source's full text in body with only its claims. That clarifies the effect of parameters beyond the terse schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb (Lists) plus resource (the Claims & sources page), with an immediate clarification of what a claim and a source each are. The definition distinguishes itself from the mutation siblings (save_claim, retire_claim) by explicitly stating it 'Does not change anything.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete routing guidance: pass sourceId to see one source's full text 'before quoting it in save_claim,' and names the Related tools list. It explains what active vs retired claims mean in workflow terms, but stops short of an explicit statement of when to reach for this list versus other listing tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_competitorsList CompetitorsARead-onlyIdempotentInspect
Lists the competitors this workspace tracks (up to 50), with ids, names, aliases (other names AI answers count as naming them) and domains. Each one's comparisonPages gives, per kind (vs, alternative, pricing), the live post's postId and status, or null when it has none. Pass includeUntracked to also see ones that were unstarred. Related: track_competitor, set_competitor_aliases, get_competitor_scorecard, draft_competitor_page.
| Name | Required | Description | Default |
|---|---|---|---|
| includeUntracked | No | Also list competitors that are no longer tracked. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| competitors | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorld=false, so the safety profile is covered structurally. The description adds real behavioral context beyond that: the 50-item cap, the null-when-absent semantics of comparisonPages, and the effect of includeUntracked. It does not discuss pagination beyond the cap, but that is minor.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with scope and shape, then the parameter behavior, then routing. No filler; the parenthetical defining aliases as 'other names AI answers count as naming them' resolves ambiguity in a single clause.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present the description needn't enumerate return values, yet it usefully previews comparisonPages. Combined with annotations covering safety and a fully documented single parameter, nothing an agent needs to invoke this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds semantic nuance the schema lacks: the schema says 'no longer tracked' while the description clarifies this means 'unstarred.' That extra interpretation is genuinely useful for a single-param tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Lists the competitors this workspace tracks') and immediately bounds the scope with a row cap and the fields returned (ids, names, aliases, domains, comparisonPages). The explanation of comparisonPages per kind (vs, alternative, pricing) is precise enough that an agent knows exactly what it gets back.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a conditional usage rule for the one parameter ('Pass includeUntracked to also see ones that were unstarred') and routes the agent via a 'Related' list of siblings (track_competitor, set_competitor_aliases, get_competitor_scorecard, draft_competitor_page). It stops short of explicitly stating when to prefer get_competitor_scorecard over this tool, so no exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_connectionsList ConnectionsARead-onlyIdempotentInspect
Lists integrations (Google, Search Console, GA4, Drive, analytics, CRM, email, Social publishing, and the website CMS) with health, last sync and failed jobs. Social publishing is one integration covering every social account, so this does not show which LinkedIn, Instagram or other accounts are connected: call list_channels for that. For the website CMS, call get_website_cms. For google_drive, lastSyncSummary has the last finished sync's counts: created, updated, unchanged, failed, complete, and skipped by reason (shortcut, unsupported_type, too_large, trashed, folder_not_readable). nextAction is the one-line total. What the customer can change per reason: shortcut, move or copy the original files into the shared folder (Mark does not follow shortcuts); unsupported_type, download Sheets, Slides, or Forms as PDF into the folder; too_large, files over 400 MB are not imported; trashed, restore the file; folder_not_readable, share the folder with Mark and add its link. Connecting still happens in the Mark app — call get_connect_link for the in-app URL, then sync_connections. connectionId is the provider name used by sync_connections, update_connection_settings, disconnect_connection and get_connect_link. Related: list_channels, get_connect_link, sync_connections, get_website_cms.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| connections | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, but the description adds substantial context they do not carry: the composition of lastSyncSummary (created, updated, unchanged, failed, complete, skipped reasons), what nextAction means, and per-reason remediation for skipped Drive files (shortcuts, unsupported types, >400 MB, trashed, unreadable folders). It also documents the cross-tool identity of connectionId.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and routing in the first sentences, and every paragraph is information-dense. However, the middle paragraph detailing lastSyncSummary fields and per-reason remediation is heavy relative to the rest and partly overlaps the output schema, which an output schema already exists to describe.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only list tool with an output schema, the description covers everything an agent needs: what is listed, what is not listed and where to go instead, the identifier vocabulary shared with sibling tools, and the correct path to actually create a connection. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4 and the schema has nothing to explain. The description goes slightly beyond by defining connectionId as 'the provider name used by sync_connections, update_connection_settings, disconnect_connection and get_connect_link', which is genuinely useful interoperability context even though it is not a parameter of this call.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Lists integrations') and enumerates the covered providers (Google, Search Console, GA4, Drive, analytics, CRM, email, Social publishing, website CMS) plus the returned status fields (health, last sync, failed jobs). It explicitly differentiates itself from list_channels and get_website_cms, so an agent can distinguish it from siblings without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names alternatives and the conditions that select them: use list_channels to see which social accounts are connected, get_website_cms for the CMS. It also routes the connection workflow ('Connecting still happens in the Mark app — call get_connect_link for the in-app URL, then sync_connections'), giving explicit when-to-use and when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_ideasList IdeasARead-onlyIdempotentInspect
Lists content ideas: things worth making content about, before or alongside the posts made for them. Filter active (default, not archived), no_posts (active, with no linked post) or archived, optionally by pillar. Each idea has its brief, pillar, angle, persona, buyer question, linked posts counted by stage, last published date, and, when archived, covered (has a published post) or dropped. Ideas never close on their own: only save_idea with archived: true closes one. Returns every tab's count. Does not change anything. Related: save_idea, save_post (ideaId).
| Name | Required | Description | Default |
|---|---|---|---|
| filter | No | active (default), no_posts, or archived. | active |
| pillarId | No | Only ideas with this pillar, from get_brand_context. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ideas | Yes | |
| appUrl | Yes | |
| counts | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent/non-destructive, so the bar is lower. The description still adds real value: it explains that ideas never close on their own and only save_idea with archived:true closes one, and that it returns every tab's count. It also states 'Does not change anything,' which is a mild restatement of readOnlyHint but harmless.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose, then the filter semantics, then the returned fields, then the mutating-related note. Slightly dense with the long field enumeration, but every sentence earns its place and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a 2-param read-only list tool with an output schema present, the description covers interpretation of filter values, the returned fields, archive semantics, and related tools. It does not need to explain return structure since an output schema exists; coverage is strong though not exhaustive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters (filter, pillarId) are fully documented in the schema itself. The description repeats the filter values without adding syntax or format details beyond what the schema provides, which is the baseline-for-100%-coverage case.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Lists) and resource (content ideas) and immediately defines what an idea is ('things worth making content about, before or alongside the posts made for them'), which meaningfully disambiguates it from sibling post-listing tools like search_posts.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The filter enum is explained inline (active/no_posts/archived) and the description names related tools (save_idea, save_post). However, it doesn't explicitly state when to prefer this over search_posts or get_post, so routing between listing options is left partly implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_market_locationsList Market LocationsARead-onlyIdempotentInspect
Searches the DataForSEO location and language catalog by place name (and optional language name) so you do not have to guess codes. Returns locationCode, place name, country, and languages available there. Does not save a market. Related: set_up_market, save_strategy_item, get_setup_status.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max rows to return. Default 20. | |
| place | Yes | Place name, such as United States or London. | |
| language | No | Language name or code, such as English or en. |
Output Schema
| Name | Required | Description |
|---|---|---|
| more | Yes | |
| locations | Yes | |
| nextCursor | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, openWorldHint=true and destructiveHint=false, so safety, repeatability and external reach are covered. The description adds that results come from a third-party catalog and enumerates return fields, but the field list duplicates the output schema and no rate limits, latency, or empty-result behavior is disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the purpose and value proposition before the boundary and related tools. The trailing 'Related:' list names three siblings of which only set_up_market is directly adjacent, which is mild noise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only lookup with an output schema and full annotation coverage, nothing needed to call it correctly is missing: purpose, input semantics, no-side-effect guarantee, and adjacent tools are all present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so 'place', 'language' and 'limit' are already documented with examples and bounds. The description only restates that search is by place name with optional language name, adding no syntax or format detail beyond the schema, which is the baseline case.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Searches the DataForSEO location and language catalog by place name'), plus what it returns. It also draws an explicit boundary ('Does not save a market'), which separates it from the setup/save siblings without needing their schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear motivating context ('so you do not have to guess codes') and one negative boundary ('Does not save a market'), plus a pointer to related tools. It stops short of stating when to prefer this over set_up_market or get_setup_status in concrete terms, so it is context without full routing rules.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_pinterest_boardsList Pinterest BoardsARead-onlyIdempotentInspect
Lists the connected Pinterest account's boards (id, name, privacy), read live from Pinterest, and currentBoardId: the default board new pins go to when the post names no boardId (null if none is stored). Use it to turn a board the requester names into its id, for a post's boardId or for set_pinterest_board. Fails when Pinterest is not connected or the board list cannot be loaded. Does not change anything. Related: set_pinterest_board, list_channels.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| boards | Yes | |
| currentBoardId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/openWorld/non-destructive, so the bar is lower, yet the description still adds real context: data is 'read live from Pinterest,' failure occurs when Pinterest is not connected or the list cannot load, and currentBoardId is null if unset. It does not cover pagination or freshness/latency behavior, so not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four compact sentences, front-loaded with what is returned and followed by usage, failure modes, and related tools. 'Does not change anything' is mildly redundant with readOnlyHint/destructiveHint annotations, a small amount of non-earning text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values needn't be spelled out, yet the description still names fields and the null case; combined with failure conditions and the related-tool routing, an agent has everything needed to call this zero-arg, read-only tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero input parameters, so the baseline is 4. The description's explanation of currentBoardId describes output semantics rather than inputs, which adds value but is technically beyond the parameter dimension.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Lists the connected Pinterest account's boards') with the returned fields enumerated, and explicitly disambiguates from siblings set_pinterest_board and list_channels. An agent can tell this apart from other list_* tools immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete use case: 'turn a board the requester names into its id, for a post's boardId or for set_pinterest_board,' plus the failure condition when Pinterest is not connected. It doesn't explicitly state when NOT to use it or compare against list_channels beyond the trailing 'Related' line, so it stops short of 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_saved_keywordsList Saved KeywordsARead-onlyIdempotentInspect
Lists your saved keywords with tags, exclusions, tracking status and latest rank. Does not change anything. Related: save_keywords, get_rankings.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | 1-based page. Default 1. Prefer limit/cursor. | |
| limit | No | How many rows to return. Default 20, max 100. | |
| query | No | Substring match on the keyword. | |
| cursor | No | Opaque cursor from a previous call's nextCursor. | |
| source | No | How the keyword was saved. | |
| audience | No | Only included, or only excluded, keywords. | |
| pageSize | No | Rows per page. Default 20, max 100. Prefer limit. | |
| tagNames | No | Only keywords that have all of these tags. |
Output Schema
| Name | Required | Description |
|---|---|---|
| more | Yes | |
| page | Yes | |
| items | Yes | |
| total | Yes | |
| appUrl | Yes | |
| pageSize | Yes | |
| nextCursor | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, destructiveHint=false, idempotentHint, and openWorldHint=false. The description's 'Does not change anything' only repeats that safety profile and adds no new behavioral context such as pagination behavior, permissions, or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler, front-loading what the tool returns before noting it is non-mutating and listing related tools. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema, rich annotations, and full schema coverage, the description does not need to explain return values or parameter details. It is nearly complete, though it could add a brief note on when to prefer this list over related keyword tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all eight parameters, including pagination, query, source, audience, and tagNames. The description adds no parameter-level meaning beyond what the schema provides, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: lists saved keywords, and names the data returned (tags, exclusions, tracking status, latest rank). It also names related tools, so an agent can distinguish this read operation from save_keywords and get_rankings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies retrieval of saved keywords and names related tools, but it gives no explicit when-to-use guidance, no exclusions, and no condition for choosing this over alternatives. Usage is inferable but not spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_sitesList SitesARead-onlyIdempotentInspect
Lists your websites with the primary site, agent-readiness score and latest audit summary. Does not change anything. Related: get_site_audit, check_site_readiness.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| sites | Yes | |
| appUrl | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint=false, so the safety profile is fully covered. The description's 'Does not change anything' reinforces that but adds no new behavioral detail such as result size limits or ordering; with the annotation bar already met, this is adequate rather than rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with the concrete payload listed first and the safety note plus related tools second. No filler, and the most decision-relevant information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value detail is not needed, and the description still flags what the listing contains. With no parameters and complete annotations, the only mild gap is the absence of explicit routing criteria against the two named related tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, so the baseline of 4 applies. The description correctly adds nothing about parameters, and there is nothing to clarify.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource ('Lists your websites') and it names the payload fields returned (primary site, agent-readiness score, latest audit summary). It partially distinguishes itself by pointing at get_site_audit and check_site_readiness as related-but-different tools, though it never states explicitly what makes it distinct from them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Related: get_site_audit, check_site_readiness' gestures at adjacent tools but doesn't say when to pick this list tool over them or when to drill into a specific site. Usage is implied rather than stated, so the agent must infer the routing decision.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_wrong_answersList Wrong AnswersARead-onlyIdempotentInspect
Lists wrong AI answers, newest seen first: ones members logged from any engine (including ones Mark doesn't check weekly), and competitor_instead ones the weekly check filed (source weekly_check). Each has a reason. Filter by status and buyer question. Does not change anything. Related: save_wrong_answer, get_buyer_question_answers.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | At most this many rows, newest first (default 25). | |
| status | No | open (default), resolved, or all. | open |
| question | No | Active buyer question id, or its exact text. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| wrongAnswers | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent/non-destructive, so 'Does not change anything' is largely redundant. The description earns credit for the source taxonomy (member-logged from any engine vs weekly_check competitor_instead) and 'each has a reason', which are behavioral details not in the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded and the three short blocks are efficient. The clause 'including ones Mark doesn't check weekly' is dense insider jargon that costs a little readability, keeping it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With full annotations, 100% schema coverage, an output schema, and no nested objects, the description supplies everything needed: what is returned, ordering, source provenance, and filters. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description mentions filtering by status and buyer question and ordering by newest, which corroborates the schema but adds no syntax or format detail beyond it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (lists) and resource (wrong AI answers) with ordering (newest seen first) and scope (member-logged entries plus weekly_check competitor_instead entries). This lets an agent distinguish it from save_wrong_answer and get_buyer_question_answers without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context for use (filter by status and buyer question) and names related tools for routing. It does not, however, state an explicit when-not-to-use or a condition that selects this over get_buyer_question_answers, so it falls short of a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
record_post_publishedRecord Post PublishedIdempotentInspect
Records that an approved LinkedIn Article (channel linkedin_article) is live: pass its id and the https linkedin.com URL LinkedIn shows for it. The post becomes published with publishedAt now and externalUrl the URL, the same as a post Mark published, and Mark reads its LinkedIn metrics daily for 30 days, then weekly until 90 days, through the connected LinkedIn account. Mark never publishes an Article itself, since LinkedIn has no API for them; a person copies the approved Article into LinkedIn at its slot time (get_post handoff reads publish_by_hand, then publish_now), then this records it. Calling again with the same URL succeeds and changes nothing. Refused for a post that isn't approved, another channel, a URL that isn't on linkedin.com or has no urn:li:share: or urn:li:ugcPost: post URN (a /pulse/ address), or a published post with a different URL. To help the person copy it, get_post gives the headline (meta.title) and the Markdown body; the cover is the asset meta.cover.assetId names, whose URL get_asset returns. Only use it once the user says the Article is live. Related: get_post, get_asset, approve_posts, get_calendar.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | The live Article's post address from LinkedIn, with its post URN in it, such as https://www.linkedin.com/feed/update/urn:li:ugcPost:7518698639439978496/ (LinkedIn's … > Embed this post shows it). A /pulse/ address is refused: it has no post URN, so Mark couldn't read the Article's metrics. | |
| postId | Yes | The approved LinkedIn Article. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| postId | Yes | |
| status | Yes | |
| externalUrl | Yes | |
| publishedAt | Yes |
refresh_ai_volumeRefresh AI Search VolumeInspect
Re-estimates how often your buyer questions are asked in AI assistants. Fetches a fresh estimate from the provider for each active buyer question, in the priority market. If this refuses because the workspace is not set up, call get_setup_status and check its rows, including skipped ones. Related: get_ai_visibility, save_strategy_item, set_up_market.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| count | No | |
| scope | No | What the run checks. |
| state | Yes |
remove_competitor_lookupRemove Competitor LookupADestructiveInspect
Removes an untracked domain from Other lookups on the competitor scorecard, in every market: deletes its unstarred competitor record and every stored lookup of it. Looking it up again runs a new lookup, and tracking it again starts fresh. Refuses a tracked competitor (untrack it first) and your own sites. A domain with nothing stored removes nothing. Related: list_competitors, untrack_competitor.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | The domain to remove, like example.com. |
Output Schema
| Name | Required | Description |
|---|---|---|
| domain | Yes | |
| removedLookups | Yes | |
| removedCompetitor | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructive/non-idempotent, but the description adds substantive behavior: it deletes both the unstarred competitor record and every stored lookup across all markets, is effectively a no-op when nothing is stored, and refuses tracked domains. This is exactly the kind of consequence detail annotations can't convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Effects are front-loaded, followed by reversibility, refusal conditions, and the no-op case, then a Related line. Each sentence carries distinct operational information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be described; the description instead covers scope, side effects, refusal cases, and the empty-state case. Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with an example (example.com), so the baseline is 3; the description adds qualification that the domain must be untracked and not a site you own, which narrows valid input meaningfully.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb+resource (remove an untracked domain's competitor lookup) plus scope ("in every market") and the exact records deleted. It clearly distinguishes itself from untrack_competitor and the delete_*/list_* siblings by naming what it does not touch (tracked competitors, own sites).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-not conditions: refuses a tracked competitor (untrack first) and refuses your own sites, and explains that re-looking-up or re-tracking starts fresh. It also names related tools (list_competitors, untrack_competitor), so the agent knows the routing alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_keywordsRemove KeywordsADestructiveInspect
Removes saved keywords and their tracking history from the workspace. This cannot be undone. Related: list_saved_keywords, save_keywords.
| Name | Required | Description | Default |
|---|---|---|---|
| savedKeywordIds | Yes | Saved keyword ids to remove. |
Output Schema
| Name | Required | Description |
|---|---|---|
| removed | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, so safety is covered structurally; the description still adds real value by disclosing that tracking history is destroyed along with the keyword and that the operation is irreversible. It does not mention permissions or partial-failure behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short clauses, front-loaded with the action and the irreversible warning, with the related-tools pointer last. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Annotations cover the safety profile and an output schema exists, so return values need not be explained. The description covers what is destroyed and irreversibility; only minor gaps like permission requirements or scope limits remain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter with 100% schema coverage, so the schema fully documents savedKeywordIds. The description adds no syntax, format, or batching guidance beyond what the schema already states, making 3 the correct baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Removes') and resource ('saved keywords and their tracking history'), which clearly separates it from delete_post, delete_site, and delete_assets. It names related siblings (list_saved_keywords, save_keywords) but does not explicitly contrast with the closest destructive alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the resource and the 'Related:' pointer to list/save tools, but there is no explicit statement of when to remove versus archive or otherwise suppress a keyword. The 'cannot be undone' line is a warning rather than routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
report_feedbackReport FeedbackAInspect
Records what the person asked you to change while drafting, and your own checks on the draft, so Mark can later suggest brand rules. Each call stores one new report. Call it at two moments: when the person states a standing rule ("never say game-changer"), before you ask whether to save it; and once on the version they accept, after save_post, with that postId. For a piece that lives outside Mark, pass externalRef instead. Each iteration is one ask: a short paraphrase in ask, its category, and scope (tenant_wide when they said it applies to everything, this_piece when only here, unsure otherwise; never guess). before, after and userQuote are optional short excerpts of the changed words and of what the person said. Keep every excerpt short, and never paste the conversation or a full draft. selfChecks list the checks you ran (check, result pass/warn/fail, reason). Recording feedback changes no rule. When the person agrees a rule, save it with save_content_exclusion (pass this report's id as feedbackId) for a phrase Mark should block or warn on, or update_brand_profile for voice guidance. Asks scoped tenant_wide or unsure come back as suggested rules from suggest_brand_rules. Related: save_content_exclusion, update_brand_profile, save_post, suggest_brand_rules.
| Name | Required | Description | Default |
|---|---|---|---|
| notes | No | Anything else worth keeping, at most 1,000 characters. Not the conversation. | |
| postId | No | The saved post this report is about, from save_post. | |
| channel | Yes | The channel being drafted. | |
| iterations | No | Up to 20 asks: {ask, category, before?, after?, userQuote?, scope}. Each text at most 300 characters. | |
| selfChecks | No | Up to 20 checks you ran: {check (at most 80 characters), result, reason (at most 300)}. | |
| externalRef | No | Link to a piece outside Mark, at most 2,048 characters. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the write/non-idempotent/non-destructive profile; the description adds the decisive context that each call appends one new report and that 'Recording feedback changes no rule', so the agent knows the side effect is scoped to storage. It also sets privacy constraints (keep excerpts short, never paste the conversation or a full draft).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded: the core action and the two invocation moments come first, with constraints and sibling routing after. The trailing 'Related:' line partly repeats tools already named in the body, which is the only redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter tool with nested arrays and an existing output schema, the description covers purpose, timing, parameter intent, privacy limits and the follow-up workflow. Return values need not be explained since an output schema exists, and nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% so the baseline is 3, but the description goes beyond it by explaining scope semantics (tenant_wide vs this_piece vs unsure, 'never guess') and characterizing before/after/userQuote as optional short excerpts. The nested-array structure is echoed but the enum guidance is the real added value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (records/stores) and resource (a feedback report of asks and self-checks), plus the downstream purpose (so Mark can suggest brand rules). It distinguishes itself from siblings by naming save_content_exclusion, update_brand_profile, save_post and suggest_brand_rules.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit invocation moments (when a standing rule is stated, before asking to save; once on the accepted version after save_post with that postId), an alternative for out-of-Mark pieces via externalRef, and clearly routes rule-saving to save_content_exclusion/update_brand_profile rather than this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reschedule_postReschedule PostAInspect
Moves a post to a new future time. A draft keeps its status; any other post goes back to review at the new time and publishes only once approved again. Pass scheduledAt for any time, or slotId and date (both, from get_calendar's open slots) to fill one posting slot occurrence: Mark puts the post at that slot's time on that date in the workspace timezone, and refuses a slot on another channel, a past occurrence, or one another post already holds, so two callers can't double-book it. The same status rules apply either way. Related: get_post, get_calendar, search_posts.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | The slot occurrence's local date (YYYY-MM-DD, workspace timezone), on the slot's weekday. Pass with slotId. | |
| postId | Yes | Post id. | |
| slotId | No | Posting slot id from get_calendar. Pass with date, instead of scheduledAt. | |
| scheduledAt | No | New publish time as a UTC ISO string, in the future. Omit when you pass slotId and date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| rev | Yes | |
| appUrl | Yes | |
| postId | Yes | |
| status | Yes | |
| scheduledAt | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial behavior beyond the annotations: a draft keeps its status, any other post returns to review and re-publishes only after approval, and the tool refuses cross-channel slots, past occurrences, and already-occupied occurrences (double-booking protection). The openWorld/idempotency hints do not carry any of this.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and status rule, then the two modes, then the refusal conditions. The single dense paragraph is efficient, though the slot-mode clause is long enough that a reader may need to re-read it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need no explanation, and the description covers the mutation's side effects, the two input modes, the prerequisite (get_calendar), the timezone interpretation, and the failure conditions. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so the baseline is 3, but the description adds real meaning: slotId and date must be passed together, come from get_calendar open slots, and Mark interprets them in the workspace timezone on the slot's weekday. It also clarifies scheduledAt must be a future UTC string.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Moves a post to a new future time') and immediately branches into the two supported modes with their distinct semantics. An agent can distinguish this from update_posting_slots or review_post without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent to pass scheduledAt for any time, or slotId+date from get_calendar's open slots to fill a slot occurrence, and names get_calendar as the source of slot ids. It lacks an explicit 'don't use this when...' exclusion, but the routing context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
research_keywordsResearch KeywordsRead-onlyIdempotentInspect
Finds keyword ideas for one to five seed terms. On labs, each idea contains its seed term. Every idea carries seed, the seed term it came from (null for a multi-seed google_ads run). Each call makes 1 request per seed term to the keyword provider (google_ads: 1 request in total), returning up to limit ideas in total. Every idea has search volume, CPC and competition. labs (the default) adds difficulty and intent; google_ads, for countries labs does not cover, has neither. A SERP overview per idea comes only with includeSerpInfo, on labs. With google_ads, close variants come back as one row listing them in closeVariants; its volume is the group's, so count it once. Results are not saved until you call save_keywords. If this refuses because the workspace is not set up, call get_setup_status and check its rows, including skipped ones. Related: check_keyword_audience, save_keywords, set_up_market.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max ideas to return. Default from the provider, up to 1000. | |
| source | No | labs (default) or google_ads. google_ads has no difficulty, intent or SERP overview. | |
| languageCode | No | Language code. Defaults to the priority market. | |
| locationCode | No | DataForSEO location. Defaults to the priority market. | |
| seedKeywords | Yes | One to five seed keywords or a topic. | |
| includeSerpInfo | No | Add a SERP overview (serpInfo) to each idea. labs only; rejected with google_ads. |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes | |
| taskId | No |
resolve_cms_conflictResolve CMS ConflictADestructiveInspect
Settles a website CMS conflict on a blog, FAQ or competitor post, the same choice as the review page buttons. Read get_post first: website.state is conflict and website.conflictDiff lists each changed field with its CMS value (cms) and Mark's value (mark). Show the user that diff and only call this when they have chosen. overwrite replaces the CMS page with Mark's version and discards the edits made in the CMS. On an approved or scheduled post Mark sends it now (outcome overwrite_queued); on a post not yet approved Mark overwrites on the next send_cms_preview or approval (overwrite_on_next_send). keep leaves the CMS page as it is (outcome kept). The post is then out of sync (website.state out_of_sync) and its review note says Mark kept the CMS version. Refused when the post is not waiting on a CMS conflict choice. Related: get_post, send_cms_preview, approve_posts.
| Name | Required | Description | Default |
|---|---|---|---|
| choice | Yes | overwrite: replace the CMS page with Mark's version, discarding the CMS edits. keep: leave the CMS page as it is; the post becomes out_of_sync. | |
| postId | Yes | The website post in conflict. |
Output Schema
| Name | Required | Description |
|---|---|---|
| outcome | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (destructiveHint, openWorldHint, non-idempotent) by disclosing exactly what overwrite discards (CMS edits), the resulting outcomes (overwrite_queued vs overwrite_on_next_send based on approval/schedule state), and the side effects of keep (post becomes out_of_sync, review note records Mark kept the CMS version). This is genuine behavioral state-machine detail.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads purpose, then prerequisite, then the two choices' effects, closing with refusal condition and related tools. Information-dense and mostly waste-free, though the outcome naming could be slightly tightened.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists so return values needn't be described; the description nonetheless covers prerequisites, both branches' outcomes, the refusal case, and sibling routing. Nothing essential for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema's enum description already covers overwrite/keep. The description adds consequence-level meaning (what each outcome does to send timing and sync state), which the enum text only partially captures.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Settles') and resource ('website CMS conflict on a blog, FAQ or competitor post') and ties it to a concrete UI affordance ('the same choice as the review page buttons'). It names related siblings (get_post, send_cms_preview, approve_posts), so an agent can place it without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly gates invocation: 'Read get_post first', 'Show the user that diff and only call this when they have chosen', and 'Refused when the post is not waiting on a CMS conflict choice.' This states both the precondition (state is conflict) and when not to call.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_external_postResolve External PostAInspect
Keeps a post published outside Mark as an unmatched external post, or links it to an existing Mark post. Admin only. Related: list_connections, get_post.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | keep leaves it external; link attaches it to targetPostId. | |
| targetPostId | No | Existing Mark post id. Required when action is link. | |
| externalPostId | Yes | Id of the unmatched external post from list_connections. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| outcome | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already disclose the mutation profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false), and the description adds the admin-only authorization requirement, which is genuinely useful. However, it does not explain the consequence of the 'link' action — e.g. whether the external post is consumed or merged — which is the key behavioral question for a resolving/mutating tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences plus a short related-tools pointer; the primary purpose is front-loaded and every clause carries information (two outcomes, auth gate, id source).
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema, full annotation coverage, and 100% parameter documentation, the description only needs to supply purpose, auth, and routing. It does that well, though it leaves the post-link side effects unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with the enum values and the targetPostId/externalPostId origins documented inline, so the schema carries the parameter burden. The description adds no syntax or format detail beyond it, making the baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb (resolve) with the two distinct outcomes (keep as unmatched external post vs. link to an existing Mark post) and names the resource precisely. An agent can distinguish this from generic post tools like get_post or list_connections without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a real prerequisite ('Admin only') and points to the sibling that supplies the input ('list_connections') plus get_post as related context. It stops short of an explicit when-not-to-use rule, but the context for invoking it is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retire_claimRetire ClaimADestructiveInspect
Retires an active claim on the Claims & sources page. Drafts and post checks stop using it. It stays listed as retired (list_claims status retired), because posts that cite it keep its wording, and it cannot be reactivated: to state the fact again, add a new claim with save_claim. To change a claim's wording, call save_claim with its id instead; that retires it and creates the new one. Related: list_claims, save_claim, get_brand_context.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | An active claim's id from list_claims. |
Output Schema
| Name | Required | Description |
|---|---|---|
| claim | Yes | |
| appUrl | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructive=true and non-idempotent, but the description adds substantial context beyond them: the retired claim stays listed, posts that cite it retain the original wording, and the action is irreversible. That irreversibility is the key behavioral fact an agent needs and it is stated outright.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the effect and consequence, then alternatives. Three sentences plus a related-tools line is slightly longer than needed but nearly every clause carries distinct information (irreversibility, cite-wording persistence, save_claim routing).
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists so return values need no explanation, and the description covers the destructive, irreversible semantics, the post-retirement visibility, and the correct alternative tool. Nothing an agent needs to call this safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with a single documented parameter ('An active claim's id from list_claims'), so the schema carries the burden. The description reinforces that the target must be an *active* claim, but adds no new syntax or sourcing detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Retires an active claim'), plus the concrete consequence that drafts and post checks stop using it. This clearly distinguishes it from the similarly-named list_claims (read) and save_claim (create/edit).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: to change wording call save_claim with the id instead, and to restate a fact add a new claim with save_claim. It also states the exclusion that reactivation is impossible, which removes an obvious but wrong alternative action.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
review_postRequest Changes or RejectADestructiveInspect
Sends a post back with decision: changes_requested plus a note, or rejects it (rejected, final). Needs the current rev. To approve, use approve_posts. On a channel set to admins only, only workspace admins can decide; anyone else is refused. A rejected post will not publish. Requesting changes unlocks the draft for editing. Rejecting a website post that sent a preview to its CMS deletes that preview draft when Mark may; otherwise cmsPreview says it is still in the CMS, where, and why, and so does the post's review note. Related: get_post, approve_posts, comment_on_post.
| Name | Required | Description | Default |
|---|---|---|---|
| rev | Yes | Current rev from get_post. | |
| note | Yes | What needs to change, or why it is rejected. | |
| postId | Yes | Post id. | |
| decision | Yes | changes_requested sends it back; rejected is final. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| postId | Yes | |
| decision | Yes | |
| cmsPreview | No | The post's preview draft in the website CMS: removed (Mark deleted it), or left_in_cms with its previewUrl and why (cannot_delete: Mark's API key may not delete it; edited: changed in the CMS; linked: a page that was in the CMS before Mark used it; live: a live page; unreachable: the CMS did not answer). Absent when the post had no preview. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true and readOnlyHint=false, but the description goes well beyond them: rejected posts will not publish, changes_requested unlocks the draft for editing, and rejecting a CMS-previewed website post deletes the preview draft or reports why it cannot via cmsPreview. That is exactly the kind of destructive side-effect detail an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core action and the sibling routing in the first two sentences, and every sentence carries substance. The final CMS-preview sentence is dense and slightly convoluted, which keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists, return values need not be explained, and the description still covers preconditions (current rev, admin-only channels), consequences of each decision, and related tools. Nothing needed to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents rev, note, postId and the decision enum. The description reinforces 'Needs the current rev' and the finality of 'rejected' but adds little syntax or format detail beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (sends a post back / rejects it) on a specific resource (post) with the two decision outcomes named. It explicitly distinguishes itself from the approve sibling, so an agent can route without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'To approve, use approve_posts', giving the alternative and the condition that selects it. It also names the admin-only channel precondition and the refusal behavior for non-admins.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_answer_engine_checkRun AI Answer CheckAInspect
Starts this week's AI answer check now, the same weekly run the schedule would start, and reports where it stands. There is at most one run per week, so calling it again returns that run with its progress (completed, failed and expected counts) and does not start a second. A workspace exempt from the weekly limit gets a new run instead once this week's run has finished; the earlier run and its answers are kept, and AI answers keeps showing them until the new run finishes. Also says when the next run is due, or why nothing was started: AI answer checks are off (an admin turns them on in Settings > Workspace; this tool does not), no buyer questions, or no market location. Covers every active market with a location; it takes no market. One run asks every active question in every such market on 6 engines (ChatGPT, Gemini, AI Overview, AI Mode, Claude and Perplexity; Claude and Perplexity through their APIs with web search on, not the consumer apps); scope.summary states it as questions × engines = checks (× markets when more than one), and get_ai_visibility's nextAnswerCheck shows it before you start. When this week's run exists, scope is that run's. Limited to 10 calls a minute per workspace when rate limiting is configured; otherwise calls pass, and the one-run-a-week rule still holds for every other workspace. Related: get_ai_visibility, set_up_market.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| run | No | |
| scope | Yes | What the run checks. |
| state | Yes | |
| appUrl | Yes | |
| nextRunOn | No | The Monday the next weekly run is due, YYYY-MM-DD (UTC). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Without relying on annotations, it discloses that calling again reuses the existing run, what happens for exempt workspaces (new run only after the prior finishes, old run and answers retained), the exposed rate limit (10 calls/min per workspace), and the engine set used. Annotations only say non-readOnly, openWorld, non-idempotent; the description adds substantial operational context on top.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in the first sentence and each subsequent sentence carries distinct information (idempotent-ish reuse, exemptions, rate limit, scope). It is dense and long, with some nested asides that could be tightened, but little is pure filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, yet the description still summarizes what comes back (progress, completed/failed/expected counts, next run timing, reasons for no start). Combined with the annotations and the scope.summary explanation, an agent has everything needed to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters, so the baseline is 4. The description usefully notes 'it takes no market' and explains that scope covers all active markets, which clarifies the absence of a targeting parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb and resource ('Starts this week's AI answer check now') and immediately scopes it as the same run a schedule would kick off. It distinguishes itself from get_ai_visibility by framing that tool's nextAnswerCheck as a pre-check rather than the trigger.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives concrete conditions under which nothing starts (checks off, no buyer questions, no market location) and points to related tools (get_ai_visibility, set_up_market). It does not explicitly state 'use get_ai_visibility instead if you only want status', so the alternative routing is implied rather than named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_rank_checkRun Rank CheckAInspect
Starts an on-demand rank refresh for tracked keywords, outside the weekly schedule. Checks the Google top 100 for each tracked keyword, 1 check per keyword in the tracker's location and language (scope.summary, like 12 keywords = 12 checks); results can take 20 minutes or more. Pass trackerId from get_rankings, or siteId to use that site's tracker. Related: get_rankings, save_keywords.
| Name | Required | Description | Default |
|---|---|---|---|
| siteId | No | Site whose tracker to refresh. Defaults to the primary site. | |
| trackerId | No | Rank tracker id from get_rankings. |
Output Schema
| Name | Required | Description |
|---|---|---|
| run | No | |
| scope | No | What the run checks. |
| state | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial behavior beyond the annotations, which only cover safety and idempotency: it discloses the cost model (1 check per keyword, '12 keywords = 12 checks'), the scope (Google top 100, tracker's location and language), and the expected latency ('20 minutes or more'). This is exactly the operational context an agent needs before firing a slow, non-idempotent job.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action and trigger, then cost/scope, then parameter routing and related tools. Dense but every clause carries information; nothing is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained. Combined with the annotations covering the safety profile and the description covering trigger, scope, cost, latency, and parameter routing, an agent has everything required to invoke this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are already documented and the baseline is 3. The description adds real value on top: it explains the relationship between trackerId and siteId, and points to get_rankings as the source of trackerId, which the schema does not say.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Starts an on-demand rank refresh for tracked keywords') and immediately scopes it against the recurring schedule ('outside the weekly schedule'). An agent can distinguish this from the nearby read tool get_rankings without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clearly defines the trigger context (on-demand, outside the weekly schedule) and routes parameter choice ('Pass trackerId from get_rankings, or siteId to use that site's tracker'). Names related tools, but stops short of an explicit when-not-to-use or a direct 'use get_rankings instead when you only want to read' exclusion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_site_auditRun Site AuditInspect
Starts a new crawl and audit of a site, up to 50 pages. Results arrive in minutes; poll get_site_audit. If this refuses because the workspace is not set up, call get_setup_status and check its rows, including skipped ones. Related: get_site_audit, list_sites, save_site.
| Name | Required | Description | Default |
|---|---|---|---|
| siteId | Yes | Site id from list_sites. |
Output Schema
| Name | Required | Description |
|---|---|---|
| audit | Yes | |
| scope | No | What the run checks. |
| state | Yes |
save_claimSave ClaimAInspect
Adds or revises a claim on the Claims & sources page. A claim is one fact drafts may state (a certification, price, lead time or spec), backed by a quote that must appear in its source's text. Claims are append-only, so posts that cite a claim keep the wording they were approved against:
Add: text, category, sourceQuote, and either sourceId (list_claims or get_brand_context sources) or source {title, body, url?} to create the source too.
Revise: id of an active claim plus only the fields that change. This retires that claim and creates a new one; the result has the new claim and retiredId. Each call creates a claim. To stop drafts using a claim, call retire_claim. Only active claims reach Mark's drafting and post checks. Related: list_claims, retire_claim, add_source, get_brand_context.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | An active claim's id, to revise it. Omit to add. | |
| text | No | The fact, in one sentence. | |
| source | No | A new source to create and quote from, instead of sourceId. Nothing is saved if the quote is not in its body. | |
| category | No | cert, price, lead_time or spec. | |
| sourceId | No | An existing source's id from list_claims. | |
| sourceQuote | No | Words copied from the source's text that prove the claim. |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| claim | Yes | |
| appUrl | Yes | |
| retiredId | Yes | The claim that was retired, if any. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial context beyond annotations: append-only model so old posts keep approved wording, revision actually retires the old claim and creates a new one returning retiredId, and the quote must appear in the source body or nothing saves. Annotations only say non-readonly/non-destructive; the description explains the real mutation semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with what the tool does, then bullets for Add and Revise, then related tools. Slightly dense with six clauses, but every sentence carries distinct operational meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a 6-param tool with nested source object and an output schema (which needn't be restated), the description is complete: it explains both call patterns, the retire-and-recreate side effect, validation of quotes, and downstream effects on drafting and post checks.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so the baseline is 3, but the description adds the cross-field logic the schema cannot: Add requires text+category+sourceQuote plus either sourceId or source, and Revise needs id plus only changed fields. It explains sourceQuote must be verbatim from the source's text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Adds or revises) and resource (a claim), then defines what a claim is and where it lives (Claims & sources page). Clearly distinguishes from siblings like retire_claim and add_source by explaining append-only semantics and the relationship to those tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly covers both modes (Add vs Revise) with the exact fields each requires, and names retire_claim as the tool for the opposite outcome. States the condition 'Only active claims reach Mark's drafting' so the agent understands the effect.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_content_exclusionSave Content ExclusionAIdempotentInspect
Creates or retires a content exclusion: a literal phrase Mark enforces (block or warn), optionally limited to one channel. BrandProfile (voice.do, voice.dont, voice.principles, doctrine) is prose guidance the model reads. ContentExclusion is phrases Mark enforces. To change an exclusion, retire it and create a new one — exclusions are never edited in place. Pass phrase and severity to create, plus feedbackId when report_feedback recorded the person asking for this rule. Pass id and active: false to retire. Related: get_brand_context, update_brand_profile, report_feedback.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Existing exclusion id. Pass with active: false to retire. | |
| active | No | false retires the exclusion. Exclusions cannot be edited; retire and create a new one. | |
| phrase | No | Literal phrase to block or warn on, at most 120 characters. | |
| reason | No | Why this phrase is excluded. | |
| channel | No | Limit to this channel. Omit for every channel. | |
| severity | No | block refuses the phrase; warn flags it. | |
| feedbackId | No | On create, the report_feedback id where the person asked for this rule. |
Output Schema
| Name | Required | Description |
|---|---|---|
| exclusion | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly=false, idempotent=true, destructive=false, so the safety profile is largely covered. The description adds genuine non-annotation context: retire is implemented as a soft deactivation via active:false rather than a deletion, and updates must be expressed as retire+create. It does not mention auth/permission requirements, but the behavioral nuance it does add is real.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences, front-loaded with the verb and object before the conceptual contrast and the create/retire mechanics. Every sentence carries information about behavior or workflow; no filler. Slightly dense for a single paragraph, but no waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation. Despite zero required parameters, the description supplies the create-vs-retire parameter recipes, the object model contrast, the linked feedback workflow, and related tools, fully covering what an agent needs to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description goes beyond it by grouping parameters per mode: phrase+severity for creation, optional feedbackId tied to report_feedback, and id+active:false for retirement. That mapping of parameters to intent is not stated in the schema itself.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb pair and resource ('Creates or retires a content exclusion') and immediately defines what the object is ('a literal phrase Mark enforces (block or warn), optionally limited to one channel'). It explicitly contrasts ContentExclusion with BrandProfile prose guidance, so an agent can distinguish it from update_brand_profile without reading schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit mode-selection guidance: 'Pass phrase and severity to create... Pass id and active: false to retire.' It also states a hard workflow rule ('exclusions are never edited in place', retire-then-create) and names related tools (get_brand_context, update_brand_profile, report_feedback), covering when this tool applies versus its neighbors.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_ideaSave IdeaAInspect
Creates, edits, archives or unarchives a content idea. To create: pass title; brief, angleId or pillarId, and buyerQuestionId are optional. To edit: pass id and only the fields that change. To archive or unarchive: pass id and archived: true or false. Archiving never changes the idea's posts. An angle sets the idea's pillar and persona to the angle's; a pillarId that contradicts the angle is refused. For a pillar on its own, pass angleId null. To draft a post from an idea, call save_post with channel and ideaId. Related: list_ideas, save_post, get_brand_context.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Existing idea id. Omit to create. | |
| brief | No | Optional detail: goal, audience, key points, call to action. null clears it. | |
| title | No | What the idea is, in a line. Required to create. | |
| angleId | No | Angle id from get_brand_context, or null to clear. Sets the pillar and persona to the angle's. | |
| archived | No | With id: true archives the idea, false unarchives it. | |
| pillarId | No | Pillar id, or null to clear. With an angle, omit it or pass the angle's own pillar. | |
| buyerQuestionId | No | One active buyer question id from get_ai_visibility, or null to clear. A website post drafted from the idea answers it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| idea | Yes | |
| appUrl | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare non-readOnly, non-destructive, non-open-world behavior, so the bar is lower, but the description adds real behavioral facts: archiving never mutates the idea's posts, and a pillarId contradicting the angle is refused. What is still missing is idempotency/retry behavior and what happens on a conflicting concurrent edit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is dense and front-loaded with the mode summary, then breaks out each mode in one sentence. Every sentence carries operational information, though the related-tools line is slightly tacked on and the block is on the long side for a single tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a seven-parameter multi-mode mutation tool with an output schema present, the description covers create/edit/archive paths, cross-field constraints, and downstream routing. Return values need not be explained given the output schema; only error/refusal handling details are left thin.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3, but the description adds cross-parameter rules the schema does not express: which fields are required per mode, that an angle sets the pillar and persona, that a standalone pillar requires angleId null, and that only changed fields should be sent on edit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a precise set of verbs and the resource: 'Creates, edits, archives or unarchives a content idea.' It clearly separates this tool from siblings like save_post (drafting) and list_ideas (reading), and the multi-mode nature is spelled out rather than implied.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-use guidance per mode ('To create: pass title', 'To edit: pass id and only the fields that change', 'To archive or unarchive: pass id and archived'), plus an explicit hand-off rule: 'To draft a post from an idea, call save_post with channel and ideaId.' Related tools are named, so routing is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_keywordsSave KeywordsIdempotentInspect
Saves keywords (from research or Search Console) and sets their tags, exclusion and rank tracking, in one call. New keywords are tracked and audience-checked (one Google top 10 fetch each) unless track is false or they are excluded. Exclude a keyword whose searchers aren't the buyer; it stops tracking. If this refuses because the workspace is not set up, call get_setup_status and check its rows, including skipped ones. Related: research_keywords, list_saved_keywords, set_up_market.
| Name | Required | Description | Default |
|---|---|---|---|
| items | Yes | Keywords to upsert. |
Output Schema
| Name | Required | Description |
|---|---|---|
| saved | Yes | |
| outcomes | Yes |
save_postSave PostInspect
Creates a new draft (omit postId; channel required) or edits an existing post: text, channel fields, media, angle, pillar, buyer questions, proposed time. Never submits or publishes. Returns a save receipt: scheduledAt, assetIds, channel, counted body length, buyerQuestions, idea, updatedAt, and checks (Mark's six content checks on the saved content, including placeholder; a fail is not a refused save, but submit_post refuses a draft while it fails). On a draft or changes-requested post, rev does not change; use updatedAt to confirm the save. A post in review, approved or scheduled needs rev (from get_post): the edit saves as the next rev and the post goes back to in review, so a person approves it again; a stale rev is refused, and so is a phrase this workspace blocks or a placeholder like [needs source]. On those posts ideaId or guideVersion alone is refused, since it would drop the approval without changing what publishes. Posts in any other status are locked. A website post that is not archived (in review, approved, scheduled, published, failed or missed) also takes postId with buyerQuestionIds alone: that replaces the buyer questions it answers and nothing else, so its status, rev, content and approval stay as they are. Asset ids that are not in this workspace are listed as dropped, never attached silently. Likewise droppedMetaKeys lists the top-level meta keys the channel does not take, which the save ignored; the save still succeeds. A LinkedIn post can carry one PDF asset (kind document) and no other media, up to 100 MB; meta.documentTitle is the title LinkedIn shows above it, else the file name. A PDF with other media, over 100 MB, or on another channel is refused with the message submit_post gives. An angle sets the post's pillar and persona to the angle's; a pillarId that contradicts the angle is refused. Website posts (blog, faq, competitor_page, landing_page) take a pillar, never an angle, plus the buyer questions the page answers (buyerQuestionIds, from get_ai_visibility). An email takes a plain-text body and meta { subject, preheader? } (preheader is the inbox preview text); Mark doesn't send email yet, so an approved email stays approved for you to send from your email tool. A LinkedIn Article (linkedin_article) takes a Markdown body and meta { title, cover? }; it needs no connected account, and once approved it waits for a person to publish it on LinkedIn and record the URL with record_post_published. ideaId links the post to an idea from list_ideas (null unlinks); linking never changes the post's pillar, persona or angle. A new draft with ideaId takes what the call leaves unset from the idea: its pillar and angle (a website post takes the pillar and persona, never the angle), its buyer question on a website post while that question is active, and a body that starts with the idea's title and brief. Call get_channel_rules first. To send it for review, call submit_post after saving. Related: get_post, submit_post, add_asset, list_ideas.
| Name | Required | Description | Default |
|---|---|---|---|
| rev | No | The post's current rev from get_post. Required to edit a post in review, approved or scheduled; ignored on drafts. | |
| body | No | Post body / caption. | |
| meta | No | Channel-specific fields from get_channel_rules. Instagram and LinkedIn: altText is the post-wide alt text and altTexts is one alt text per image in media order; a blank entry uses altText, and videos and PDFs take none. LinkedIn: documentTitle is the line LinkedIn shows above an attached PDF; blank uses the file name. Social posts (not YouTube): cmsImages: [{ mediaId, collection }] attaches images already in the connected CMS (search_cms_media), after the assets on post 1; collection is the media collection search_cms_media named (left out, the default from get_website_cms; one Mark cannot read is refused). Mark fills in the type and size of each, takes JPEG, PNG, WebP or GIF, and copies them to the platform at scheduling. They count toward media limits like assets. mediaOrder sets the order of the media on post 1 across assets and CMS images: a list of keys, an asset id as is or cms:~<collection>:<mediaId> for a CMS image (get_post shows the collection of each; an image saved before names a channel instead, cms:<channel>:<mediaId>; cms::<mediaId> for an image sent without either). An unknown or repeated key is dropped and media it leaves out goes last; without it, assets go first, then CMS images. altTexts follow this media order. meta without mediaOrder keeps the saved order; [] resets it. On Instagram, LinkedIn and Pinterest, a newly attached CMS image with blank alt text takes the CMS alt (its altTexts entry on a post with several media, else altText; on Pinterest only when it is the only image on the pin). Edit or clear it like any alt text. X: thread is the replies after the body, in order; threadMedia puts media on a reply: one list of asset ids per thread entry, in the same order ([[], ["id"]] puts id on post 3). Every threadMedia id must also be in assetIds and on one post only; post 1 gets the assetIds no reply lists. meta replaces the saved meta: when thread keeps its number of replies and threadMedia is left out, the saved threadMedia carries over; when the number changes, send threadMedia too. Each X thread post takes up to 4 images, or 1 video, or 1 GIF. Website posts (blog, faq, landing_page, competitor_page): the cover is cover: { source: "asset", assetId, alt } with an image id from search_assets / add_asset, or cover: { source: "cms", mediaId, collection, alt? } with an image already in the connected CMS from search_cms_media called with the same channel (collection left out: the default for that channel; a cover comes only from the collection the cover field accepts, else where new media goes, and any other is refused; Mark fills its type and size, alt defaults to the CMS alt, and an edited alt is written back to that CMS image on approve). alt is required before submit when the CMS takes a cover. Omit cover for no cover. An image already in the CMS goes in the body as  on its own line, with url from search_cms_media (any readable collection): on a rich-text mapping it publishes by reference with no upload and shows the alt text the CMS has (get_channel_rules says which). | |
| ideaId | No | Idea id from list_ideas, or null to unlink. Archived ideas can't be newly linked. On a new draft, unset pillar, angle, buyer questions and body come from the idea. | |
| postId | No | Existing post to edit. Omit to create a new draft. | |
| angleId | No | Angle id, or null to clear. Social posts only; refused on website posts. Sets the post's pillar and persona to the angle's. | |
| channel | No | Required to create a draft. When editing, omit it or pass the post's current channel — the channel cannot be changed here. | |
| assetIds | No | Asset ids from search_assets / add_asset, in order. Instagram takes at most 10; more is refused with an assetIds error. An X thread lists every asset in the thread here; meta.threadMedia says which reply each goes on. Website posts take no attachments: set meta.cover instead (assetIds may be omitted or hold only the cover id); other images go in the body as Markdown. | |
| pillarId | No | Pillar id, or null to clear. With an angle, omit it or pass the angle's own pillar; any other value, null included, is refused. | |
| scheduledAt | No | Proposed publish time as a UTC ISO string, or null. | |
| guideVersion | No | guideVersion from get_drafting_guide for this channel, after checking the draft against that guide. | |
| buyerQuestionIds | No | Website posts only: the buyer question ids this page answers, from get_ai_visibility. Replaces the set; null or [] clears it; omit to keep it. Active questions only, except ones already linked. Refused on social posts. Sent alone with postId, it also changes a submitted or live website post, without review; refused once archived. |
Output Schema
| Name | Required | Description |
|---|---|---|
| rev | Yes | |
| idea | Yes | The idea the post is linked to after this save. |
| appUrl | Yes | |
| assets | Yes | |
| checks | Yes | Mark's content checks on the saved content: exclusion, char_limit, required_meta, ai_fluff, unsourced_number, placeholder, and on a competitor_page also table and open_placeholder. On a draft, a fail stops submit_post; warn never does. |
| guided | Yes | Whether the post was saved against the workspace's current drafting guide. |
| postId | Yes | |
| status | Yes | |
| channel | Yes | |
| assetIds | Yes | |
| updatedAt | Yes | |
| bodyLength | Yes | |
| contentHash | Yes | |
| scheduledAt | Yes | |
| guideVersion | Yes | The drafting guide version recorded on the post, or null. |
| buyerQuestions | Yes | The buyer questions the post answers after this save. |
| characterLimit | Yes | |
| droppedAssetIds | Yes | |
| droppedMetaKeys | Yes | Top-level meta keys this channel does not take, so the save ignored them. Empty when none. |
save_siteSave SiteAIdempotentInspect
Adds or edits a website: hostname, name, whether it is primary, and lead-capture settings for the site tag. Pass siteId to edit. Related: list_sites, delete_site.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Display name for the site. | |
| domain | No | Bare hostname, e.g. example.com. Required when adding. | |
| siteId | No | Existing site id. Omit to add. | |
| capture | No | Lead-capture config: capture.kind selector|hubspot, honeypotField, gtmContainerId, cookiebotId, consentMode. | |
| primary | No | true makes this the primary website. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| siteId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=true, destructiveHint=false, so the agent knows this is a non-destructive, repeatable write. The description adds the upsert framing, which is useful, but says nothing about permission requirements, behavior on an invalid siteId, or side effects on the primary-site flag. With annotations carrying the safety profile, this is adequate but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences: the capability and field list come first, the upsert selector and related tools follow. Every clause carries information; nothing is padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be described, and the 5 parameters are fully covered by the schema. The description covers the add/edit distinction and field scope, leaving only edge-case behavior (invalid siteId, effect of promoting a new primary) unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter (including the nested capture object) is already documented in the schema. The description restates siteId's edit semantics and loosely renames 'domain' as 'hostname', adding no syntax or format detail beyond the schema. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb pair (adds or edits) and resource (a website), then enumerates the manageable fields (hostname, name, primary, lead-capture). It does not spell out how it differs from near-neighbours like update_asset or update_brand_profile, offering only a 'Related:' pointer list, so sibling differentiation is partial.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Pass siteId to edit' explicitly tells the agent which branch of the upsert it is invoking, matching the schema's 'Omit to add'. The Related list routes the agent to list_sites for discovery and delete_site for removal, but there are no stated exclusions or prerequisites (e.g. what happens with an unknown siteId).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_strategy_itemSave Strategy ItemAIdempotentInspect
Creates or updates one strategy item: kind = persona | pillar | angle | market | buyer_question | kpi_target. Personas, pillars and angles are the Messaging page (/settings/messaging); an angle is one persona × pillar pair, so create it with fields.personaId and fields.pillarId from get_brand_context. Markets are the Markets page (/settings/markets); to add one from a place name, set_up_market resolves the codes for you. Pass id to update an existing item. For a persona, pillar, angle or market, send only the fields that change; the rest, and the active flag, keep their saved values. Pillar and angle slugs cannot change after creation. A new market without priority goes after every existing one; a locationCode and languageCode pair must be one list_market_locations returns. Pass id and active only (no fields) to deactivate (false) or reactivate (true) a persona, pillar, angle, market, or buyer question without deleting it. KPI targets are the Targets page (/settings/targets): one target per metric per month. Saving a metric and month that already has one is refused with that target's id; to change it, pass its id and fields.value only (metric and month cannot change). engagement_rate is a percent: send 4.5 for 4.5%. KPI targets have no active flag — passing active is refused. Delete a KPI with delete_strategy_item. Read targets with their actuals and progress from get_content_performance (kpis). Buyer question text cannot be edited in place — create a new one, or retire with active: false. A buyer question's topic (a short label, max 60 characters) can change any time: pass id with fields.topic, or empty to clear. It touches no past or future check. Creating a buyer question also returns item.firstCheck { questions, markets, engines, checks }: what the next AI answer check sends (active questions × active markets with a location × engines). suggest_buyer_questions lists questions to start with. Returns appUrl, the page where a person sees the item. Related: get_brand_context, suggest_buyer_questions, delete_strategy_item, set_up_market, list_market_locations, get_content_performance.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Existing item id. Omit to create. | |
| kind | Yes | Which kind of strategy item. | |
| active | No | false retires the item without deleting it. | |
| fields | No | Kind-specific fields. persona: name, slug, wants, convincedBy (list), objections (list; put the answer in the line as objection: answer), pains (list), jobs (list: jobs to be done), language (list: phrases the customer uses, in their words). pillar: name, slug, formats (list), notes. angle: name, slug, personaId, pillarId. Lists and notes are optional on create. market: name, country (ISO code such as US), timezone (IANA, such as America/New_York), priority (lower comes first; optional on create), locationCode and languageCode (from list_market_locations; null clears them). buyer_question: question, topic (optional; a short label, max 60 characters; empty clears it). kpi_target: metric (posts_per_week | impressions | engagement_rate | leads | qualified | rejection_rate | cost_per_lead), month (YYYY-MM), value (zero or more, up to 4 decimal places; engagement_rate in percent, so 4.5 means 4.5%). |
Output Schema
| Name | Required | Description |
|---|---|---|
| item | Yes | |
| kind | Yes | |
| appUrl | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations give idempotentHint=true and destructiveHint=false, and the description layers on real behavior beyond that: slug immutability for pillar/angle, KPI month/metric immutability, KPI target active refusal, and buyer-question firstCheck return contents. Strong contextual disclosure; missing retry/permission semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense wall of text covering six kinds, running to hundreds of words with abrupt jumps between persona, market, KPI, and buyer-question info. Front-loading exists but readability and scannability suffer; much of this belongs in schema or linked docs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the six-entity scope, mutation semantics, output schema presence, and 4 parameters, the description covers almost everything an agent needs: creation vs update, immutability rules, deactivation flow, return value (appUrl), and related tools. Complete for the task.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so per policy the baseline is 3. The description does reinforce some semantics (personaId+pillarId come from get_brand_context, metric/month cannot change, engagement_rate is percent) that add marginal value, but the schema already documents these fields in detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a clear verb+resource ('Creates or updates one strategy item') and enumerates the six kinds, distinguishing it from sibling save_* tools. It is somewhat sprawling across six different entities, which blurs focus, but each is defined in place.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Rich routing guidance: 'to add one from a place name, set_up_market resolves the codes for you', point to suggest_buyer_questions and get_content_performance, and explicit when-to-use-id vs omit-id. Lacks explicit when-not-to-use framing but alternatives are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_wrong_answerSave Wrong AnswerAInspect
Logs a wrong AI answer, or resolves or reopens one. To log: pass engine, reason, prompt, quote and seenOn; question, market and note are optional. To resolve or reopen: pass id and resolved: true or false. Logged rows are never edited. Related: list_wrong_answers, get_buyer_question_answers.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Existing wrong answer id. Pass with resolved. | |
| note | No | Why it's wrong, e.g. invented pricing. | |
| quote | No | What the engine said, the wrong part. | |
| engine | No | Where it was seen. | |
| market | No | Active market id or exact name. | |
| prompt | No | What was asked. | |
| reason | No | Why it's wrong. Required to log; ignored on resolve or reopen. | |
| seenOn | No | YYYY-MM-DD. | |
| question | No | Active buyer question id, or its exact text. | |
| resolved | No | With id: true marks it resolved, false reopens it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| wrongAnswer | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this is a non-readonly, non-destructive, non-idempotent write. The description adds genuinely new behavioral facts: logged rows are never edited (immutability), and 'reason' is ignored on resolve/reopen. It does not cover auth/permission needs or rate limits, keeping it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences plus a related-tools line, front-loaded with the verb and mode split. Every clause carries routing or constraint information; nothing is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need no explanation, and the description compensates for the schema's zero required parameters by spelling out the per-mode required set. It leaves out error/validation behavior (e.g. what happens if id is passed with logging fields), a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds conditional semantics the schema cannot express: the required-for-logging set (engine, reason, prompt, quote, seenOn), the optional trio, and the id+resolved pairing for state changes. It does not explain enum values, which the schema already handles.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource pair ('Logs a wrong AI answer') and explicitly enumerates the three supported operations (log, resolve, reopen). It also names related siblings (list_wrong_answers, get_buyer_question_answers), so an agent can distinguish it from read-side tools without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit mode-selection rules: which parameters to pass to log versus to resolve/reopen, and which fields are optional or ignored per mode. It lists related tools but does not state when to prefer list_wrong_answers over this one, so it falls short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_assetsSearch AssetsARead-onlyIdempotentInspect
Searches the media library (images, video, documents) by text, type, source or date. Does not change anything. Related: get_asset, add_asset.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Name search. Typo-tolerant. | |
| kind | No | Filter by kind. | |
| limit | No | How many rows to return. Default 20, max 100. | |
| cursor | No | Opaque cursor from a previous call's nextCursor. | |
| source | No | How the asset entered Mark. |
Output Schema
| Name | Required | Description |
|---|---|---|
| more | Yes | |
| items | Yes | |
| nextCursor | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so 'Does not change anything' largely restates structured data. It adds no new behavioral context such as pagination behavior, result ordering, or how cursor/limit interact, though the output schema carries nextCursor. With annotations covering the safety profile, a 3 is fair.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences with zero filler; the core purpose is front-loaded and the sibling pointers come second. Nothing needs pruning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only search with a full output schema and complete annotation coverage, the description covers enough to call the tool correctly. The only gap is the unsupported 'date' filter mention and no hint that results are paginated, both minor given the schema already documents limit, cursor, and nextCursor.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so every parameter is already documented in the schema, including typo tolerance, the 20/100 limit default, and enum values. The description only gestures at the filter dimensions without adding syntax or semantics beyond the schema. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb ('Searches') and resource ('the media library') and enumerates the filter dimensions (text, type, source, date). It also names related siblings get_asset and add_asset. However, it claims a 'date' filter that no schema parameter supports, a small inaccuracy that keeps it from a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It says 'Related: get_asset, add_asset' but never states the condition that selects this tool over those siblings (e.g., use get_asset when you already know the ID). Usage is only implied by the word 'Searches'. No when-not guidance or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_cms_mediaSearch CMS MediaRead-onlyIdempotentInspect
Searches the images already in one of the connected CMS's media collections, newest first, 24 per page. get_website_cms lists the collections Mark can read (mediaCollections); left out, Mark uses the default, and the reply names the collection it searched. Use a result as a website post's cover with save_post meta.cover = { source: "cms", mediaId, collection }, or attach it to a social post with save_post meta.cmsImages = [{ mediaId, collection }]: Mark keeps a reference, never a copy, and a social post's image is copied to the platform when the post is scheduled. To put one in a website post's body, add on its own line with the result's url (the original file): on a rich-text (lexical) mapping Mark publishes it as that media document, uploading nothing.
Does not change anything; reads from the customer's CMS. These ids are not Mark asset ids. Related: save_post, get_website_cms, search_assets.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number, from 1. | |
| query | No | Matches file name or alt text. | |
| channel | No | For a website cover, its channel (blog, faq, competitor_page, landing_page): limits the search to the collections that channel's cover field accepts. Leave it out for a social post or a body image. | |
| collection | No | Media collection slug from get_website_cms mediaCollections. Left out, the default (where new media goes, else the first readable). |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes | |
| collection | Yes | |
| hasNextPage | Yes |
search_postsSearch PostsRead-onlyIdempotentInspect
Finds posts by status (including awaiting_review, i.e. the review queue), channel, scheduled time range, angle, pillar, text, or website CMS delivery state. Returns each post's current rev, updatedAt, mediaCount (assets, a website cover and images from the CMS; 0 means no media, so finding posts without an image needs no get_post per post) and, for website posts, the buyer questions it answers (buyerQuestions). A refresh of a live website page Mark published carries refresh: { text, pageUrl }, the reason Mark queued it for review; refresh is null on every other post. An approved social post moves to scheduled within seconds while Mark hands it to the publisher; handoff says handing_off then, or stuck with the reason and fix when it can't go (no scheduled time, no connected account, or no progress 5 minutes after approval). An approved LinkedIn Article carries handoff publish_by_hand before its scheduled time and publish_now from it on, each with the reason (a person publishes it on LinkedIn). handoff is null on every other post. status: approved still matches handing-off, stuck, publish_by_hand and publish_now posts. rev is the frozen revision: it stays 0 on drafts and only advances when the post is submitted (or frozen). updatedAt confirms a draft save. from and to filter by scheduled time, not created or updated. Each accepts YYYY-MM-DD or a full ISO timestamp. A date-only to includes that whole day in the workspace timezone. Unscheduled drafts never match a date range. websiteState filters blog, FAQ and competitor posts by CMS delivery: preview (a pre-approval preview draft in the CMS, not live), queued, sent_to_cms (saved in the CMS, not live), published, taken_down, failed, removed, conflict, out_of_sync, or none — the same values as get_post's website.state. Use awaiting_review to open the review queue. Optional timezone (IANA) renders scheduled and published times in that zone; it does not change stored data. Does not change anything. Related: get_post, approve_posts, review_post.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Scheduled-to: YYYY-MM-DD (includes that whole day in the workspace timezone) or a full ISO timestamp. | |
| from | No | Scheduled-from: YYYY-MM-DD (start of that day in the workspace timezone) or a full ISO timestamp. | |
| text | No | Case-insensitive match in the body. | |
| limit | No | How many rows to return. Default 20, max 100. | |
| cursor | No | Opaque cursor from a previous call's nextCursor. | |
| status | No | Filter by status. awaiting_review is the review queue. | |
| angleId | No | Angle id. | |
| channel | No | Channel id, e.g. linkedin. | |
| pillarId | No | Pillar id. | |
| timezone | No | IANA zone to render times in. Does not change stored data. Defaults to the workspace timezone. | |
| websiteState | No | Filter website posts by CMS delivery state: queued, sent_to_cms (saved in the CMS, not live), published, taken_down, failed, removed, conflict, out_of_sync, or none. Same values as get_post's website.state. |
Output Schema
| Name | Required | Description |
|---|---|---|
| more | Yes | |
| items | Yes | |
| nextCursor | Yes |
send_cms_previewSend CMS PreviewAInspect
Saves a blog, FAQ or competitor post that is not yet approved (draft, changes requested, or in review) to its website CMS as a draft, so a reviewer can open it on the customer's own site before approving. Sends the post's current saved content. Always a draft, even when the connection publishes live, and nothing goes live. Sending again updates the same CMS document; approving later updates it too. Refused, with the reason, for an approved, scheduled or published post, a channel with no CMS mapping, or a collection without drafts. Refused as a conflict when the CMS page changed since Mark last sent it; choose overwrite or keep with resolve_cms_conflict. Refused when another page in the CMS uses the post's slug: the error names each page (CMS id, title, its latest draft when it differs, live or draft, edit link, and the Mark post that owns it, if any) and says which ids useCmsPageId accepts. Then either change the slug with save_post, or call again with useCmsPageId to send into that page. Does not approve or change the post's status. Related: get_post (website.previewUrl, previewSentAt), save_post, approve_posts.
| Name | Required | Description | Default |
|---|---|---|---|
| postId | Yes | The website post to preview. | |
| useCmsPageId | No | Send into this existing CMS page instead: a page id a refusal listed as one useCmsPageId accepts (not live, and no other Mark post owns it). Replaces that page's content with this post. It stays a draft, and from then on it is this post's page. |
Output Schema
| Name | Required | Description |
|---|---|---|
| state | Yes | |
| sentAt | Yes | |
| previewUrl | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations mark this non-read-only and open-world, but the description supplies the behavioral detail they cannot: it is always a draft, nothing goes live even on a publishing connection, repeats update the same CMS document, refusals carry reasons, and the slug-collision error enumerates CMS ids, titles, draft states and owning posts. useCmsPageId replaces another page's content, which is worth knowing given destructiveHint=false, though the replacement stays scoped to a draft and does not rise to a contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense paragraphs with the core action front-loaded in the first sentence and 'Related:' cross-references last. It is longer than most definitions, but nearly every clause carries distinct operational information (state guards, idempotent-update behavior, conflict routing, slug collision payload).
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the description covers the remaining agent-relevant surface: entry conditions, refusal taxonomy, recovery paths, and cross-references to get_post, save_post, approve_posts and resolve_cms_conflict. Nothing needed to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are already documented and the baseline is 3. The description goes further by explaining how useCmsPageId is actually obtained (the ids a refusal lists as acceptable), its side effect of replacing the target page's content, and that the page then becomes this post's page permanently.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with scope: saves an unapproved post (draft, changes requested, in review) to its website CMS as a draft for on-site review. It is immediately separable from siblings like approve_posts, save_post and resolve_cms_conflict, and it explicitly notes what it does NOT do ('Does not approve or change the post's status').
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit preconditions (post must be in draft/changes-requested/in-review), explicit refusal conditions (approved, scheduled or published post; channel with no CMS mapping; collection without drafts), and explicit alternatives for each refusal case (save_post to change the slug, useCmsPageId to target an existing page, resolve_cms_conflict for overwrite/keep).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_setup_checklistEmail Setup ChecklistInspect
Emails the signed-in user the setup checklist: the rows still to do (the same rows get_setup_status and Home list) with a link to each, the rows skipped and done, and every connection waiting on the customer with its next step. Sends nothing when no row is to do and no connection is waiting. Related: get_setup_status, list_connections.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| sent | Yes | |
| message | Yes |
set_business_aliasesSet Business AliasesAIdempotentInspect
Replaces your business's other names (up to 5). An AI answer that uses your business name or any alias counts as naming you, for named rate and share of voice, in past weeks' answers too. Trims each name, drops duplicates and the business name itself; an empty list goes back to the name only. Any member can call it. Related: get_workspace, get_ai_visibility, set_competitor_aliases.
| Name | Required | Description | Default |
|---|---|---|---|
| aliases | Yes | The full list of other names, like ["Verdella"] for "Verdella Landscaping & Design Co.". Replaces the current list. |
Output Schema
| Name | Required | Description |
|---|---|---|
| businessName | Yes | |
| businessAliases | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses the up-to-5 cap, that input is trimmed, duplicates and the business name itself are dropped, that an empty list resets to name-only, and that the effect reaches past answers. This is rich behavioral context the readOnly/idempotent/destructive hints alone do not convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and effect, and nearly every clause carries information. It is densely packed but the clause about 'past weeks' answers' slightly interrupts the flow; still efficient overall.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter mutation with an output schema present, the description covers everything an agent needs to call it correctly: what it replaces, the limit, normalization behavior, reset semantics, permission scope, and related tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already gives a concrete example, so baseline is 3. The description adds genuine meaning not in the schema: the five-item ceiling and the trim/dedupe/drop-own-name normalization rules applied to the aliases parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Replaces your business's other names') with the count limit, and the Related line names the sibling set_competitor_aliases, letting an agent separate business aliases from competitor aliases without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clearly establishes context: applies to business aliases, affects named rate and share of voice including past weeks' answers, and notes 'Any member can call it.' It does not, however, give explicit when-not conditions or contrast its use against set_competitor_aliases beyond the Related link.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_check_cadenceSet Check CadenceAIdempotentInspect
Sets how often a rank check or site audit runs: cadence off (manual only) or weekly. Saving a cadence never starts a check. For rank, pass trackerId from get_rankings or siteId. For site_audit, pass siteId. Related: run_rank_check, run_site_audit.
| Name | Required | Description | Default |
|---|---|---|---|
| check | Yes | Which scheduled check to set. | |
| siteId | No | Site id. Required for site_audit. | |
| cadence | Yes | off is manual only; weekly runs once a week. | |
| trackerId | No | Rank tracker id from get_rankings. |
Output Schema
| Name | Required | Description |
|---|---|---|
| check | Yes | |
| nextAt | Yes | |
| cadence | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this is a mutation (readOnlyHint=false) that is idempotent and non-destructive. The description adds the genuinely non-obvious trait that saving a cadence has no immediate side effect ('never starts a check'), which is the key behavioral fact an agent needs. It omits permission requirements and return behavior, but the safety profile is otherwise covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences: purpose and enum values first, the non-obvious side-effect caveat second, then parameter routing and related tools. Every sentence earns its place with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with full annotation coverage, 100% schema coverage, and an output schema (so return values need not be described), the definition supplies the purpose, the behavioral caveat, and the per-check parameter routing. Nothing essential for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds cross-parameter routing logic beyond the schema: it clarifies that rank accepts either trackerId or siteId while site_audit requires siteId, a relationship the per-field schema descriptions only imply.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Sets how often a rank check or site audit runs') and enumerates the possible cadence values. Crucially it separates itself from the run_* siblings with 'Saving a cadence never starts a check', so an agent can distinguish scheduling from triggering without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete routing: pass trackerId from get_rankings or siteId for rank, siteId for site_audit, and names run_rank_check/run_site_audit as related tools. It stops short of an explicit 'use run_rank_check when you want to trigger a check now' exclusion, so it is clear context rather than full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_competitor_aliasesSet Competitor AliasesAIdempotentInspect
Replaces a competitor's other names (up to 5). An AI answer that uses its name or any alias counts as naming it, in past weeks' answers too. Trims each name, drops duplicates and the competitor's own name; an empty list goes back to the name only. Related: list_competitors, get_competitor_scorecard.
| Name | Required | Description | Default |
|---|---|---|---|
| aliases | Yes | The full list of other names, like ["Casita"] for "Casita Builders". Replaces the current list. | |
| competitorId | Yes | Competitor id from list_competitors. |
Output Schema
| Name | Required | Description |
|---|---|---|
| competitor | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare a non-read, idempotent, non-destructive mutation; the description goes well beyond them by disclosing that the list is fully replaced (not appended), that aliases count as naming the competitor in past weeks' answers, and that names are trimmed, deduplicated, self-name-stripped, and that an empty list resets to name-only. These side-effect details are exactly what annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, no filler. The replacement/limit fact is front-loaded, behavioral edge cases follow, and the affinity links sit at the end where they belong.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter mutation with a full output schema, the description covers the mutation semantics an agent needs. It is slightly thin on practical details such as what happens if more than 5 aliases are supplied or whether the update takes effect immediately in scoring, but nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real semantics the schema lacks: the maximum of 5 aliases, the normalization rules applied to each entry, and the empty-list reset behavior. It does not restate the schema's own example format, but the added constraints are meaningful.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('replaces') plus the exact resource ('a competitor's other names') and even the cardinality limit (up to 5). An agent can immediately distinguish this from list_competitors or get_competitor_scorecard, which are read operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'Related: list_competitors, get_competitor_scorecard' line hints at the workflow (get the id, then set aliases), but it never states when to use this versus alternatives such as track_competitor or untrack_competitor. Usage is implied rather than prescribed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_pinterest_boardSet Pinterest BoardAIdempotentInspect
Sets the default board new pins go to when a post names no boardId. boardId must be on the connected account's board list (list_pinterest_boards). Posts that name their own boardId, and pins already scheduled or published, keep their board. Call it only when the requester asks to change the default board, not to place one pin: for that, set boardId on the post. Related: list_pinterest_boards, list_channels.
| Name | Required | Description | Default |
|---|---|---|---|
| boardId | Yes | Board id from list_pinterest_boards. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| boardId | Yes | |
| boardName | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotentHint=true and destructiveHint=false, and the description adds the blast radius that matters for a mutation: posts with their own boardId and already-scheduled/published pins keep their board. What is missing is any mention of permission/auth requirements or what happens on an invalid boardId.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short, front-loaded sentences: effect, constraint, then usage rule and alternatives. Nothing is padding, and the routing guidance comes early enough to prevent a wrong call.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described; for a single-parameter mutation the description covers effect scope, prerequisite, exclusions, and sibling routing. Nothing an agent needs in order to call it correctly is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds real meaning beyond the schema: boardId must exist on the connected account's board list obtained via list_pinterest_boards, and it defines what the value means semantically (the target of an implicit default).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb (set) plus resource (default Pinterest board) and, crucially, the trigger scope: new pins with no boardId. It also distinguishes itself from sibling list_pinterest_boards and from the per-post boardId mechanism, so an agent can tell it apart without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use ('only when the requester asks to change the default board') and explicit when-not ('not to place one pin'), with the correct alternative named for the excluded case ('set boardId on the post'). Prerequisite is also stated: boardId must come from list_pinterest_boards.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_up_marketSet Up MarketAIdempotentInspect
Creates or updates an active market from a place name and language, resolving DataForSEO location and language codes. If the place or language is ambiguous, it refuses and returns candidates instead of guessing. A market already stored for that location is updated and reactivated, keeping its name, priority and time zone unless you pass them. Does not start a rank check. To rename, deactivate or delete a market, use save_strategy_item or delete_strategy_item (kind: market) with marketId. Related: list_market_locations, get_setup_status, get_brand_context, research_keywords.
| Name | Required | Description | Default |
|---|---|---|---|
| place | Yes | Place name, such as United States. | |
| language | No | Language name or code. Defaults to the only language that place offers. | |
| priority | No | Lower comes first. A new market defaults to after every existing one; an existing market keeps its priority. | |
| timezone | No | IANA timezone. A new market defaults from the country or workspace; an existing market keeps its time zone. |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | No | |
| active | No | |
| appUrl | Yes | |
| outcome | Yes | |
| marketId | No | |
| priority | No | |
| timezone | No | |
| candidates | No | |
| languageCode | No | |
| locationCode | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety/idempotency profile (readOnly=false, idempotent=true, destructive=false, openWorld=true), so the description's added value is the ambiguity-refusal behavior (returns candidates instead of guessing) and the reactivation/preservation semantics for an existing market. It stops short of stating auth requirements or rate limits, so a 4 rather than 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is front-loaded with the core action and uses short, scannable sentences for ambiguity behavior, the rank-check boundary, and the alternative routing. Slightly dense with the multi-tool 'Related' list, but every sentence carries useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with a full annotation set and an output schema, the description supplies the remaining decision-relevant context: ambiguity handling, reactivation behavior, parameter preservation, and explicit routing to alternative tools. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all four parameters and their defaults. The description reinforces the override-vs-keep behavior but adds no new syntax or format detail beyond what the schema states, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence gives a specific verb and resource ('Creates or updates an active market') plus the input basis ('from a place name and language'). It also clarifies what happens under ambiguity, so an agent can distinguish it from siblings like save_strategy_item without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when NOT to use it ('Does not start a rank check') and routes rename/deactivate/delete to save_strategy_item or delete_strategy_item with a named argument. It closes by listing related tools (list_market_locations, get_setup_status, get_brand_context, research_keywords), leaving little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_workspace_timezoneSet Workspace TimezoneAIdempotentInspect
Sets the workspace IANA timezone. Only org admins can call it. Posting slots keep their local clock times, so real posting instants move. Already-scheduled posts keep their times. Related: get_workspace, get_calendar, update_posting_slots.
| Name | Required | Description | Default |
|---|---|---|---|
| timezone | Yes | IANA time zone, such as America/New_York. Not EST or +05:00. |
Output Schema
| Name | Required | Description |
|---|---|---|
| newTimezone | Yes | |
| oldTimezone | Yes | |
| affectedSlotCount | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the generic mutation/idempotency profile; the description adds the substantive consequence that posting slots retain local clock times so real posting instants shift, while already-scheduled posts keep their times. That is exactly the side-effect disclosure an agent needs before calling this, plus an auth requirement not present in annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action and authority requirement, then the behavioral consequence, then routing. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained. With auth scope, side effects on existing schedules, and related tools all covered, an agent has everything needed to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single parameter already documents the IANA format with a counter-example ("Not EST or +05:00"). The description restates "IANA timezone" without adding format or validation detail beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Sets the workspace IANA timezone") that an agent can immediately distinguish from get_workspace, get_calendar, and update_posting_slots. The scope is precise and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete prerequisite ("Only org admins can call it") and lists related tools, which helps route an agent that actually wanted to read or adjust scheduling rather than change the timezone. It does not state an explicit when-not condition, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
show_postShow PostRead-onlyIdempotentInspect
Use this when the person wants to see or review one post themselves: "show me the pricing post", "let's review this one". In Claude and ChatGPT it draws the post's preview with Approve, Request changes and Reject when it is in review; other clients get the same text as get_post. One post per call, and only for what the person asked to see. To read posts for a task (editing, checking media, approving, going through several), use get_post, which draws nothing. Related: get_post, search_posts, review_post.
| Name | Required | Description | Default |
|---|---|---|---|
| postId | Yes | The post id from search_posts or save_post. | |
| timezone | No | IANA zone to render times in. Does not change stored data. Defaults to the workspace timezone. |
Output Schema
| Name | Required | Description |
|---|---|---|
| post | Yes |
skip_setup_stepSkip Setup StepIdempotentInspect
Skips one setup checklist row, or with skipped false brings it back, for everyone in the workspace, the same as Skip and Undo skip on Home's setup card. Use it when the user says they don't need a step. A done row stays done and is left as it is. Returns the updated rows, as get_setup_status does. step is one of: website, market, brand_voice, web_analytics, content_sources, social, buyer_questions, posting_times, connect_agent. Related: get_setup_status.
| Name | Required | Description | Default |
|---|---|---|---|
| step | Yes | One of website, market, brand_voice, web_analytics, content_sources, social, buyer_questions, posting_times, connect_agent. | |
| skipped | No | False brings a skipped row back. |
Output Schema
| Name | Required | Description |
|---|---|---|
| gaps | Yes | |
| rows | Yes | |
| ready | Yes | |
| appUrl | Yes |
submit_postSubmit Post for ReviewInspect
Sends a draft to review. If the channel is set to auto-approve and there are no claim flags, Mark approves it. The result says which happened and, for website channels, names the next CMS step (queued at a time, or a CMS draft that does not go live); an auto-approved email stays approved, since Mark doesn't send email yet, and so does a LinkedIn Article, which a person publishes on LinkedIn. Refuses a post the channel would reject at publish (no media on Instagram, TikTok, Pinterest or YouTube; more than 10 Instagram carousel items; a PDF on a channel other than LinkedIn, with other media, or over 100 MB; no Pinterest board; over the length limit; missing required meta) and a post that uses a phrase this workspace blocks (the error names each phrase and why) or still has a placeholder such as [needs source] or TODO (the error names each one), and lists what to fix. Content-check warnings never stop it; Mark stores all six results for the new revision. Does not publish immediately unless the post is already scheduled and auto-approved. If this refuses because the workspace is not set up, call get_setup_status and check its rows, including skipped ones. Related: save_post, get_post, approve_posts, get_connect_link.
| Name | Required | Description | Default |
|---|---|---|---|
| postId | Yes | The draft to submit. |
Output Schema
| Name | Required | Description |
|---|---|---|
| rev | Yes | |
| appUrl | Yes | |
| postId | Yes | |
| status | Yes |
submit_urls_to_indexnowSubmit URLs to IndexNowADestructiveInspect
Notifies IndexNow search engines of URLs on one of your sites. Verifies the key file first. This cannot be undone: the URLs are sent to IndexNow immediately. Related: list_sites.
| Name | Required | Description | Default |
|---|---|---|---|
| urls | Yes | HTTPS URLs on this site's domain. At most 100. | |
| siteId | Yes | Site id from list_sites. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | |
| message | Yes | |
| urlCount | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes beyond annotations by stating the key-file verification step and the immediacy/irreversibility of submission. Annotations already flag destructiveHint=true and non-idempotent, but the description adds concrete operational context (key verification, immediate dispatch) that the agent needs before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, no waste. Front-loads the action, then a prerequisite, then the irreversibility warning, then a related-tool pointer.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return values needn't be explained. The description covers purpose, prerequisite verification, and an irreversibility caveat. A minor gap is the lack of any usage condition vs alternatives, but for a narrowly-scoped mutation tool this is close to complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are fully documented in the schema. The description adds no parameter-level detail beyond tying siteId implicitly to list_sites.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (submits/notifies) and resource (URLs to IndexNow search engines) scoped to a site. No sibling tool does the same thing, and the IndexNow reference is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies usage ('Notifies IndexNow of URLs on one of your sites') but gives no explicit when-to-use vs alternatives. The 'Related: list_sites' hint provides a prerequisite link, which helps select the right siteId, but there's no exclusion or condition guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
suggest_brand_rulesSuggest Brand RulesARead-onlyIdempotentInspect
Lists brand rules suggested from drafting feedback (report_feedback): asks people made while drafting that may apply to everything, with the same ask from several reports listed once. This tool saves nothing. Each suggestion has ask, category, kind (exclusion: a phrase Mark could block or warn on; voice: a voice do or dont line), scopes (tenant_wide, unsure), count (reports that raised it), feedbackIds, and the newest report's channel, createdAt and before, after and userQuote excerpts. Asks scoped this_piece are never listed, and neither are asks from a report that already has a linked exclusion. Unsure asks come first, then higher count, then newest; at most 25, read from the newest 200 reports. Show each suggestion to the person and ask before saving it. On a yes, save an exclusion with save_content_exclusion (pass one of its feedbackIds as feedbackId), or a voice line with update_brand_profile (section voice, the full merged list, without confirm; the person confirms the section on the Brand page at appUrl). On a no, save nothing. A declined suggestion, or one saved as a voice line, can be listed again. state: ready, or none when nothing is waiting. Returns appUrl, the Brand page. Related: report_feedback, save_content_exclusion, update_brand_profile, get_brand_context.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| state | Yes | |
| appUrl | Yes | |
| suggestions | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations confirm read-only/idempotent/non-destructive, and the description adds substantial context beyond them: what is filtered out (this_piece-scoped asks, asks from reports with a linked exclusion), ordering, the cap of 25, and that it reads the newest 200 reports.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded and the sentences are information-dense with little waste, but the single block is long and packed with filtering, ordering, and workflow detail that could be more structured. Still, nearly every clause carries operational weight.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, yet the description still orients the agent (state values ready/none, appUrl return, field meanings) and fully covers the workflow a caller must execute. Nothing needed to invoke and act on this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero input parameters, so per the baseline this is a 4. The description adds no parameter detail because none exists, and correctly focuses on output/behavior instead.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: it lists brand rules suggested from drafting feedback (report_feedback). It clearly distinguishes itself from siblings report_feedback (source data), save_content_exclusion, and update_brand_profile (the save paths), and even clarifies 'This tool saves nothing.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly describes the downstream workflow: show each suggestion to the person, ask before saving, then use save_content_exclusion or update_brand_profile on a yes and save nothing on a no. It names alternatives and the exact condition for each.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
suggest_buyer_questionsSuggest Buyer QuestionsARead-onlyIdempotentInspect
Suggests up to 10 buyer questions to start tracking in AI answers, the same list the empty AI answers tab shows: up to 3 People Also Ask and Search Console questions the workspace already has, then questions written by one AI model call from the Brand page (positioning, products, personas, pillars) and tracked competitors. Each has a source: brand, competitor (with the competitor's name), people_also_ask or search_console. None repeats a question on the list, active or retired. Nothing is saved: add the ones you pick with save_strategy_item (kind buyer_question, fields.question). Each call writes a new list. state: ready; failed (the model call failed, rows from search still listed); intelligence_off (AI answer checks are off, so no model call, rows from search still listed); no_context (nothing to suggest from). Limited to 10 calls a minute per workspace when rate limiting is configured. Related: save_strategy_item, get_ai_visibility, run_answer_engine_check, track_competitor.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| state | Yes | |
| appUrl | Yes | |
| suggestions | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses that nothing is persisted, that each call regenerates the list, the rate limit (10 calls/min per workspace), dedup against active and retired questions, and enumerates the state values (ready, failed, intelligence_off, no_context) with their meanings. Annotations only cover safety; the description carries the operational detail.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, and most clauses carry real information. However it is a single dense paragraph mixing purpose, sources, dedup rules, state enum, rate limit and related tools, which hurts scanability and readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though an output schema exists and would carry return values, the description proactively explains the state enum and source values. For a zero-parameter, read-only suggestion tool, nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4 and there is no parameter semantics to add. The description correctly signals this is a no-argument call by never introducing inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (suggests buyer questions to track in AI answers) and pins down scope ('up to 10', 'the same list the empty AI answers tab shows'). An agent can distinguish this from get_buyer_question_answers or save_strategy_item without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context (starting a buyer-question list, mirroring the empty AI answers tab) and routes the agent to the right follow-up tool: 'add the ones you pick with save_strategy_item (kind buyer_question, fields.question)'. It also lists related tools, though it never states an explicit when-not-to-use condition.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sync_connectionsSync ConnectionsAInspect
Refreshes integration health. Pass connectionId (the provider from list_connections) to check one integration, retryJobId to retry a failed sync job, both, or neither to refresh all. It works per integration: zernio refreshes Social publishing as a whole, not one social account. Drive also starts an ingest when a folder is configured. When a website post's approval failed because another CMS page uses its slug (get_post reviewNote lists each page's CMS id), pass useCmsPageId with retryJobId to make that page the post's own and retry in one step. Only a page that is not live and no other Mark post owns is accepted; anything else is refused with the reason and nothing is written. In live publish mode the page is published; in draft mode it stays a draft. Related: list_connections, list_channels, get_post.
| Name | Required | Description | Default |
|---|---|---|---|
| retryJobId | No | Failed sync job id to retry. | |
| connectionId | No | Provider from list_connections, e.g. google_drive. | |
| useCmsPageId | No | With retryJobId, for a website post that failed on a slug collision: the CMS id of the page holding the slug to use for this post before retrying. Replaces that page's content with the post. |
Output Schema
| Name | Required | Description |
|---|---|---|
| retry | No | |
| ingest | No | |
| refresh | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses an overwrite: useCmsPageId 'Replaces that page's content with the post,' and in live mode the page is published. That is a destructive update, yet the annotations declare destructiveHint=false (which per spec means 'only additive updates'). This is an annotation contradiction, though confined to an optional mode, so it is not a flat 1.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core purpose, then proceeds mode-by-mode. Dense but every sentence carries operational information (per-integration scope, zernio vs Drive behavior, the slug scenario). Slightly long, but not padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, no return-value coverage is needed, and the annotations plus description together cover mutating/external/non-idempotent nature and the special-case workflow. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, and the description adds real value on top: it explains that passing both or neither has distinct meaning, and it spells out the exact slug-collision workflow and acceptance guardrails for useCmsPageId that the schema only hints at.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ('Refreshes integration health') and explains the retry/refresh modes with dedicated parameters. It references the related sibling tools (list_connections, list_channels, get_post), though it does not sharply separate itself from update_connection_settings or disconnect_connection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly maps each parameter combination to intent: connectionId checks one integration, retryJobId retries a failed job, both or neither refresh all. It even gives the conditional scenario for useCmsPageId. It stops short of naming when to prefer an alternative tool, so it is context-rich but not fully routable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
track_competitorTrack CompetitorAIdempotentInspect
Starts tracking a competitor's domain, so it shows on the competitor scorecard and in AI answer matches. Tracking the same domain again reuses it. Refuses your own sites, and more than 50 tracked competitors. Related: list_competitors, untrack_competitor.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | How AI answers name them. Defaults to the domain's name, title-cased. | |
| domain | Yes | The competitor's domain, like example.com. |
Output Schema
| Name | Required | Description |
|---|---|---|
| competitor | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare write (readOnlyHint=false), idempotent, non-destructive, and closed-world. The description adds value on top: the idempotent reuse behavior is spelled out in operator terms, and two external constraints (own-site refusal, 50-competitor limit) are disclosed that annotations cannot convey. It doesn't say what a refusal looks like (error vs. silent no-op), which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences with zero filler, front-loaded on what the tool does before constraints, then a short related-tools pointer. Every sentence carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the mutation semantics are covered by annotations plus the refusal rules in the text. The one small gap is the failure mode (what error or state results when your own site or the 50-cap is hit).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both parameters are documented in-schema, including the default for 'name'. The description adds no syntax, format, or naming guidance beyond what the schema already states, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('starts tracking a competitor's domain') plus the downstream effect (scorecard and AI answer matches), which goes beyond a bare restatement of the name. It explicitly names list_competitors and untrack_competitor as relatives, so an agent can place it among siblings without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete preconditions: re-tracking the same domain reuses the existing competitor, your own sites are refused, and a 50-competitor cap applies. It names related tools but does not explicitly route the agent ('call X when you want Y'), so it stops just short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unpublish_postUnpublish PostADestructiveInspect
Takes a published blog, FAQ or competitor page down from the website CMS and keeps the post in Mark. Workspace admins only. Mark unpublishes the page, reads it back, and only then records taken_down. The CMS document stays, so approving the post again updates the same page. Pass an optional reason stored on the post. Refused when the page is not live, the collection has no drafts, or the unpublish cannot be confirmed. Never returns API keys. Related: get_post, delete_post, approve_posts.
| Name | Required | Description | Default |
|---|---|---|---|
| postId | Yes | The published website post whose CMS page to take down. | |
| reason | No | Optional note stored on the post and the take-down record. |
Output Schema
| Name | Required | Description |
|---|---|---|
| state | Yes | |
| postId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructive=true, readOnly=false, idempotent=false, openWorld=true. The description adds genuinely useful non-obvious behavior beyond that: the read-back verification before recording taken_down, the fact that the CMS document survives so re-approval reuses the same page, and the three refusal conditions. Minor deduction for the boilerplate 'Never returns API keys' which is irrelevant here.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core action and packs failure semantics into a compact block; nearly every sentence earns its place. The closing 'Never returns API keys' sentence is unsupported boilerplate that dilutes an otherwise tight definition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists so return values need no explanation, and the description still covers the authorization requirement, side effects, reversibility, and refusal cases for a destructive mutation. Nothing an agent needs in order to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are already documented, and the description only restates the optional reason ('stored on the post'). No additional format, constraint, or identifier guidance is contributed beyond the schema baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('takes a published blog, FAQ or competitor page down from the website CMS') and adds the crucial qualifier that the post stays in Mark, which is what distinguishes it from delete_post and archive_post. An agent can tell what this does without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the precondition ('Workspace admins only') and the refusal conditions ('not live', 'collection has no drafts', 'unpublish cannot be confirmed'), and points at related tools. It gives clear context but never explicitly states when to prefer this over approve_posts/delete_post, leaving the routing inference to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
untrack_competitorUntrack CompetitorAIdempotentInspect
Stops tracking a competitor. Its history stays, and tracking the domain again brings it back. Related: list_competitors, track_competitor.
| Name | Required | Description | Default |
|---|---|---|---|
| competitorId | Yes | Competitor id from list_competitors. |
Output Schema
| Name | Required | Description |
|---|---|---|
| competitor | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safety profile (not read-only, destructive=false, idempotent=true); the description adds genuinely new behavioral context by stating history is retained and the action is reversible by re-tracking. It stops short of permissions or side effects on dependent data.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with zero filler, and the primary action is front-loaded before the reversibility note and cross-references.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter, idempotent mutation with annotations and an output schema already present, the description supplies the one thing an agent most needs to know – that the action is non-destructive and reversible. Only the absence of explicit usage conditions keeps it from being fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema coverage the single parameter is already fully documented ('Competitor id from list_competitors'). The description adds no syntax, format, or sourcing detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Stops tracking a competitor') and names its direct counterpart track_competitor, so an agent can distinguish it from the many other competitor tools without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'Related:' line points to list_competitors and track_competitor, which implies the reverse operation exists, but it never states when to untrack versus when to leave tracking in place, nor any precondition. Usage is inferred rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_assetUpdate AssetAIdempotentInspect
Renames an asset (and later other metadata). Drive-synced files cannot be renamed here. Related: get_asset, search_assets.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | New display name. | |
| assetId | Yes | Asset id. |
Output Schema
| Name | Required | Description |
|---|---|---|
| asset | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the mutation is idempotent and non-destructive, so the safety profile is covered. The description adds genuinely useful behavior beyond that: the drive-sync restriction that blocks renaming in this tool. It stops short of explaining what happens on failure or what the response returns.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with the action front-loaded and the constraint second; nothing is padded. The trailing 'Related:' list is terse to the point of being cryptic but costs little space.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described, and annotations cover the safety profile. The remaining gap is the forward-looking '(and later other metadata)' phrasing, which leaves an agent unsure whether other fields are currently updatable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both parameters are documented ('New display name.', 'Asset id.'), so the schema carries the load. The description only implies that 'name' is the renamed field and adds no format, length, or uniqueness semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Renames an asset') and disambiguates from siblings by naming get_asset and search_assets as related. The parenthetical '(and later other metadata)' is vague and hints at unbuilt scope, slightly muddying what the tool does today.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete negative condition: drive-synced files cannot be renamed here. It also points at related tools, though it doesn't say when to reach for get_asset or search_assets versus this one, so the routing is suggestive rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_brand_profileUpdate Brand ProfileAIdempotentInspect
Edits one section of the Brand page: section=voice (Brand and voice), visual (Visual identity: logo, colors, fonts), overlay (Entities and evidence: primary and secondary entities, experts, evidence, sameAs, Wikidata ids) or offer (Offer: what is sold today, available now, planned and not available yet, pricing, promises, claims to avoid). Pass the section's object with only the fields that change, in the shape get_brand_context returns under profile. Fields you leave out keep their saved values; lists you send replace the saved list; an empty string clears a text field. voice.voice and voice.companyFacts merge key by key, and visual.colors merges by role. Set the logo with visual.logoAssetId, an image id from search_assets or add_asset. Overlay evidence cites a source by sourceId (get_brand_context sources) or a sourceUrl. Confirmed means a person reviewed the section, and Mark's own drafting uses a section only once it is confirmed. Saving clears the section's confirmation unless you pass confirm: true. Only pass confirm: true when the person you act for has reviewed the content and explicitly asked you to confirm it. confirm: true with no fields confirms the section as it is. Otherwise send them the returned appUrl to review and confirm it there. BrandProfile voice (do, dont, principles, doctrine) is prose guidance the model reads. Claims the brand must not make go in offer.claimsToAvoid, not voice.dont. Literal phrases to block or warn on belong in save_content_exclusion. Related: get_brand_context, search_assets, add_asset, save_content_exclusion.
| Name | Required | Description | Default |
|---|---|---|---|
| offer | No | Offer fields to change: today (what you sell today, one or two sentences), availableNow (list), planned (list: planned and not available yet), pricing (text), promises (list), claimsToAvoid (list). | |
| voice | No | Brand and voice fields to change: positioning, differentiators, doctrine, voice {tone, principles, do, dont, examplePosts, hashtags, ctaDefaults}, companyFacts {name, site, hq, factoryLocations, productRangeSummary, languages}. | |
| visual | No | Visual identity fields to change: logoAssetId (image asset id; empty string removes the logo), faviconUrl, colors [{role: primary|secondary|accent|background|text, value: #RRGGBB}], headingFont, bodyFont. | |
| confirm | No | Default false. true marks the section as reviewed by a person. Only when they explicitly asked you to confirm it. | |
| overlay | No | Entities and evidence fields to change: primaryEntity, secondaryEntities (at most 3), experts [{name, title, sourceUrl?}], evidence [{label, sourceId or sourceUrl}], sameAs (profile URLs), wikidataIds (like Q42). | |
| section | Yes | Which Brand section to update. |
Output Schema
| Name | Required | Description |
|---|---|---|
| title | Yes | |
| appUrl | Yes | |
| values | Yes | |
| section | Yes | |
| confirmed | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say not-read-only, idempotent, non-destructive; the description adds real behavioral depth the annotations cannot: merge-by-key for voice.voice/companyFacts, list replacement, empty-string clearing, logo removal, and that saving clears a section's confirmation unless confirm: true.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the section map before the mutation rules, and essentially every sentence carries decision-relevant content. It is a dense, long block however; the confirmation/merge rules could be more scannable, which keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-param tool with nested objects, one enum, and an output schema already covering return values, the description supplies everything an agent needs: section semantics, update/merge rules, and the confirm workflow with its caveat.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, but the description still adds semantics the schema lacks: per-field merge vs replace vs clear behavior, colors merging by role, and where the logoAssetId and sourceId values come from. This is genuinely more than the structured fields provide.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ('Edits one section of the Brand page') and then enumerates all four sections with exactly what each covers, so an agent can route correctly without opening the schema. It also names sibling tools (get_brand_context) that supply the data shapes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'when' rules: only pass confirm: true when a person has reviewed and asked; otherwise send the returned appUrl. It also gives alternatives ('Literal phrases to block... belong in save_content_exclusion') and source lookups (search_assets/add_asset, get_brand_context).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_channel_settingsUpdate Channel SettingsADestructiveInspect
Updates a channel's settings, including approval mode. How often it posts is its posting slots: use update_posting_slots. approval=required keeps human review; approval=auto skips human review and can publish as soon as a post is submitted — only use auto when the workspace has chosen to skip review for that channel. approverRole=approver means admins only: only workspace admins can approve, request changes on, or reject that channel's posts, and only admins can change approverRole. Related: list_channels, get_channel_rules, submit_post.
| Name | Required | Description | Default |
|---|---|---|---|
| notes | No | Internal notes for this channel. | |
| active | No | false retires the channel. | |
| icpFit | No | Whether this channel fits the ICP: confirmed or uncertain. | |
| channel | Yes | Channel id, e.g. linkedin. | |
| approval | No | required keeps review; auto skips human review. | |
| approverRole | No | member: any member can decide; approver: only workspace admins. | |
| bioDestination | No | URL the profile bio link should open, e.g. https://example.com/offer. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| channel | Yes | |
| approval | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and non-idempotent/non-read-only, so the safety profile is covered structurally. The description adds real behavioral consequence: approval=auto 'can publish as soon as a post is submitted,' and approverRole=approver restricts who can approve/request-changes/reject and notes only admins can change that field. It doesn't say what happens to unmentioned settings or confirm the change's reversibility, so it stops short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core purpose, then handles the sibling routing and the two risky enums before a compact 'Related:' list. Dense em-dash chaining makes it slightly run-on, but every sentence earns its place and nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described. Given 7 parameters, 4 enums, and a destructive mutation, the description covers purpose, alternative routing, enum consequences, and authorization constraints — an agent has everything needed to invoke it correctly and safely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description meaningfully deepens the enum semantics beyond the one-line schema entries: approval=required vs auto with its publication consequence, and approverRole's admin-only authorization implications. The remaining params (notes, active, icpFit, bioDestination) are left to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Updates a channel's settings, including approval mode') and immediately scopes out what it does NOT cover by pointing posting frequency to update_posting_slots. An agent can distinguish it from siblings like update_posting_slots and list_channels without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent to update_posting_slots for cadence, gives a conditional rule for approval=auto ('only use auto when the workspace has chosen to skip review for that channel'), and lists related tools. When-to-use and when-not-to-use are both present.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_connection_settingsUpdate Connection SettingsAIdempotentInspect
Saves a Google Search Console or GA4 property, or Drive folders to watch. Pass connectionId from list_connections (search_console, ga4, google, or google_drive). Related: list_connections, sync_connections.
| Name | Required | Description | Default |
|---|---|---|---|
| product | No | Required when connectionId is google and you set a property. | |
| property | No | Search Console site URL or GA4 property id. | |
| addFolders | No | Google Drive folder links or ids to watch. | |
| connectionId | Yes | Provider from list_connections, e.g. search_console. | |
| removeFolderIds | No | Stored Drive folder ids to stop watching. |
Output Schema
| Name | Required | Description |
|---|---|---|
| added | Yes | |
| appUrl | Yes | |
| connectionId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=true, destructiveHint=false, and openWorldHint=false, so the mutation and safety profile is largely covered. The description adds that the operation attaches a property or watch folders, but says nothing about auth requirements, what happens to previously set properties/folders, or how removeFolderIds interacts with addFolders.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the purpose and followed by the key parameter hint and related tools. Efficient, though the parenthetical provider list slightly duplicates schema content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a full schema, annotations covering the safety profile, and an output schema present, the description only needs to state purpose and connectionId provenance — both of which it does. Nothing essential for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description restates the connectionId sourcing ('Pass connectionId from list_connections') and names the accepted provider values, which the schema already conveys, but adds no syntax or format detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb ('Saves') and enumerates the resource types: Search Console or GA4 property, or Drive folders to watch. It is distinguishable from siblings like list_connections and sync_connections, though 'Saves' is slightly loose for a tool named update_connection_settings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It tells the agent where connectionId comes from (list_connections) and lists the related tools, which is useful routing context. However it never states when to use this versus sync_connections or disconnect_connection, nor any preconditions or exclusions, so guidance is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_posting_slotsUpdate Posting SlotsAIdempotentInspect
Adds or removes recurring weekday+time posting slots for a channel. Weekday is 1 (Monday) through 7 (Sunday). Time is 24-hour HH:MM stored as local wall-clock in the workspace timezone; a 09:00 slot stays 09:00 across daylight saving. Related: list_channels, get_calendar, get_channel_rules.
| Name | Required | Description | Default |
|---|---|---|---|
| add | No | Slots to add. | |
| remove | No | Existing slot ids to remove, from get_calendar. | |
| channel | Yes | Channel id, e.g. linkedin. |
Output Schema
| Name | Required | Description |
|---|---|---|
| added | Yes | |
| slots | Yes | |
| appUrl | Yes | |
| errors | Yes | |
| removed | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly=false, idempotent=true, destructive=false). The description adds genuine behavioral context beyond them: slots are stored as local wall-clock in the workspace timezone and remain stable across DST, which an agent would otherwise get wrong.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded purpose, then two focused sentences on the tricky parameter semantics. The trailing 'Related:' list is slightly tacked-on but short and useful; overall well-sized with little waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present there is no need to describe returns, and annotations cover safety. The description covers purpose, both indexed params' semantics, and the timezone subtlety; only explicit usage routing is thin, which is a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline would be 3, but the schema leaves weekday's meaning undocumented (only min/max 1-7). The description supplies the 1=Monday…7=Sunday mapping and reinforces the 24-hour local-wall-clock semantics of the time value, adding real value over the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb pair (adds/removes), the exact resource (recurring weekday+time posting slots), and the target (channel). It clearly distinguishes itself from siblings like reschedule_post (single post) and update_channel_settings (channel-level config).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It lists related tools (list_channels, get_calendar, get_channel_rules) which implies where slot ids come from, but never states explicit when-to-use vs when-not conditions or which related tool to call first. Usage is inferable rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_sourceUpdate SourceAIdempotentInspect
Edits a pasted note (a source with type note) on the Claims & sources page: its title, text (body) or link. Pass id and only the fields that change. Claims quote a note's text, so a body edit is refused when a claim citing the note, active or retired, quotes text the new body no longer contains. The error names those quotes; revise those claims with save_claim first, or keep the text. Line breaks, case and curly quotes are ignored, as in save_claim. Other source types are refused: a drive_doc syncs from Google Drive and is edited there. Related: list_claims, delete_source, save_claim.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The note's id from list_claims. | |
| url | No | A new link to the original, or null to remove it. | |
| body | No | The full new text. It replaces the old text. | |
| title | No | A new title. |
Output Schema
| Name | Required | Description |
|---|---|---|
| appUrl | Yes | |
| source | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover safety/idempotency, yet the description goes well beyond them: it discloses the claim-quote validation gate on body edits, that the error names the offending quotes, that line breaks/case/curly quotes are normalized (matching save_claim), and that non-note sources are rejected. These are exactly the runtime surprises an agent needs to anticipate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose and the update contract are front-loaded, and every sentence carries information (refusal rule, error behavior, normalization, sibling cross-references). The refusal paragraph is dense, but nothing is redundant or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations, a full input schema and an output schema already present, the remaining burden is failure modes and cross-tool routing — both covered in detail (quote-conflict refusals, source-type refusals, save_claim remediation). An agent has everything needed to call it correctly or know when not to.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3, but the description adds the partial-update contract ('only the fields that change') and the semantic constraint that body replaces the old text wholesale and is validated against citing claims. That is real meaning beyond the schema, though id/url/title get no further clarification.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb (edits) and resource (a pasted note / source with type note), enumerates the editable fields (title, body, link), and explicitly scopes out the neighboring source types ('a drive_doc syncs from Google Drive and is edited there'). An agent can distinguish it from add_source, delete_source and save_claim without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit invocation rule ('Pass id and only the fields that change'), states concrete when-not conditions (body edits are refused when a citing claim's quoted text would no longer be present; other source types are refused), and routes the agent to the alternative tool ('revise those claims with save_claim first, or keep the text'). Nothing about when to pick this tool is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_website_cmsUpdate Website CMSIdempotentInspect
Changes how approved website posts reach a website CMS: pass provider (from get_website_cms) when more than one CMS is connected, then per channel (blog, faq, competitor_page, landing_page) which collection and fields they fill, mediaDestination (where new media goes), or a switch back to draft mode. Pass rediscover to read the CMS's collections again first. A mapping is checked against the discovered fields before it is saved; it cannot target the collection the API key signs in with, or a media collection. A channel publishes to one CMS. Saving reads from the customer's CMS and re-checks the connection. Admins only. Switching to live mode, the API key and the site URL are changed in the Mark app only. Related: get_website_cms, sync_connections (test, or retry a failed publish).
| Name | Required | Description | Default |
|---|---|---|---|
| mapping | No | Per channel: a full channel mapping to set, or null to stop publishing that channel. Channels not named keep their mapping. A channel publishes to one CMS. | |
| provider | No | Website CMS provider from get_website_cms, for example payload. Required when more than one website CMS is connected. | |
| rediscover | No | Read the CMS's collections and fields again first. | |
| publishMode | No | Set to draft so Mark saves drafts and the customer publishes in the CMS. Switching to live is done in the Mark app. | |
| mediaDestination | No | New media goes to: the media collection (from get_website_cms mediaCollections) Mark uploads a website post's Mark images into when it publishes, or null so Mark uploads nothing (covers and body images must then come from the CMS). Left out, unchanged. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cms | Yes | |
| appUrl | Yes |
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
- Changed
get_setup_status3 fields changed- changed
Output schema / properties / gaps / items / properties / area / enumPrevious value: -[ - "market", - "site", - "brand", - "slots", - "connections" -]New value: +[ + "website", + "market", + "brand_voice", + "web_analytics", + "content_sources", + "social", + "buyer_questions", + "posting_times", + "connect_agent" +] - added
Output schema / properties / rowsAdded value: +{ + "items": { + "additionalProperties": false, + "properties": { + "action": { + "additionalProperties": false, + "properties": { + "label": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "required": [ + "label", + "url" + ], + "type": "object" + }, + "detail": { + "type": "string" + }, + "key": { + "enum": [ + "website", + "market", + "brand_voice", + "web_analytics", + "content_sources", + "social", + "buyer_questions", + "posting_times", + "connect_agent" + ], + "type": "string" + }, + "state": { + "enum": [ + "done", + "todo", + "skipped" + ], + "type": "string" + }, + "title": { + "type": "string" + } + }, + "required": [ + "action", + "detail", + "key", + "state", + "title" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / requiredPrevious value: -[ - "appUrl", - "gaps", - "ready" -]New value: +[ + "appUrl", + "gaps", + "ready", + "rows" +]
- Added
skip_setup_step
2 tool updates
- Changed
search_posts2 fields changed- added
Output schema / properties / items / items / properties / mediaCountAdded value: +{ + "description": "Media on the post: assets, a website cover and images from the CMS. 0 means none.", + "type": "number" +} - changed
Output schema / properties / items / items / requiredPrevious value: -[ - "angleId", - "appUrl", - "buyerQuestions", - "channel", - "excerpt", - "handoff", - "id", - "pillarId", - "publishedAt", - "refresh", - "rev", - "scheduledAt", - "status", - "updatedAt" -]New value: +[ + "angleId", + "appUrl", + "buyerQuestions", + "channel", + "excerpt", + "handoff", + "mediaCount", + "id", + "pillarId", + "publishedAt", + "refresh", + "rev", + "scheduledAt", + "status", + "updatedAt" +]
- Added
show_post
3 tool updates
- Changed
save_post3 fields changed- changed
Input schema / properties / meta / descriptionPrevious value: -"Channel-specific fields from get_channel_rules. Instagram: altTexts is one alt text per slide in media order (blank entries and videos use altText or none). LinkedIn: documentTitle is the line LinkedIn shows above an attached PDF; blank uses the file name. Social posts (not YouTube): cmsImages: [{ mediaId }] attaches images already in the connected CMS (search_cms_media), after the assets on post 1; Mark fills in the channel, type and size of each, takes JPEG, PNG, WebP or GIF, and copies them to the platform at scheduling. They count toward media limits like assets. mediaOrder sets the order of the media on post 1 across assets and CMS images: a list of keys, an asset id as is or cms:<channel>:<mediaId> for a CMS image (get_post shows the channel of each; cms::<mediaId> for an image sent without one). An unknown or repeated key is dropped and media it leaves out goes last; without it, assets go first, then CMS images. altTexts follow this media order. meta without mediaOrder keeps the saved order; [] resets it. On Instagram and Pinterest, a newly attached CMS image with blank alt text takes the CMS alt (its altTexts entry on a carousel, else altText; on Pinterest only when it is the only image on the pin). Edit or clear it like any alt text. X: thread is the replies after the body, in order; threadMedia puts media on a reply: one list of asset ids per thread entry, in the same order ([[], [\"id\"]] puts id on post 3). Every threadMedia id must also be in assetIds and on one post only; post 1 gets the assetIds no reply lists. meta replaces the saved meta: when thread keeps its number of replies and threadMedia is left out, the saved threadMedia carries over; when the number changes, send threadMedia too. Each X thread post takes up to 4 images, or 1 video, or 1 GIF. Website posts (blog, faq, landing_page, competitor_page): the cover is cover: { source: \"asset\", assetId, alt } with an image id from search_assets / add_asset, or cover: { source: \"cms\", mediaId, alt? } with an image already in the connected CMS from search_cms_media (Mark fills its type and size, alt defaults to the CMS alt, and an edited alt is written back to that CMS image on approve). alt is required before submit when the CMS takes a cover. Omit cover for no cover. An image already in the CMS goes in the body as  on its own line, with url from search_cms_media called with the same channel: on a rich-text mapping it publishes by reference with no upload and shows the alt text the CMS has (get_channel_rules says which)."New value: +"Channel-specific fields from get_channel_rules. Instagram and LinkedIn: altText is the post-wide alt text and altTexts is one alt text per image in media order; a blank entry uses altText, and videos and PDFs take none. LinkedIn: documentTitle is the line LinkedIn shows above an attached PDF; blank uses the file name. Social posts (not YouTube): cmsImages: [{ mediaId, collection }] attaches images already in the connected CMS (search_cms_media), after the assets on post 1; collection is the media collection search_cms_media named (left out, the default from get_website_cms; one Mark cannot read is refused). Mark fills in the type and size of each, takes JPEG, PNG, WebP or GIF, and copies them to the platform at scheduling. They count toward media limits like assets. mediaOrder sets the order of the media on post 1 across assets and CMS images: a list of keys, an asset id as is or cms:~<collection>:<mediaId> for a CMS image (get_post shows the collection of each; an image saved before names a channel instead, cms:<channel>:<mediaId>; cms::<mediaId> for an image sent without either). An unknown or repeated key is dropped and media it leaves out goes last; without it, assets go first, then CMS images. altTexts follow this media order. meta without mediaOrder keeps the saved order; [] resets it. On Instagram, LinkedIn and Pinterest, a newly attached CMS image with blank alt text takes the CMS alt (its altTexts entry on a post with several media, else altText; on Pinterest only when it is the only image on the pin). Edit or clear it like any alt text. X: thread is the replies after the body, in order; threadMedia puts media on a reply: one list of asset ids per thread entry, in the same order ([[], [\"id\"]] puts id on post 3). Every threadMedia id must also be in assetIds and on one post only; post 1 gets the assetIds no reply lists. meta replaces the saved meta: when thread keeps its number of replies and threadMedia is left out, the saved threadMedia carries over; when the number changes, send threadMedia too. Each X thread post takes up to 4 images, or 1 video, or 1 GIF. Website posts (blog, faq, landing_page, competitor_page): the cover is cover: { source: \"asset\", assetId, alt } with an image id from search_assets / add_asset, or cover: { source: \"cms\", mediaId, collection, alt? } with an image already in the connected CMS from search_cms_media called with the same channel (collection left out: the default for that channel; a cover comes only from the collection the cover field accepts, else where new media goes, and any other is refused; Mark fills its type and size, alt defaults to the CMS alt, and an edited alt is written back to that CMS image on approve). alt is required before submit when the CMS takes a cover. Omit cover for no cover. An image already in the CMS goes in the body as  on its own line, with url from search_cms_media (any readable collection): on a rich-text mapping it publishes by reference with no upload and shows the alt text the CMS has (get_channel_rules says which)." - added
Output schema / properties / droppedMetaKeysAdded value: +{ + "description": "Top-level meta keys this channel does not take, so the save ignored them. Empty when none.", + "items": { + "type": "string" + }, + "type": "array" +} - changed
Output schema / requiredPrevious value: -[ - "appUrl", - "assetIds", - "assets", - "bodyLength", - "buyerQuestions", - "channel", - "characterLimit", - "checks", - "contentHash", - "droppedAssetIds", - "idea", - "guided", - "guideVersion", - "postId", - "rev", - "scheduledAt", - "status", - "updatedAt" -]New value: +[ + "appUrl", + "assetIds", + "assets", + "bodyLength", + "buyerQuestions", + "channel", + "characterLimit", + "checks", + "contentHash", + "droppedAssetIds", + "droppedMetaKeys", + "idea", + "guided", + "guideVersion", + "postId", + "rev", + "scheduledAt", + "status", + "updatedAt" +]
- Changed
search_cms_media4 fields changed- changed
Input schema / properties / channel / descriptionPrevious value: -"Website channel whose CMS mapping names the media collection. Leave it out for a social post: Mark uses the first website channel with a media collection."New value: +"For a website cover, its channel (blog, faq, competitor_page, landing_page): limits the search to the collections that channel's cover field accepts. Leave it out for a social post or a body image." - added
Input schema / properties / collectionAdded value: +{ + "description": "Media collection slug from get_website_cms mediaCollections. Left out, the default (where new media goes, else the first readable).", + "maxLength": 64, + "minLength": 1, + "type": "string" +} - added
Output schema / properties / collectionAdded value: +{ + "type": "string" +} - changed
Output schema / requiredPrevious value: -[ - "hasNextPage", - "items" -]New value: +[ + "collection", + "hasNextPage", + "items" +]
- Changed
update_website_cms2 fields changed- changed
Input schema / properties / mapping / additionalProperties / anyOfPrevious value: -[ - { - "properties": { - "bodyFormat": { - "description": "How the post body is stored: markdown or lexical (rich text).", - "enum": [ - "markdown", - "lexical" - ], - "type": "string" - }, - "collection": { - "description": "CMS collection slug this channel publishes into.", - "maxLength": 64, - "minLength": 1, - "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", - "type": "string" - }, - "defaults": { - "additionalProperties": {}, - "description": "Fixed values for required CMS fields Mark cannot fill, such as an author id.", - "propertyNames": { - "maxLength": 64, - "minLength": 1, - "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", - "type": "string" - }, - "type": "object" - }, - "fields": { - "description": "CMS field paths Mark fills on each document.", - "properties": { - "author": { - "description": "CMS field for the author.", - "maxLength": 64, - "minLength": 1, - "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", - "type": "string" - }, - "body": { - "description": "CMS field for the post body.", - "maxLength": 64, - "minLength": 1, - "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", - "type": "string" - }, - "categories": { - "description": "CMS field for categories.", - "maxLength": 64, - "minLength": 1, - "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", - "type": "string" - }, - "cover": { - "description": "CMS field for the cover image.", - "maxLength": 64, - "minLength": 1, - "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", - "type": "string" - }, - "description": { - "description": "CMS field for the meta description.", - "maxLength": 64, - "minLength": 1, - "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", - "type": "string" - }, - "excerpt": { - "description": "CMS field for the short listing excerpt.", - "maxLength": 64, - "minLength": 1, - "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", - "type": "string" - }, - "ogImage": { - "description": "CMS field for the social/OG image.", - "maxLength": 64, - "minLength": 1, - "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", - "type": "string" - }, - "publishedAt": { - "description": "CMS field for the published-at timestamp.", - "maxLength": 64, - "minLength": 1, - "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", - "type": "string" - }, - "seoDescription": { - "description": "CMS field for the SEO description.", - "maxLength": 64, - "minLength": 1, - "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", - "type": "string" - }, - "seoTitle": { - "description": "CMS field for the SEO title.", - "maxLength": 64, - "minLength": 1, - "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", - "type": "string" - }, - "slug": { - "description": "CMS field for the URL slug.", - "maxLength": 64, - "minLength": 1, - "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", - "type": "string" - }, - "tags": { - "description": "CMS field for tags.", - "maxLength": 64, - "minLength": 1, - "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", - "type": "string" - }, - "title": { - "description": "CMS field for the post title.", - "maxLength": 64, - "minLength": 1, - "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", - "type": "string" - } - }, - "required": [ - "title", - "slug", - "body", - "description" - ], - "type": "object" - }, - "mediaCollection": { - "description": "Media collection for the cover image. Omit so this channel sends no images.", - "maxLength": 64, - "minLength": 1, - "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", - "type": "string" - }, - "previewUrlTemplate": { - "description": "Draft preview URL pattern. Must include {slug} or {id} (the CMS document id), for example https://www.example.com/blog/preview/{id}?token=SECRET. Omit if the CMS has no draft preview URL.", - "maxLength": 2048, - "minLength": 1, - "type": "string" - }, - "provider": { - "const": "payload", - "description": "Which website CMS publishes this channel. A channel maps to one CMS.", - "type": "string" - }, - "urlPattern": { - "description": "Live page URL pattern. Must include {slug}, for example https://www.example.com/blog/{slug}.", - "maxLength": 2048, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "collection", - "fields", - "bodyFormat", - "urlPattern" - ], - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "properties": { + "bodyFormat": { + "description": "How the post body is stored: markdown or lexical (rich text).", + "enum": [ + "markdown", + "lexical" + ], + "type": "string" + }, + "collection": { + "description": "CMS collection slug this channel publishes into.", + "maxLength": 64, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + }, + "defaults": { + "additionalProperties": {}, + "description": "Fixed values for required CMS fields Mark cannot fill, such as an author id.", + "propertyNames": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", + "type": "string" + }, + "type": "object" + }, + "fields": { + "description": "CMS field paths Mark fills on each document.", + "properties": { + "author": { + "description": "CMS field for the author.", + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", + "type": "string" + }, + "body": { + "description": "CMS field for the post body.", + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", + "type": "string" + }, + "categories": { + "description": "CMS field for categories.", + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", + "type": "string" + }, + "cover": { + "description": "CMS field for the cover image.", + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", + "type": "string" + }, + "description": { + "description": "CMS field for the meta description.", + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", + "type": "string" + }, + "excerpt": { + "description": "CMS field for the short listing excerpt.", + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", + "type": "string" + }, + "ogImage": { + "description": "CMS field for the social/OG image.", + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", + "type": "string" + }, + "publishedAt": { + "description": "CMS field for the published-at timestamp.", + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", + "type": "string" + }, + "seoDescription": { + "description": "CMS field for the SEO description.", + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", + "type": "string" + }, + "seoTitle": { + "description": "CMS field for the SEO title.", + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", + "type": "string" + }, + "slug": { + "description": "CMS field for the URL slug.", + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", + "type": "string" + }, + "tags": { + "description": "CMS field for tags.", + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", + "type": "string" + }, + "title": { + "description": "CMS field for the post title.", + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$", + "type": "string" + } + }, + "required": [ + "title", + "slug", + "body", + "description" + ], + "type": "object" + }, + "mediaCollection": { + "description": "Read only. Set the connection's mediaDestination instead.", + "maxLength": 64, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + }, + "previewUrlTemplate": { + "description": "Draft preview URL pattern. Must include {slug} or {id} (the CMS document id), for example https://www.example.com/blog/preview/{id}?token=SECRET. Omit if the CMS has no draft preview URL.", + "maxLength": 2048, + "minLength": 1, + "type": "string" + }, + "provider": { + "const": "payload", + "description": "Which website CMS publishes this channel. A channel maps to one CMS.", + "type": "string" + }, + "urlPattern": { + "description": "Live page URL pattern. Must include {slug}, for example https://www.example.com/blog/{slug}.", + "maxLength": 2048, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "collection", + "fields", + "bodyFormat", + "urlPattern" + ], + "type": "object" + }, + { + "type": "null" + } +] - added
Input schema / properties / mediaDestinationAdded value: +{ + "anyOf": [ + { + "maxLength": 64, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "New media goes to: the media collection (from get_website_cms mediaCollections) Mark uploads a website post's Mark images into when it publishes, or null so Mark uploads nothing (covers and body images must then come from the CMS). Left out, unchanged." +}
1 tool update
- Added
get_plan_usage
2 tool updates
- Added
get_asset_thumbnails - Changed
record_post_published1 field changed- changed
Input schema / properties / url / descriptionPrevious value: -"The live Article's URL from LinkedIn, such as https://www.linkedin.com/pulse/..."New value: +"The live Article's post address from LinkedIn, with its post URN in it, such as https://www.linkedin.com/feed/update/urn:li:ugcPost:7518698639439978496/ (LinkedIn's … > Embed this post shows it). A /pulse/ address is refused: it has no post URN, so Mark couldn't read the Article's metrics."
1 tool update
- Added
approve_post_from_preview
11 tool updates
- Changed
approve_posts2 fields changed- changed
Output schema / properties / outcomes / items / properties / handoff / anyOfPrevious value: -[ - { - "oneOf": [ - { - "additionalProperties": false, - "properties": { - "state": { - "const": "handing_off", - "type": "string" - } - }, - "required": [ - "state" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "reason": { - "type": "string" - }, - "state": { - "const": "stuck", - "type": "string" - } - }, - "required": [ - "reason", - "state" - ], - "type": "object" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "oneOf": [ + { + "additionalProperties": false, + "properties": { + "state": { + "const": "handing_off", + "type": "string" + } + }, + "required": [ + "state" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "reason": { + "type": "string" + }, + "state": { + "const": "stuck", + "type": "string" + } + }, + "required": [ + "reason", + "state" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "reason": { + "type": "string" + }, + "state": { + "const": "publish_by_hand", + "type": "string" + } + }, + "required": [ + "reason", + "state" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "reason": { + "type": "string" + }, + "state": { + "const": "publish_now", + "type": "string" + } + }, + "required": [ + "reason", + "state" + ], + "type": "object" + } + ] + }, + { + "type": "null" + } +] - changed
Output schema / properties / outcomes / items / properties / handoff / descriptionPrevious value: -"An approved social post's handoff to the publisher: handing_off (it moves to scheduled within seconds), stuck with the reason and fix (no scheduled time, no connected account for the channel, or no progress 5 minutes after approval), or null for every other status and every website post."New value: +"An approved social post's handoff to the publisher: handing_off (it moves to scheduled within seconds), stuck with the reason and fix (no scheduled time, no connected account for the channel, or no progress 5 minutes after approval), or null for every other status and every website post. An approved LinkedIn Article has no publisher: publish_by_hand before its scheduled time and publish_now from it on, until someone records its URL with record_post_published."
- Changed
check_draft1 field changed- changed
Input schema / properties / channel / enumPrevious value: -[ - "instagram", - "facebook", - "youtube", - "pinterest", - "tiktok", - "x", - "linkedin", - "blog", - "faq", - "competitor_page", - "landing_page", - "email", - "meta_ads", - "google_ads" -]New value: +[ + "instagram", + "facebook", + "youtube", + "pinterest", + "tiktok", + "x", + "linkedin", + "linkedin_article", + "blog", + "faq", + "competitor_page", + "landing_page", + "email", + "meta_ads", + "google_ads" +]
- Changed
get_channel_rules1 field changed- changed
Input schema / properties / channel / enumPrevious value: -[ - "instagram", - "facebook", - "youtube", - "pinterest", - "tiktok", - "x", - "linkedin", - "blog", - "faq", - "competitor_page", - "landing_page", - "email" -]New value: +[ + "instagram", + "facebook", + "youtube", + "pinterest", + "tiktok", + "x", + "linkedin", + "linkedin_article", + "blog", + "faq", + "competitor_page", + "landing_page", + "email" +]
- Changed
get_weekly_brief2 fields changed- added
Output schema / properties / upcomingAdded value: +{} - changed
Output schema / requiredPrevious value: -[ - "aiAnswers", - "businessName", - "nextActions", - "search", - "settingsUrl", - "waiting", - "weekOf" -]New value: +[ + "aiAnswers", + "businessName", + "nextActions", + "search", + "settingsUrl", + "upcoming", + "waiting", + "weekOf" +]
- Added
record_post_published - Changed
report_feedback1 field changed- changed
Input schema / properties / channel / enumPrevious value: -[ - "instagram", - "facebook", - "youtube", - "pinterest", - "tiktok", - "x", - "linkedin", - "blog", - "faq", - "competitor_page", - "landing_page", - "email", - "meta_ads", - "google_ads" -]New value: +[ + "instagram", + "facebook", + "youtube", + "pinterest", + "tiktok", + "x", + "linkedin", + "linkedin_article", + "blog", + "faq", + "competitor_page", + "landing_page", + "email", + "meta_ads", + "google_ads" +]
- Changed
save_content_exclusion1 field changed- changed
Input schema / properties / channel / anyOfPrevious value: -[ - { - "enum": [ - "instagram", - "facebook", - "youtube", - "pinterest", - "tiktok", - "x", - "linkedin", - "blog", - "faq", - "competitor_page", - "landing_page", - "email", - "meta_ads", - "google_ads" - ], - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "instagram", + "facebook", + "youtube", + "pinterest", + "tiktok", + "x", + "linkedin", + "linkedin_article", + "blog", + "faq", + "competitor_page", + "landing_page", + "email", + "meta_ads", + "google_ads" + ], + "type": "string" + }, + { + "type": "null" + } +]
- Changed
save_post1 field changed- changed
Input schema / properties / channel / enumPrevious value: -[ - "instagram", - "facebook", - "youtube", - "pinterest", - "tiktok", - "x", - "linkedin", - "blog", - "faq", - "competitor_page", - "landing_page", - "email" -]New value: +[ + "instagram", + "facebook", + "youtube", + "pinterest", + "tiktok", + "x", + "linkedin", + "linkedin_article", + "blog", + "faq", + "competitor_page", + "landing_page", + "email" +]
- Changed
search_posts2 fields changed- changed
Output schema / properties / items / items / properties / handoff / anyOfPrevious value: -[ - { - "oneOf": [ - { - "additionalProperties": false, - "properties": { - "state": { - "const": "handing_off", - "type": "string" - } - }, - "required": [ - "state" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "reason": { - "type": "string" - }, - "state": { - "const": "stuck", - "type": "string" - } - }, - "required": [ - "reason", - "state" - ], - "type": "object" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "oneOf": [ + { + "additionalProperties": false, + "properties": { + "state": { + "const": "handing_off", + "type": "string" + } + }, + "required": [ + "state" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "reason": { + "type": "string" + }, + "state": { + "const": "stuck", + "type": "string" + } + }, + "required": [ + "reason", + "state" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "reason": { + "type": "string" + }, + "state": { + "const": "publish_by_hand", + "type": "string" + } + }, + "required": [ + "reason", + "state" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "reason": { + "type": "string" + }, + "state": { + "const": "publish_now", + "type": "string" + } + }, + "required": [ + "reason", + "state" + ], + "type": "object" + } + ] + }, + { + "type": "null" + } +] - changed
Output schema / properties / items / items / properties / handoff / descriptionPrevious value: -"An approved social post's handoff to the publisher: handing_off (it moves to scheduled within seconds), stuck with the reason and fix (no scheduled time, no connected account for the channel, or no progress 5 minutes after approval), or null for every other status and every website post."New value: +"An approved social post's handoff to the publisher: handing_off (it moves to scheduled within seconds), stuck with the reason and fix (no scheduled time, no connected account for the channel, or no progress 5 minutes after approval), or null for every other status and every website post. An approved LinkedIn Article has no publisher: publish_by_hand before its scheduled time and publish_now from it on, until someone records its URL with record_post_published."
- Changed
update_channel_settings1 field changed- changed
Input schema / properties / channel / enumPrevious value: -[ - "instagram", - "facebook", - "youtube", - "pinterest", - "tiktok", - "x", - "linkedin", - "blog", - "faq", - "competitor_page", - "landing_page", - "email", - "meta_ads", - "google_ads" -]New value: +[ + "instagram", + "facebook", + "youtube", + "pinterest", + "tiktok", + "x", + "linkedin", + "linkedin_article", + "blog", + "faq", + "competitor_page", + "landing_page", + "email", + "meta_ads", + "google_ads" +]
- Changed
update_posting_slots1 field changed- changed
Input schema / properties / channel / enumPrevious value: -[ - "instagram", - "facebook", - "youtube", - "pinterest", - "tiktok", - "x", - "linkedin", - "blog", - "faq", - "competitor_page", - "landing_page", - "email", - "meta_ads", - "google_ads" -]New value: +[ + "instagram", + "facebook", + "youtube", + "pinterest", + "tiktok", + "x", + "linkedin", + "linkedin_article", + "blog", + "faq", + "competitor_page", + "landing_page", + "email", + "meta_ads", + "google_ads" +]
1 tool update
- Added
get_weekly_brief
1 tool update
- Changed
check_keyword_audience5 fields changed- added
Input schema / properties / keywordAdded value: +{ + "description": "A keyword to look up without saving it.", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / languageCodeAdded value: +{ + "description": "Language code, with keyword only. Defaults to the priority market.", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / locationCodeAdded value: +{ + "description": "DataForSEO location, with keyword only. Defaults to the priority market.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" +} - changed
Input schema / properties / savedKeywordId / descriptionPrevious value: -"Saved keyword id."New value: +"Saved keyword id. Pass this or keyword, not both." - removed
Input schema / requiredRemoved value: -[ - "savedKeywordId" -]
1 tool update
- Changed
get_visitor_locations1 field changed- added
Input schema / properties / sourceAdded value: +{ + "description": "all (default): every visit. ai_referral: only visits from an AI assistant's answer.", + "enum": [ + "all", + "ai_referral" + ], + "type": "string" +}
2 tool updates
- Changed
compare_buyer_question_answers1 field changed- changed
Output schema / properties / comparison / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "afterRunId": { - "description": "Both null with fewer than two runs.", - "type": [ - "string", - "null" - ] - }, - "beforeRunId": { - "type": [ - "string", - "null" - ] - }, - "defaultReason": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "changedAt": { - "type": [ - "string", - "null" - ] - }, - "kind": { - "enum": [ - "answer_page_changed", - "no_check_since_change", - "previous_run" - ], - "type": "string" - }, - "page": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "label": { - "type": "string" - }, - "postId": { - "type": "string" - } - }, - "required": [ - "postId", - "label" - ], - "type": "object" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "kind", - "page", - "changedAt" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "Why Mark picked Before; null when you passed beforeRunId. The page and changedAt are the answer page change it keyed on." - }, - "engines": { - "items": { - "additionalProperties": false, - "properties": { - "after": { - "additionalProperties": false, - "properties": { - "answerText": { - "type": [ - "string", - "null" - ] - }, - "baseline": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "checkedAt": { - "type": "string" - }, - "state": { - "type": "string" - } - }, - "required": [ - "state", - "checkedAt" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The first answered check for this question and engine in this market (cited, mentioned or not_mentioned, and when); null when none." - }, - "checkedAt": { - "type": [ - "string", - "null" - ] - }, - "citedPages": { - "items": { - "additionalProperties": false, - "properties": { - "answerPage": { - "description": "The live URL of a post linked to this question.", - "type": "boolean" - }, - "competitor": { - "type": [ - "string", - "null" - ] - }, - "url": { - "type": "string" - }, - "yours": { - "type": "boolean" - } - }, - "required": [ - "url", - "yours", - "answerPage", - "competitor" - ], - "type": "object" - }, - "type": "array" - }, - "competitors": { - "description": "Active tracked competitors the answer named or cited.", - "items": { - "additionalProperties": false, - "properties": { - "cited": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "named": { - "type": "boolean" - } - }, - "required": [ - "name", - "named", - "cited" - ], - "type": "object" - }, - "type": "array" - }, - "failedAt": { - "type": [ - "string", - "null" - ] - }, - "failedReason": { - "description": "Why the check failed, as recorded; null unless failed.", - "type": [ - "string", - "null" - ] - }, - "platform": { - "type": "string" - }, - "state": { - "description": "cited, mentioned or not_mentioned are answers about you. no_answer, unknown, failed, not_set_up and no_data are not, and never mean not mentioned.", - "type": "string" - } - }, - "required": [ - "platform", - "state", - "failedAt", - "failedReason", - "checkedAt", - "baseline", - "answerText", - "competitors", - "citedPages" - ], - "type": "object" - }, - "before": { - "additionalProperties": false, - "properties": { - "answerText": { - "type": [ - "string", - "null" - ] - }, - "baseline": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "checkedAt": { - "type": "string" - }, - "state": { - "type": "string" - } - }, - "required": [ - "state", - "checkedAt" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The first answered check for this question and engine in this market (cited, mentioned or not_mentioned, and when); null when none." - }, - "checkedAt": { - "type": [ - "string", - "null" - ] - }, - "citedPages": { - "items": { - "additionalProperties": false, - "properties": { - "answerPage": { - "description": "The live URL of a post linked to this question.", - "type": "boolean" - }, - "competitor": { - "type": [ - "string", - "null" - ] - }, - "url": { - "type": "string" - }, - "yours": { - "type": "boolean" - } - }, - "required": [ - "url", - "yours", - "answerPage", - "competitor" - ], - "type": "object" - }, - "type": "array" - }, - "competitors": { - "description": "Active tracked competitors the answer named or cited.", - "items": { - "additionalProperties": false, - "properties": { - "cited": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "named": { - "type": "boolean" - } - }, - "required": [ - "name", - "named", - "cited" - ], - "type": "object" - }, - "type": "array" - }, - "failedAt": { - "type": [ - "string", - "null" - ] - }, - "failedReason": { - "description": "Why the check failed, as recorded; null unless failed.", - "type": [ - "string", - "null" - ] - }, - "platform": { - "type": "string" - }, - "state": { - "description": "cited, mentioned or not_mentioned are answers about you. no_answer, unknown, failed, not_set_up and no_data are not, and never mean not mentioned.", - "type": "string" - } - }, - "required": [ - "platform", - "state", - "failedAt", - "failedReason", - "checkedAt", - "baseline", - "answerText", - "competitors", - "citedPages" - ], - "type": "object" - }, - "citations": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "added": { - "description": "Pages cited in After and not in Before.", - "items": { - "additionalProperties": false, - "properties": { - "answerPage": { - "description": "The live URL of a post linked to this question.", - "type": "boolean" - }, - "competitor": { - "type": [ - "string", - "null" - ] - }, - "url": { - "type": "string" - }, - "yours": { - "type": "boolean" - } - }, - "required": [ - "url", - "yours", - "answerPage", - "competitor" - ], - "type": "object" - }, - "type": "array" - }, - "dropped": { - "description": "Pages cited in Before and not in After.", - "items": { - "additionalProperties": false, - "properties": { - "answerPage": { - "description": "The live URL of a post linked to this question.", - "type": "boolean" - }, - "competitor": { - "type": [ - "string", - "null" - ] - }, - "url": { - "type": "string" - }, - "yours": { - "type": "boolean" - } - }, - "required": [ - "url", - "yours", - "answerPage", - "competitor" - ], - "type": "object" - }, - "type": "array" - }, - "inBoth": { - "description": "Pages cited in both.", - "type": "number" - } - }, - "required": [ - "added", - "dropped", - "inBoth" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "Null when either side has no completed check for this engine." - }, - "notCompared": { - "description": "The sides with no completed check for this engine.", - "items": { - "enum": [ - "before", - "after" - ], - "type": "string" - }, - "type": "array" - }, - "platform": { - "type": "string" - } - }, - "required": [ - "platform", - "before", - "after", - "citations", - "notCompared" - ], - "type": "object" - }, - "type": "array" - }, - "market": { - "additionalProperties": false, - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "required": [ - "id", - "name" - ], - "type": "object" - }, - "question": { - "additionalProperties": false, - "properties": { - "id": { - "type": "string" - }, - "question": { - "type": "string" - }, - "topic": { - "description": "The question's topic, if set.", - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "id", - "question", - "topic" - ], - "type": "object" - }, - "runs": { - "description": "Every completed or partial check run that asked this question in this market, newest first; same-week reruns are separate entries.", - "items": { - "additionalProperties": false, - "properties": { - "finishedAt": { - "type": "string" - }, - "id": { - "type": "string" - }, - "weekKey": { - "type": "string" - }, - "weekOf": { - "type": "string" - } - }, - "required": [ - "id", - "weekKey", - "weekOf", - "finishedAt" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "question", - "market", - "runs", - "beforeRunId", - "afterRunId", - "defaultReason", - "engines" - ], - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "afterRunId": { + "description": "Both null with fewer than two runs.", + "type": [ + "string", + "null" + ] + }, + "beforeRunId": { + "type": [ + "string", + "null" + ] + }, + "defaultReason": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "changedAt": { + "type": [ + "string", + "null" + ] + }, + "kind": { + "enum": [ + "answer_page_changed", + "no_check_since_change", + "previous_run" + ], + "type": "string" + }, + "page": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "label": { + "type": "string" + }, + "postId": { + "type": "string" + } + }, + "required": [ + "postId", + "label" + ], + "type": "object" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "kind", + "page", + "changedAt" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Why Mark picked Before; null when you passed beforeRunId. The page and changedAt are the answer page change it keyed on." + }, + "engines": { + "items": { + "additionalProperties": false, + "properties": { + "after": { + "additionalProperties": false, + "properties": { + "answerText": { + "type": [ + "string", + "null" + ] + }, + "baseline": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "checkedAt": { + "type": "string" + }, + "state": { + "type": "string" + } + }, + "required": [ + "state", + "checkedAt" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The first answered check for this question and engine in this market (cited, mentioned or not_mentioned, and when); null when none." + }, + "checkedAt": { + "type": [ + "string", + "null" + ] + }, + "citedPages": { + "items": { + "additionalProperties": false, + "properties": { + "answerPage": { + "description": "The live URL of a post linked to this question.", + "type": "boolean" + }, + "competitor": { + "type": [ + "string", + "null" + ] + }, + "title": { + "description": "The page title the engine returned with the answer; null when it gave none. Pages are never fetched for it.", + "type": [ + "string", + "null" + ] + }, + "url": { + "type": "string" + }, + "yours": { + "type": "boolean" + } + }, + "required": [ + "url", + "yours", + "answerPage", + "competitor", + "title" + ], + "type": "object" + }, + "type": "array" + }, + "competitors": { + "description": "Active tracked competitors the answer named or cited.", + "items": { + "additionalProperties": false, + "properties": { + "cited": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "named": { + "type": "boolean" + } + }, + "required": [ + "name", + "named", + "cited" + ], + "type": "object" + }, + "type": "array" + }, + "failedAt": { + "type": [ + "string", + "null" + ] + }, + "failedReason": { + "description": "Why the check failed, as recorded; null unless failed.", + "type": [ + "string", + "null" + ] + }, + "platform": { + "type": "string" + }, + "state": { + "description": "cited, mentioned or not_mentioned are answers about you. no_answer, unknown, failed, not_set_up and no_data are not, and never mean not mentioned.", + "type": "string" + }, + "youNamed": { + "description": "Whether the answer names your current business name or an alias, the rule the app highlights with; null with no answer text or no business name. state uses the name at check time, so the two can differ after a rename.", + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "platform", + "state", + "failedAt", + "failedReason", + "checkedAt", + "baseline", + "answerText", + "youNamed", + "competitors", + "citedPages" + ], + "type": "object" + }, + "before": { + "additionalProperties": false, + "properties": { + "answerText": { + "type": [ + "string", + "null" + ] + }, + "baseline": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "checkedAt": { + "type": "string" + }, + "state": { + "type": "string" + } + }, + "required": [ + "state", + "checkedAt" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The first answered check for this question and engine in this market (cited, mentioned or not_mentioned, and when); null when none." + }, + "checkedAt": { + "type": [ + "string", + "null" + ] + }, + "citedPages": { + "items": { + "additionalProperties": false, + "properties": { + "answerPage": { + "description": "The live URL of a post linked to this question.", + "type": "boolean" + }, + "competitor": { + "type": [ + "string", + "null" + ] + }, + "title": { + "description": "The page title the engine returned with the answer; null when it gave none. Pages are never fetched for it.", + "type": [ + "string", + "null" + ] + }, + "url": { + "type": "string" + }, + "yours": { + "type": "boolean" + } + }, + "required": [ + "url", + "yours", + "answerPage", + "competitor", + "title" + ], + "type": "object" + }, + "type": "array" + }, + "competitors": { + "description": "Active tracked competitors the answer named or cited.", + "items": { + "additionalProperties": false, + "properties": { + "cited": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "named": { + "type": "boolean" + } + }, + "required": [ + "name", + "named", + "cited" + ], + "type": "object" + }, + "type": "array" + }, + "failedAt": { + "type": [ + "string", + "null" + ] + }, + "failedReason": { + "description": "Why the check failed, as recorded; null unless failed.", + "type": [ + "string", + "null" + ] + }, + "platform": { + "type": "string" + }, + "state": { + "description": "cited, mentioned or not_mentioned are answers about you. no_answer, unknown, failed, not_set_up and no_data are not, and never mean not mentioned.", + "type": "string" + }, + "youNamed": { + "description": "Whether the answer names your current business name or an alias, the rule the app highlights with; null with no answer text or no business name. state uses the name at check time, so the two can differ after a rename.", + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "platform", + "state", + "failedAt", + "failedReason", + "checkedAt", + "baseline", + "answerText", + "youNamed", + "competitors", + "citedPages" + ], + "type": "object" + }, + "citations": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "added": { + "description": "Pages cited in After and not in Before.", + "items": { + "additionalProperties": false, + "properties": { + "answerPage": { + "description": "The live URL of a post linked to this question.", + "type": "boolean" + }, + "competitor": { + "type": [ + "string", + "null" + ] + }, + "title": { + "description": "The page title the engine returned with the answer; null when it gave none. Pages are never fetched for it.", + "type": [ + "string", + "null" + ] + }, + "url": { + "type": "string" + }, + "yours": { + "type": "boolean" + } + }, + "required": [ + "url", + "yours", + "answerPage", + "competitor", + "title" + ], + "type": "object" + }, + "type": "array" + }, + "dropped": { + "description": "Pages cited in Before and not in After.", + "items": { + "additionalProperties": false, + "properties": { + "answerPage": { + "description": "The live URL of a post linked to this question.", + "type": "boolean" + }, + "competitor": { + "type": [ + "string", + "null" + ] + }, + "title": { + "description": "The page title the engine returned with the answer; null when it gave none. Pages are never fetched for it.", + "type": [ + "string", + "null" + ] + }, + "url": { + "type": "string" + }, + "yours": { + "type": "boolean" + } + }, + "required": [ + "url", + "yours", + "answerPage", + "competitor", + "title" + ], + "type": "object" + }, + "type": "array" + }, + "inBoth": { + "description": "Pages cited in both.", + "type": "number" + } + }, + "required": [ + "added", + "dropped", + "inBoth" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Null when either side has no completed check for this engine." + }, + "notCompared": { + "description": "The sides with no completed check for this engine.", + "items": { + "enum": [ + "before", + "after" + ], + "type": "string" + }, + "type": "array" + }, + "platform": { + "type": "string" + } + }, + "required": [ + "platform", + "before", + "after", + "citations", + "notCompared" + ], + "type": "object" + }, + "type": "array" + }, + "market": { + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ], + "type": "object" + }, + "question": { + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "question": { + "type": "string" + }, + "topic": { + "description": "The question's topic, if set.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "question", + "topic" + ], + "type": "object" + }, + "runs": { + "description": "Every completed or partial check run that asked this question in this market, newest first; same-week reruns are separate entries.", + "items": { + "additionalProperties": false, + "properties": { + "finishedAt": { + "type": "string" + }, + "id": { + "type": "string" + }, + "weekKey": { + "type": "string" + }, + "weekOf": { + "type": "string" + } + }, + "required": [ + "id", + "weekKey", + "weekOf", + "finishedAt" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "question", + "market", + "runs", + "beforeRunId", + "afterRunId", + "defaultReason", + "engines" + ], + "type": "object" + }, + { + "type": "null" + } +]
- Changed
get_buyer_question_answers1 field changed- changed
Output schema / properties / answers / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "answerPages": { - "description": "Website posts linked to this question with save_post buyerQuestionIds; archived posts excluded.", - "items": { - "additionalProperties": false, - "properties": { - "citedBy": { - "description": "Engines whose completed check this week cited the page.", - "items": { - "type": "string" - }, - "type": "array" - }, - "label": { - "description": "The post's title, else its first line.", - "type": "string" - }, - "live": { - "description": "Published with a live URL. Only a live page can be cited.", - "type": "boolean" - }, - "notCitedBy": { - "description": "Engines whose completed check this week did not cite it. An engine with no completed check is in neither list.", - "items": { - "type": "string" - }, - "type": "array" - }, - "postId": { - "type": "string" - }, - "status": { - "type": "string" - }, - "url": { - "description": "The live URL; null until published.", - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "postId", - "label", - "status", - "url", - "live", - "citedBy", - "notCitedBy" - ], - "type": "object" - }, - "type": "array" - }, - "engines": { - "items": { - "additionalProperties": false, - "properties": { - "answerText": { - "type": [ - "string", - "null" - ] - }, - "baseline": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "checkedAt": { - "type": "string" - }, - "state": { - "type": "string" - } - }, - "required": [ - "state", - "checkedAt" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The first answered check for this question and engine in this market (cited, mentioned or not_mentioned, and when); null when none." - }, - "checkedAt": { - "type": [ - "string", - "null" - ] - }, - "citedPages": { - "items": { - "additionalProperties": false, - "properties": { - "answerPage": { - "description": "The live URL of a post linked to this question.", - "type": "boolean" - }, - "competitor": { - "type": [ - "string", - "null" - ] - }, - "url": { - "type": "string" - }, - "yours": { - "type": "boolean" - } - }, - "required": [ - "url", - "yours", - "answerPage", - "competitor" - ], - "type": "object" - }, - "type": "array" - }, - "competitors": { - "description": "Active tracked competitors the answer named or cited.", - "items": { - "additionalProperties": false, - "properties": { - "cited": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "named": { - "type": "boolean" - } - }, - "required": [ - "name", - "named", - "cited" - ], - "type": "object" - }, - "type": "array" - }, - "failedAt": { - "type": [ - "string", - "null" - ] - }, - "failedReason": { - "description": "Why the check failed, as recorded; null unless failed.", - "type": [ - "string", - "null" - ] - }, - "platform": { - "type": "string" - }, - "state": { - "description": "cited, mentioned or not_mentioned are answers about you. no_answer, unknown, failed, not_set_up and no_data are not, and never mean not mentioned.", - "type": "string" - } - }, - "required": [ - "platform", - "state", - "failedAt", - "failedReason", - "checkedAt", - "baseline", - "answerText", - "competitors", - "citedPages" - ], - "type": "object" - }, - "type": "array" - }, - "market": { - "additionalProperties": false, - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "required": [ - "id", - "name" - ], - "type": "object" - }, - "question": { - "additionalProperties": false, - "properties": { - "id": { - "type": "string" - }, - "question": { - "type": "string" - }, - "topic": { - "description": "The question's topic, if set.", - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "id", - "question", - "topic" - ], - "type": "object" - }, - "weekKey": { - "description": "The ISO week shown; null when no finished check asked it yet.", - "type": [ - "string", - "null" - ] - }, - "weeks": { - "description": "Finished weekly checks that asked this question, newest first.", - "items": { - "additionalProperties": false, - "properties": { - "weekKey": { - "type": "string" - }, - "weekOf": { - "type": "string" - } - }, - "required": [ - "weekKey", - "weekOf" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "question", - "market", - "answerPages", - "weekKey", - "weeks", - "engines" - ], - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "answerPages": { + "description": "Website posts linked to this question with save_post buyerQuestionIds; archived posts excluded.", + "items": { + "additionalProperties": false, + "properties": { + "citedBy": { + "description": "Engines whose completed check this week cited the page.", + "items": { + "type": "string" + }, + "type": "array" + }, + "label": { + "description": "The post's title, else its first line.", + "type": "string" + }, + "live": { + "description": "Published with a live URL. Only a live page can be cited.", + "type": "boolean" + }, + "notCitedBy": { + "description": "Engines whose completed check this week did not cite it. An engine with no completed check is in neither list.", + "items": { + "type": "string" + }, + "type": "array" + }, + "postId": { + "type": "string" + }, + "status": { + "type": "string" + }, + "url": { + "description": "The live URL; null until published.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "postId", + "label", + "status", + "url", + "live", + "citedBy", + "notCitedBy" + ], + "type": "object" + }, + "type": "array" + }, + "engines": { + "items": { + "additionalProperties": false, + "properties": { + "answerText": { + "type": [ + "string", + "null" + ] + }, + "baseline": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "checkedAt": { + "type": "string" + }, + "state": { + "type": "string" + } + }, + "required": [ + "state", + "checkedAt" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The first answered check for this question and engine in this market (cited, mentioned or not_mentioned, and when); null when none." + }, + "checkedAt": { + "type": [ + "string", + "null" + ] + }, + "citedPages": { + "items": { + "additionalProperties": false, + "properties": { + "answerPage": { + "description": "The live URL of a post linked to this question.", + "type": "boolean" + }, + "competitor": { + "type": [ + "string", + "null" + ] + }, + "title": { + "description": "The page title the engine returned with the answer; null when it gave none. Pages are never fetched for it.", + "type": [ + "string", + "null" + ] + }, + "url": { + "type": "string" + }, + "yours": { + "type": "boolean" + } + }, + "required": [ + "url", + "yours", + "answerPage", + "competitor", + "title" + ], + "type": "object" + }, + "type": "array" + }, + "competitors": { + "description": "Active tracked competitors the answer named or cited.", + "items": { + "additionalProperties": false, + "properties": { + "cited": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "named": { + "type": "boolean" + } + }, + "required": [ + "name", + "named", + "cited" + ], + "type": "object" + }, + "type": "array" + }, + "failedAt": { + "type": [ + "string", + "null" + ] + }, + "failedReason": { + "description": "Why the check failed, as recorded; null unless failed.", + "type": [ + "string", + "null" + ] + }, + "platform": { + "type": "string" + }, + "state": { + "description": "cited, mentioned or not_mentioned are answers about you. no_answer, unknown, failed, not_set_up and no_data are not, and never mean not mentioned.", + "type": "string" + }, + "youNamed": { + "description": "Whether the answer names your current business name or an alias, the rule the app highlights with; null with no answer text or no business name. state uses the name at check time, so the two can differ after a rename.", + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "platform", + "state", + "failedAt", + "failedReason", + "checkedAt", + "baseline", + "answerText", + "youNamed", + "competitors", + "citedPages" + ], + "type": "object" + }, + "type": "array" + }, + "market": { + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ], + "type": "object" + }, + "question": { + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "question": { + "type": "string" + }, + "topic": { + "description": "The question's topic, if set.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "question", + "topic" + ], + "type": "object" + }, + "weekKey": { + "description": "The ISO week shown; null when no finished check asked it yet.", + "type": [ + "string", + "null" + ] + }, + "weeks": { + "description": "Finished weekly checks that asked this question, newest first.", + "items": { + "additionalProperties": false, + "properties": { + "weekKey": { + "type": "string" + }, + "weekOf": { + "type": "string" + } + }, + "required": [ + "weekKey", + "weekOf" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "question", + "market", + "answerPages", + "weekKey", + "weeks", + "engines" + ], + "type": "object" + }, + { + "type": "null" + } +]
4 tool updates
- Changed
check_draft2 fields changed- changed
Output schema / properties / checks / descriptionPrevious value: -"Mark's content checks on the saved content: exclusion, char_limit, required_meta, ai_fluff, unsourced_number, placeholder. On a draft, a fail stops submit_post; warn never does."New value: +"Mark's content checks on the saved content: exclusion, char_limit, required_meta, ai_fluff, unsourced_number, placeholder, and on a competitor_page also table and open_placeholder. On a draft, a fail stops submit_post; warn never does." - changed
Output schema / properties / checks / items / properties / checkId / enumPrevious value: -[ - "exclusion", - "char_limit", - "required_meta", - "ai_fluff", - "unsourced_number", - "placeholder" -]New value: +[ + "exclusion", + "char_limit", + "required_meta", + "ai_fluff", + "unsourced_number", + "placeholder", + "table", + "open_placeholder" +]
- Added
draft_competitor_page - Changed
get_competitor_scorecard2 fields changed- added
Output schema / properties / nextComparisonPageAdded value: +{} - changed
Output schema / requiredPrevious value: -[ - "appUrl", - "scorecard" -]New value: +[ + "appUrl", + "nextComparisonPage", + "scorecard" +]
- Changed
save_post2 fields changed- changed
Output schema / properties / checks / descriptionPrevious value: -"Mark's content checks on the saved content: exclusion, char_limit, required_meta, ai_fluff, unsourced_number, placeholder. On a draft, a fail stops submit_post; warn never does."New value: +"Mark's content checks on the saved content: exclusion, char_limit, required_meta, ai_fluff, unsourced_number, placeholder, and on a competitor_page also table and open_placeholder. On a draft, a fail stops submit_post; warn never does." - changed
Output schema / properties / checks / items / properties / checkId / enumPrevious value: -[ - "exclusion", - "char_limit", - "required_meta", - "ai_fluff", - "unsourced_number", - "placeholder" -]New value: +[ + "exclusion", + "char_limit", + "required_meta", + "ai_fluff", + "unsourced_number", + "placeholder", + "table", + "open_placeholder" +]
1 tool update
- Added
estimate_ai_volume
1 tool update
- Added
get_performance_overview
2 tool updates
- Added
dismiss_ai_crawler_404 - Changed
get_site_audit2 fields changed- added
Output schema / properties / aiCrawler404sAdded value: +{ + "items": {}, + "type": "array" +} - changed
Output schema / requiredPrevious value: -[ - "appUrl", - "audit" -]New value: +[ + "aiCrawler404s", + "appUrl", + "audit" +]
1 tool update
- Changed
inspect_url1 field changed- changed
Input schema / properties / url / descriptionPrevious value: -"Absolute https URL on a site this workspace owns."New value: +"Absolute https URL on the workspace's connected Search Console property. The error names the property when the page is not on it."
1 tool update
- Added
compare_buyer_question_answers
3 tool updates
- Changed
get_workspace2 fields changed- added
Output schema / properties / businessAliasesAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - changed
Output schema / requiredPrevious value: -[ - "appUrl", - "channels", - "connections", - "mcpUrl", - "members", - "name", - "needsAttention", - "orgId", - "role", - "sites", - "timezone" -]New value: +[ + "appUrl", + "businessAliases", + "channels", + "connections", + "mcpUrl", + "members", + "name", + "needsAttention", + "orgId", + "role", + "sites", + "timezone" +]
- Added
remove_competitor_lookup - Added
set_business_aliases
Publisher details
- Operator
- Life With Data · Publisher source
- Operator website
- https://lifewithdata.org · Publisher source
- Vendor relationship
- First-party
- Documentation
- https://docs.use-mark.com · Publisher source
- Trust center
- Not applicable
- Restrictions
- Not applicable
Related MCP Servers
- AlicenseNot gradedqualityBmaintenancePerplexity for social: ask what competitors are running across social and get answers grounded in real ad and creative data, not guesses.2Apache 2.0
- AlicenseCqualityBmaintenanceCompetitor Monitor AI - MCP server providing AI-powered tools and automation by MEOK AI Labs119 npmMIT
- AlicenseAqualityCmaintenanceEnables brand visibility monitoring across major AI platforms like ChatGPT, Claude, Gemini, and Perplexity. It allows users to track visibility scores, analyze competitor data, and receive actionable insights to improve AI-generated brand recommendations.164 npm1MIT

industrylens-mcpofficial
AlicenseNot gradedqualityBmaintenanceBrowse IndustryLens's published competitive-intelligence reports and head-to-head competitor comparisons from any AI agent — real, source-backed data.MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.