Skip to main content
Glama

TofuBofu AI Visibility

scan_ai_visibility

Start an AI-visibility scan of a company's website. It asks ChatGPT, Claude, Perplexity, Gemini, Google AI Mode real buying queries and records which companies they name. A free scan asks 5 queries on each engine, 25 in all. A call carrying a TofuBofu API key (Authorization: Bearer tb_live_...) re-scans that workspace's existing brand for the website, on its plan and quota.

Before calling: call research_company, walk the user through its steps, show them the pre-filled answers and the queries (for a returning brand, the ones its last scan asked, which this scan asks again), and get a yes. Ask where they sell if you do not know it: geo_scope changes every query. Omit a field you do not know rather than inventing a value.

The scan runs in the background (a few minutes); call get_visibility_report with the returned report_id. Returns report_id, report_url, assumed (answers not supplied) and query_warnings (buyer_questions that read as a topic, each with its reason; every one is still asked as sent). status "not_started" with report_id null means no scan ran: the email already has an account, or this website's free scan already ran this month. A sign-in link went to that inbox; show the note and stop.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "domain": "<domain>",
      "email": "<email>"
    },
    "name": "scan_ai_visibility"
  }
}

Input Schema

NameRequiredDescriptionDefault
emailYesThe user's work email. Required: we send the finished report there and it identifies the account. One free scan per website a month.
domainYesThe company's website or domain, e.g. "acme.com".
not_forNoWho are you NOT for? The buyer you turn away, and why. Saying it costs nothing and it is what makes the rest of the answer specific. Omit it if the user did not say.
capacityNoWho will do the fixes? Who on the user's side will make the changes. One of: solo; one_marketer (One marketer); small_team (A small team, 2 to 4); full_team (A full team, 5 or more). Omit it if the user did not say.
hired_byNoWho usually hires you? Who signs the contract, in their words. Up to three. Omit it if the user did not say.
platformNoWhat is your site built on? Decides which publishing route we can offer you. One of: wordpress (WordPress); webflow (Webflow); hubspot (HubSpot); shopify (Shopify); squarespace (Squarespace); wix (Wix); framer (Framer); custom (Something custom). Omit it if the user did not say.
sells_toNoWhat size and type of customer? SMB and enterprise are different queries with different winners. Omit it if the user did not say.
servicesNoWhich services do you want to be recommended for? Up to three services this brand wants AI engines to recommend it for, in a buyer's words. Omit it if the user did not say.
confirmedNoThe params above that the user confirmed or answered, as opposed to values you passed through from research_company unchallenged. A value not listed here is recorded as our guess, not as their answer.
geo_scopeNoWhere do you sell? Where the brand's buyers are. One of: global (Anywhere); national (Across one country); national_local (National, with a local angle); local (My own city or region). Omit it if the user did not say.
locationsNoWhich places? The country you sell across, or the cities you are bound to. Omit it if the user did not say.
tg_peopleNoWhich people? The consumer group this brand sells to, e.g. parents or students. Consumer brands only. Omit it if the user did not say.
brand_nameNoIs this you? The company name as buyers say it, read from the website and confirmed or corrected by the user. Omit it if the user did not say.
competitorsNoWho else would a buyer consider? Companies the user says a buyer would pick instead of them. We track whoever the engines name either way, so this is the user's own view rather than the whole comparison set. Omit it if the user did not say.
tg_occasionsNoWhen do they buy it? The occasion or moment this brand is bought for. Consumer brands only. Omit it if the user did not say.
buyer_audienceNoWho buys from you? Whether this brand's buyers are businesses or people, as the user said. One of: business (Businesses); consumer (Consumers). Omit it if the user did not say.
differentiatorNoWhat makes you different? One line. Leave it blank if nothing stands out. Omit it if the user did not say.
buyer_questionsNoQueries your buyers ask. Queries this company's buyers ask. Each is put to the engines as written, every scan. Omit it if the user did not say.
product_categoryNoWhat would a buyer search for to find you? What a buyer would type to find a company like yours, in their words. Omit it if the user did not say.
segment_industriesNoWhich industries do you sell into? The verticals your buyers work in. Leave it empty if you sell across all of them. Omit it if the user did not say.
segment_buyer_rolesNoWho reads the shortlist? The roles who compare vendors and hand up a recommendation. Omit it if the user did not say.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed20 schema fields changed
    • addedInput schema / properties / brand_name
      Added value: +{
      +  "default": "",
      +  "description": "Is this you? The company name as buyers say it, read from the website and confirmed or corrected by the user. Omit it if the user did not say.",
      +  "title": "Brand Name",
      +  "type": "string"
      +}
    • addedInput schema / properties / buyer_audience
      Added value: +{
      +  "default": "",
      +  "description": "Who buys from you? Whether this brand's buyers are businesses or people, as the user said. One of: business (Businesses); consumer (Consumers). Omit it if the user did not say.",
      +  "title": "Buyer Audience",
      +  "type": "string"
      +}
    • changedInput schema / properties / buyer_questions / description
      Previous value: -"Queries your buyers ask. Queries this company's buyers actually ask. They are put to the engines verbatim and tracked scan over scan, which is what makes a trend line mean anything. Shapes the queries themselves, pinned ahead of the generated ones. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."New value: +"Queries your buyers ask. Queries this company's buyers ask. Each is put to the engines as written, every scan. Omit it if the user did not say."
    • changedInput schema / properties / capacity / description
      Previous value: -"Who will do the fixes? We size and sequence the plan to match. A solo founder does not get a list built for a five-person team. One of: solo (Just me); one_marketer (One marketer); small_team (A small team, 2 to 4); full_team (A full team, 5 or more). Shapes the fix plan, which is generated in the tail after the engines answer. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."New value: +"Who will do the fixes? Who on the user's side will make the changes. One of: solo; one_marketer (One marketer); small_team (A small team, 2 to 4); full_team (A full team, 5 or more). Omit it if the user did not say."
    • changedInput schema / properties / competitors / description
      Previous value: -"Who else would a buyer consider? Companies the user says a buyer would pick instead of them. We track whoever the engines name either way, so this is the user's own view rather than the whole comparison set. Shapes the comparison set, the mismatch between who you name and who the engines do, and which of those two a given finding is about. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."New value: +"Who else would a buyer consider? Companies the user says a buyer would pick instead of them. We track whoever the engines name either way, so this is the user's own view rather than the whole comparison set. Omit it if the user did not say."
    • addedInput schema / properties / confirmed
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "The params above that the user confirmed or answered, as opposed to values you passed through from research_company unchallenged. A value not listed here is recorded as our guess, not as their answer.",
      +  "title": "Confirmed"
      +}
    • addedInput schema / properties / differentiator
      Added value: +{
      +  "default": "",
      +  "description": "What makes you different? One line. Leave it blank if nothing stands out. Omit it if the user did not say.",
      +  "title": "Differentiator",
      +  "type": "string"
      +}
    • changedInput schema / properties / email / description
      Previous value: -"The user's work email. Required: we send the finished report there and it identifies the account. One free scan per email per month."New value: +"The user's work email. Required: we send the finished report there and it identifies the account. One free scan per website a month."
    • changedInput schema / properties / geo_scope / description
      Previous value: -"Where do you sell? Getting this wrong skews the whole report: a national firm scored on one city's queries looks invisible, and a local one scored nationally looks unwinnable. One of: global (Anywhere); national (Across one country); national_local (National, with a local angle); local (My own city or region). Shapes every buying query. This is the single highest-leverage answer here. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."New value: +"Where do you sell? Where the brand's buyers are. One of: global (Anywhere); national (Across one country); national_local (National, with a local angle); local (My own city or region). Omit it if the user did not say."
    • addedInput schema / properties / hired_by
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Who usually hires you? Who signs the contract, in their words. Up to three. Omit it if the user did not say.",
      +  "title": "Hired By"
      +}
    • changedInput schema / properties / locations / description
      Previous value: -"Which places? The country you sell across, or the cities you are bound to. Shapes which geography goes into a localized buying query. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."New value: +"Which places? The country you sell across, or the cities you are bound to. Omit it if the user did not say."
    • addedInput schema / properties / not_for
      Added value: +{
      +  "default": "",
      +  "description": "Who are you NOT for? The buyer you turn away, and why. Saying it costs nothing and it is what makes the rest of the answer specific. Omit it if the user did not say.",
      +  "title": "Not For",
      +  "type": "string"
      +}
    • addedInput schema / properties / platform
      Added value: +{
      +  "default": "",
      +  "description": "What is your site built on? Decides which publishing route we can offer you. One of: wordpress (WordPress); webflow (Webflow); hubspot (HubSpot); shopify (Shopify); squarespace (Squarespace); wix (Wix); framer (Framer); custom (Something custom). Omit it if the user did not say.",
      +  "title": "Platform",
      +  "type": "string"
      +}
    • addedInput schema / properties / product_category
      Added value: +{
      +  "default": "",
      +  "description": "What would a buyer search for to find you? What a buyer would type to find a company like yours, in their words. Omit it if the user did not say.",
      +  "title": "Product Category",
      +  "type": "string"
      +}
    • addedInput schema / properties / segment_buyer_roles
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Who reads the shortlist? The roles who compare vendors and hand up a recommendation. Omit it if the user did not say.",
      +  "title": "Segment Buyer Roles"
      +}
    • addedInput schema / properties / segment_industries
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Which industries do you sell into? The verticals your buyers work in. Leave it empty if you sell across all of them. Omit it if the user did not say.",
      +  "title": "Segment Industries"
      +}
    • changedInput schema / properties / sells_to / description
      Previous value: -"What size and type of customer? SMB and enterprise are different queries with different winners. Shapes the same. 'Best sales engagement platform for SMB teams' is not the same query as 'for enterprise revenue orgs'. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."New value: +"What size and type of customer? SMB and enterprise are different queries with different winners. Omit it if the user did not say."
    • addedInput schema / properties / services
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Which services do you want to be recommended for? Up to three services this brand wants AI engines to recommend it for, in a buyer's words. Omit it if the user did not say.",
      +  "title": "Services"
      +}
    • addedInput schema / properties / tg_occasions
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "When do they buy it? The occasion or moment this brand is bought for. Consumer brands only. Omit it if the user did not say.",
      +  "title": "Tg Occasions"
      +}
    • addedInput schema / properties / tg_people
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Which people? The consumer group this brand sells to, e.g. parents or students. Consumer brands only. Omit it if the user did not say.",
      +  "title": "Tg People"
      +}
  2. Changed1 schema field changed
    • changedInput schema / properties / competitors / description
      Previous value: -"Who would a buyer otherwise pick? Companies the user says a buyer would pick instead of them. We track whoever the engines name either way, so this is the user's own view rather than the whole comparison set. Shapes the comparison set, the mismatch between who you name and who the engines do, and which of those two a given finding is about. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."New value: +"Who else would a buyer consider? Companies the user says a buyer would pick instead of them. We track whoever the engines name either way, so this is the user's own view rather than the whole comparison set. Shapes the comparison set, the mismatch between who you name and who the engines do, and which of those two a given finding is about. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."
  3. Changed4 schema fields changed
    • changedInput schema / properties / buyer_questions / description
      Previous value: -"Questions your buyers ask. Questions this company's buyers actually ask. They are put to the engines verbatim and tracked scan over scan, which is what makes a trend line mean anything. Shapes the questions themselves, pinned ahead of the generated ones. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."New value: +"Queries your buyers ask. Queries this company's buyers actually ask. They are put to the engines verbatim and tracked scan over scan, which is what makes a trend line mean anything. Shapes the queries themselves, pinned ahead of the generated ones. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."
    • changedInput schema / properties / geo_scope / description
      Previous value: -"Where do you sell? Getting this wrong skews the whole report: a national firm scored on one city's questions looks invisible, and a local one scored nationally looks unwinnable. One of: global (Anywhere); national (Across one country); national_local (National, with a local angle); local (My own city or region). Shapes every buying question. This is the single highest-leverage answer here. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."New value: +"Where do you sell? Getting this wrong skews the whole report: a national firm scored on one city's queries looks invisible, and a local one scored nationally looks unwinnable. One of: global (Anywhere); national (Across one country); national_local (National, with a local angle); local (My own city or region). Shapes every buying query. This is the single highest-leverage answer here. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."
    • changedInput schema / properties / locations / description
      Previous value: -"Which places? The country you sell across, or the cities you are bound to. Shapes which geography goes into a localized buying question. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."New value: +"Which places? The country you sell across, or the cities you are bound to. Shapes which geography goes into a localized buying query. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."
    • changedInput schema / properties / sells_to / description
      Previous value: -"What size and type of customer? SMB and enterprise are different questions with different winners. Shapes the same. 'Best sales engagement platform for SMB teams' is not the same question as 'for enterprise revenue orgs'. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."New value: +"What size and type of customer? SMB and enterprise are different queries with different winners. Shapes the same. 'Best sales engagement platform for SMB teams' is not the same query as 'for enterprise revenue orgs'. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."
  4. Changed8 schema fields changed
    • addedInput schema / properties / buyer_questions / description
      Added value: +"Questions your buyers ask. Questions this company's buyers actually ask. They are put to the engines verbatim and tracked scan over scan, which is what makes a trend line mean anything. Shapes the questions themselves, pinned ahead of the generated ones. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."
    • addedInput schema / properties / capacity / description
      Added value: +"Who will do the fixes? We size and sequence the plan to match. A solo founder does not get a list built for a five-person team. One of: solo (Just me); one_marketer (One marketer); small_team (A small team, 2 to 4); full_team (A full team, 5 or more). Shapes the fix plan, which is generated in the tail after the engines answer. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."
    • addedInput schema / properties / competitors / description
      Added value: +"Who would a buyer otherwise pick? Companies the user says a buyer would pick instead of them. We track whoever the engines name either way, so this is the user's own view rather than the whole comparison set. Shapes the comparison set, the mismatch between who you name and who the engines do, and which of those two a given finding is about. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."
    • addedInput schema / properties / domain / description
      Added value: +"The company's website or domain, e.g. \"acme.com\"."
    • addedInput schema / properties / email / description
      Added value: +"The user's work email. Required: we send the finished report there and it identifies the account. One free scan per email per month."
    • addedInput schema / properties / geo_scope / description
      Added value: +"Where do you sell? Getting this wrong skews the whole report: a national firm scored on one city's questions looks invisible, and a local one scored nationally looks unwinnable. One of: global (Anywhere); national (Across one country); national_local (National, with a local angle); local (My own city or region). Shapes every buying question. This is the single highest-leverage answer here. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."
    • addedInput schema / properties / locations / description
      Added value: +"Which places? The country you sell across, or the cities you are bound to. Shapes which geography goes into a localized buying question. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."
    • addedInput schema / properties / sells_to / description
      Added value: +"What size and type of customer? SMB and enterprise are different questions with different winners. Shapes the same. 'Best sales engagement platform for SMB teams' is not the same question as 'for enterprise revenue orgs'. Omit it rather than guessing: an omitted answer is recorded as unknown, a guessed one is indistinguishable from a real answer."
  5. Changed6 schema fields changed
    • addedInput schema / properties / buyer_questions
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Buyer Questions"
      +}
    • addedInput schema / properties / capacity
      Added value: +{
      +  "default": "",
      +  "title": "Capacity",
      +  "type": "string"
      +}
    • addedInput schema / properties / competitors
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Competitors"
      +}
    • addedInput schema / properties / geo_scope
      Added value: +{
      +  "default": "",
      +  "title": "Geo Scope",
      +  "type": "string"
      +}
    • addedInput schema / properties / locations
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Locations"
      +}
    • addedInput schema / properties / sells_to
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Sells To"
      +}
  6. First observed

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnly=false, openWorld=true, idempotent=false, destructive=false; the description goes far beyond them. It discloses quota (5 queries per engine, 25 total, one free scan per website per month), the API-key branch and its plan/quota implications, the asynchronous few-minute runtime, and the exact failure state (status "not_started" with report_id null means an account exists or this month's free scan already ran, with a sign-in link sent to the inbox).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then a clearly delimited "Before calling" block, then return values, then the failure mode. Dense but well ordered. Some sentences are long multi-clause run-ons (the free-vs-API-key sentence, the query_warnings sentence) that could be split without losing content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 21 parameters, no output schema and an asynchronous job, the description carries exactly the missing load: it enumerates the return fields (report_id, report_url, assumed, query_warnings), explains query_warnings semantics (flagged buyer_questions are still asked as sent), and documents the terminal no-scan state. An agent has everything needed to call it, wait correctly, and handle the blocked case.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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 cross-parameter behavior the schema cannot express: geo_scope "changes every query," buyer_questions are asked as written on every scan, competitors are the user's own view rather than the full comparison set, and `confirmed` determines whether a value is recorded as the user's answer or as a guess. The instruction to omit unknown fields rather than invent values is genuinely operational. It stops short of 5 only because the individual field meanings are already well documented in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Start an AI-visibility scan of a company's website") and then explains the mechanism concretely: it asks ChatGPT, Claude, Perplexity, Gemini and Google AI Mode real buying queries and records which companies they name. It also distinguishes the two modes of the same tool (anonymous free scan vs API-key re-scan of a workspace brand), so an agent knows exactly what it is triggering.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit gating: "Before calling: call research_company, walk the user through its steps... and get a yes," naming the prerequisite sibling by name. It also handles the ambiguous-input case ("Ask where they sell if you do not know it: geo_scope changes every query") and routes the agent to get_visibility_report for results, which are the two other siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources