AEO Optima Docs
Reference

MCP API Reference

Connect AI assistants like Claude, ChatGPT, Cursor, and more to AEO Optima via the Model Context Protocol (MCP).

Overview

AEO Optima exposes a Model Context Protocol (MCP) server that allows AI assistants to access your brand visibility data, capture snapshots, run analytics, and more — all without leaving your AI tool.

Server URL: https://mcp.aeo.techshu.ai/mcp

Transport: Streamable HTTP (JSON-RPC over HTTP POST)

Authentication: Bearer token or OAuth 2.1


Getting Started

There are two ways to connect your AI client to AEO Optima. The step-by-step setup for each assistant is on one page, Connect AI assistants; this page is the reference.

Option A: Manual Token

  1. Log in to the AEO Optima dashboard
  2. Go to Settings > MCP / API
  3. Click Generate Token
  4. Give it a name (e.g., "Claude Code") and select a role cap
  5. Copy the token immediately — it's shown only once
  6. Paste the token into your AI client's configuration (see Client Configuration below)

Option B: OAuth 2.1 (Click-to-connect)

Some AI clients (Claude.ai and ChatGPT) sign in with OAuth, so there is no token to copy. When you connect from your AI client:

  1. A browser window opens with the AEO Optima login page
  2. You log in (or are already logged in)
  3. A consent screen shows what the AI client is requesting
  4. You pick your organization and access level, and approve
  5. You're redirected back — connection is automatic

OAuth discovery endpoints:

  • Authorization Server Metadata: https://aeo.techshu.ai/.well-known/oauth-authorization-server
  • Protected Resource Metadata: https://mcp.aeo.techshu.ai/.well-known/oauth-protected-resource

OAuth supports PKCE (required), Dynamic Client Registration, refresh tokens, and token revocation.


Client Configuration

The setup for each assistant is on Connect AI assistants. If the assistant uses a token, start with Generate a token; Which way each assistant connects summarises every assistant.


Authentication

AEO Optima supports two authentication methods. Both produce a Bearer token that is sent with every MCP request.

Method 1: Manual Tokens

Generated from the Settings page. Format: aeo_ + 48 random hex characters (52 characters total).

  • SHA-256 hashed before storage — plaintext is never stored
  • Optional expiration dates for time-limited access
  • Can be revoked at any time from the Settings page
  • Scoped to a specific user + organization

Method 2: OAuth 2.1

OAuth tokens are generated automatically through the browser-based consent flow. Format: oat_ + 48 random hex characters.

OAuth supports:

  • Authorization Code + PKCE (S256 only) — no client secrets needed
  • Dynamic Client Registration (RFC 7591) — AI clients auto-register
  • Refresh Tokens — access tokens auto-renew without re-authorization
  • Token Revocation (RFC 7009) — revoke access or refresh tokens
  • Scopes: mcp:tools, mcp:resources, mcp:prompts

Role Hierarchy

Both token types have a role cap that limits what they can do, regardless of the user's actual role:

RoleRead DataWrite DataView CostsAdmin Tools
viewerProjects, snapshots, analytics, prompts, modelsNoNoNo
memberEverything a viewer can + usage/cost dataCapture snapshots, create/update promptsYesNo
adminEverythingEverything a member canYesNo
ownerEverythingEverythingYesNo

The effective permission is always the minimum of the token's role cap and the user's actual organization role.


Tools

The MCP server exposes the customer-facing tools below, grouped by category, plus platform-owner-only tools that never appear for customer tokens. Tools that require a feature flag (Advanced Analytics, GEO Audit, GA4, GSC, Webhooks, Connectors, Citations, Crawlers, Content, Predictive, Enterprise, Query Universe, Fusion Insights) only work for organizations whose plan includes the corresponding feature.

Every tool advertises a short human-readable title (for example "Delete an alert rule") alongside readOnlyHint and destructiveHint. Clients that honour these hints can run read-only tools without asking and ask you to confirm anything that changes or deletes data.

Pagination & structured output

Every tool carries the MCP spec annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) so clients can reason about a tool's safety before calling it. Large list tools are cursor-paginated and never silently truncate: get_snapshots, list_insights, and list_actions use a keyset cursor ordered on (created_at desc, id desc), while get_citations uses a documented offset cursor over its deterministically sorted source lists. Whenever more data exists, the response includes a nextCursor — pass it back as cursor to fetch the next page (an invalid cursor returns a clean 400 error):

{ "project_id": "...", "limit": 50, "cursor": "eyJjcmVhdGVkX2F0Ijoi..." }

get_dashboard_metrics, get_citations, get_aeo_program, and get_criteria_map also return structuredContent alongside the text block, with an outputSchema declared on the tool definition.

Projects

ToolDescriptionMin Role
list_projectsList all projects in your organizationviewer
get_projectGet detailed project info (brand, competitors, LLM configs). The project carries its budget and auto-refill amount fields (budget_allocation, budget_used_current_period, auto_refill_amount, auto_refill_max_per_day, auto_refill_used_today) with their figures only for a token whose organization role is owner or admin; for a member or viewer token each is null (the key is kept, never 0)viewer
create_projectCreate a project with platform defaults — recommended AI models pre-configured, 5 default alert rules, optional competitor seeding and category/industries business context (industries: up to 5, primary first; a single industry becomes the primary). Counts toward the projects quota. The returned project carries its budget and auto-refill amount fields (budget_allocation, budget_used_current_period, auto_refill_amount, auto_refill_max_per_day, auto_refill_used_today) as null: dollar figures are shown to organization owners and admins in the appmember
update_projectUpdate a project's core fields (name, brand, website, description) and its category/industries business context (merge-only settings write). industries replaces the whole list (up to 5, primary first). industry alone sets the PRIMARY and keeps the other industries; an empty industry removes only the primary. When both are sent, industries wins. comparison_basis sets what every coloured number is judged against (best_competitor, benchmark, target, past_best or immediate_past); an empty string clears it, which means the defaults: the best competitor for non-brand questions and the project's own past best for brand questions. Org owner/admin only. The returned project carries its budget and auto-refill amount fields as null, as PATCH /api/projects does; get_project gives an owner or admin the figuresadmin
get_brand_factsList the project's Brand Facts — verified key-value facts (founding year, HQ, pricing, certifications) ordered by category then keyviewer
get_claim_libraryThe claim library: every Brand Fact with its approval state, validity dates, evidence URL, and how many capture runs contradicted it. Only approved claims inside their dates are used in anything the platform generates — look here first when an FAQ or schema block omits a factviewer
set_brand_factsCreate or update Brand Facts in bulk (upsert on fact_key, up to 100 per call), including approval state, validity dates and evidence URL. Approving is a human decision, and changing the value of an approved claim returns it to pending. Omitted fields are left alone; an explicit null clears one. Honest per-fact results. Org owner/admin onlyadmin
add_competitorAdd a competitor to track (case-insensitive duplicate rejection, URL validation; a name the project already tracks through its client group is refused with status 409, naming that competitor). For an owner or admin, also returns the names it may also appear under in your answers of the last 30 days, as data; nothing is savedmember
remove_competitorRemove a tracked competitor from a project. A competitor that comes from the project's client group is refused with status 409: hide it for the project instead. Org owner/admin onlyadmin

Snapshots

ToolDescriptionMin Role
get_snapshotsRetrieve snapshots with filters (date, model, sentiment, brand mention). Each row carries sentimentMethod beside sentiment (who produced the verdict) and sentimentOutcome (what the judge found when it ran: accepted, nothing_to_judge, judge_unavailable, judge_not_run or no_outcome), and mentionBasis beside brand_mentioned: the rule that decided the stored verdict — detector (the name matcher), alias_own (one of your curated names), alias_exclusion (a curated name you marked as not yours), unknown (your curated names could not be read at capture), or owner_revert (a platform-wide correction had newly read the answer as naming you and its undo put it back to not naming you). It is null on answers captured before 23 September 2026, 4:30 pm IST (not recorded) unless a correction has since re-decided them; see Brand Mention. From 17 September 2026 the sentiment filter matches judge-scored answers only and therefore returns fewer rows than beforeviewer
get_snapshot_detailGet full AI response text and analysis for a snapshotviewer
capture_snapshotCapture new AI responses for a prompt across models (captures per hour are capped by plan — see Rate Limits). Each returned result carries sentimentMethod — judge, word_list or no_record — beside sentiment, so the caller that asked for the capture can see who scored itmember

Analytics

ToolDescriptionMin Role
get_dashboard_metricsKPI summary: visibility %, sentiment, rank, period-over-period changes (default 30-day window, matching the dashboard; days overridable). avgRankPosition is kept for compatibility — position within one answer is unstable across runs; topThreeRate is the replacementviewer
get_analyticsVisibility trends, LLM comparison, prompt performance. Per surface, per prompt and overall, avgRank is kept for compatibility (position within one answer is unstable across runs); topThreeRate with its rankedRuns denominator is the replacement beside it. poolEngineSplit compares engines inside each of the four question types (rate, numerator, denominator, question floor, best-to-worst spread per type); llmComparison blends the four types into one rate per engine and is kept for compatibility — rank engines on the split, never on the blendviewer
get_usage_metricsToken usage and cost breakdown by provider, model, day. Cost figures (totalCost, avgCostPerRequest, each item's cost) for an owner or admin token, or a platform admin; every cost value null for a member token — tokens and request counts for all (Decision K)member
get_sentiment_breakdownSentiment analysis by prompt and modelviewer

Advanced Analytics

get_entity_analysis, get_shopping_visibility and get_multi_language_analysis require the ai_insights_advanced feature flag; list_emerging_competitors and get_share_of_model work on any plan with MCP access.

ToolDescriptionMin Role
get_entity_analysisBrand attribute extraction from snapshots, clarity scoring (0-100), verified against brand facts. Accepts optional segment parameter.viewer
get_shopping_visibilityShopping keyword detection, position tracking, price accuracy, competitor analysis. Accepts optional segment parameter. Its tone figures moved on 17 September 2026 — sentimentBreakdown counts judge-scored answers only, the payload carries tonePopulation, and notJudgedReasons says why each un-judged row is un-judgedviewer
get_multi_language_analysisPer-language visibility, character-range detection (CJK/Arabic/Cyrillic), localized recommendations. Accepts optional segment parameter. Its tone figures moved on 17 September 2026 — judgedCount and sentimentCounts cover judge-scored answers only, and the new judgedAvgSentiment is null where the deprecated avgSentiment reads 0viewer
list_emerging_competitorsBrands extracted from snapshots that are not yet in your configured competitor list, ranked by mention count over the last N daysviewer
get_share_of_modelShare of Model: per prompt × engine inclusion frequency — the share of sampled runs your brand appears in. Each cell carries sample size n and a confidence band (under 10 = low confidence, 10-29 = below target, 30+ = ok). SERP-AI surfaces appear as their own enginesviewer

Sentiment counting (changed 4 September 2026): wherever a tool returns a sentimentBreakdown, its positive, neutral and negative counts are answers that named your brand AND carry a judged verdict — so a share computed over them is a share of answers that actually expressed something. Two residuals now travel beside them and are never folded in: notJudged (your brand was named, but no verdict was recorded) and notNamed (your brand was not in the answer, so no judgement was possible). Before this date an answer with no verdict was counted as neutral, which reported a missing judgement as a neutral opinion. The three key names and their types are unchanged, so existing integrations keep working; a neutral figure taken from before 4 September 2026 is not comparable with one taken after.

Tone is counted from judge-scored answers only (changed 17 September 2026): when the sentiment judge cannot be reached, a word list still records a verdict so the capture is not lost. A word list is a stand-in for a reading, not a reading, and until this date every tool counted the two as one thing — while the product's own Sentiment page had stopped counting them on 16 September, a day earlier. From 17 September the verdict counts on get_analytics (overallStats.sentimentBreakdown and each entry of promptPerformance) and on get_sentiment_breakdown (overall, byPrompt, byModel) cover judge-scored answers only, and each payload states the population it is over in an additive tonePopulation field, whose one value today is judge_scored. Measured over the 30 days to 16 September 2026, this moved 1,875 counted answers to 1,777 across nine projects — but read the per-project figures in the analytics guide before the average: eight of the nine move by 8% or less while one loses close to a third. Three things to know: total on get_sentiment_breakdown is now the sum of the three verdict counts (the judge-scored answers), with named carrying the figure it used to hold and notJudged carrying the difference, so a share computed from this payload divides by the population its numerators came from; get_snapshots returns sentimentMethod (judge | word_list | no_record) on every row and its sentiment filter now matches judge-scored rows only, so it returns fewer rows than before for the same value; and get_dashboard_metrics is deliberately unchanged — its sentimentScore, sentimentPolarity and positiveRate still cover every brand-mentioning answer, exactly as their field descriptions say. get_entity_analysis did not move either: its per-entity tone has always read judge-written rows only.

Which tools moved. get_analytics, get_sentiment_breakdown, get_shopping_visibility and get_multi_language_analysis all count fewer answers than they did before 17 September 2026, and each now states tonePopulation in its response. get_snapshots and capture_snapshot do not count anything, but every row they return carries sentimentMethod, and get_snapshots' sentiment filter narrowed. get_shopping_visibility also gains notJudgedReasons: its per-row sentiment: 'not_judged' token now covers four different facts — the answer named nobody, a word list wrote the verdict, nothing records how it was scored, or a judge scored it and stored no usable verdict — and those four counts sum to exactly the number of not_judged rows. An existing field's VALUE moved there, not just its shape: a row the split no longer counts now reads sentiment: "not_judged" where it previously reported the stored verdict — because a word list wrote that verdict, because nothing records how it was scored, or because the answer named nobody. Measured live on 17 September 2026, 154 of the 161 rows that move are the middle case, so most of the drop is missing provenance rather than a word list. Read notJudgedReasons for the split. The shape is additive; the values are not. get_multi_language_analysis gains judgedAvgSentiment, which is null where the deprecated avgSentiment reads 0, and whose non-zero value also moved, because the mean's population narrowed with the counts; on a −1…1 scale 0 means "perfectly balanced", so a language whose every answer a word list scored used to report a balanced tone it never measured.

What moves an answer out of the count. Two things, and only the first is what the measured figures above are made of: a verdict a word list wrote, and a row that does not record how it was scored at all. Over the 30 days those figures cover, all 98 dropped answers were word-list verdicts and none were missing-provenance rows — so the explanation above is complete for that window. It is not complete platform-wide: rows carrying no provenance key exist in older data and they stop counting too, for the same reason (silence is not a record that a judge did the reading).

Segment filtering: All analytics tools — get_dashboard_metrics, get_analytics, get_sentiment_breakdown, get_entity_analysis, get_shopping_visibility, get_multi_language_analysis, get_visibility_forecast, detect_anomalies, analyze_citation_gaps, and generate_report — accept an optional segment parameter (all, branded, non-branded, or competitor) to filter by prompt type. All REST API analytics endpoints also accept ?segment= as a query parameter.

Prompts

ToolDescriptionMin Role
list_promptsList monitoring prompts for a project (includes topic)viewer
create_promptCreate a new monitoring prompt. Optional building_block_ids links it to contexts of this project (active context ids, from list_building_blocks); a set with any other id is refused and nothing is written. Arguments outside this list are refusedmember
update_promptUpdate prompt text, type, topic, priority, active status, or question type (prompt_segment: branded / non-branded / competitor — a refiling is recorded as a reclassification of the tracked set). Optional building_block_ids replaces its context links, checked as on create_prompt; [] clears them. Arguments outside this list are refusedmember
delete_promptSoft-delete a monitoring prompt — hidden from analytics but capture history is preserved (30-day snapshot restore window). Org owner/admin onlyadmin
discover_promptsAI-assisted prompt discovery: generates up to 50 candidate prompts seeded from your brand, website, competitors, and existing prompts. Returns suggestions for review — nothing is auto-inserted. Spends LLM creditsadmin
fanout_promptGenerate a query fan-out tree for a seed query — the sub-queries an answer engine expands a question into (reformulations, comparisons, follow-ups). Spends LLM creditsadmin
get_prompt_gapsCompetitive prompt-gap analysis: prompts and topics where competitors surface but your brand does not, ranked by gap score. Pass refresh=true to recompute from snapshot data (member role, no LLM spend)viewer
classify_intentClassify search intent for prompts with the rule-based classifier and persist changed intents. No LLM spendmember
estimate_volumeEstimate and persist relative search-volume scores (1-100) for active prompts from text heuristics + database signals. No LLM spendmember

Page Analysis

ToolDescriptionMin Role
analyze_pageAnalyze a URL for AEO score (0-100) across 6 categories with improvement suggestionsadmin

Models

ToolDescriptionMin Role
list_modelsList available AI models from the dynamic registry, optionally filtered by providerviewer

Alerts

ToolDescriptionMin Role
get_alertsSurface active alerts — firings of your configured alert rules, statistical anomalies from the anomaly detector, and capture-health checks (your own thresholds, not hardcoded ones)viewer
list_alert_rulesList the configured alert rules for a project (rule type, threshold, active state, notify settings)viewer
create_alert_ruleCreate or update an alert rule (one rule per type — re-creating a type updates it). Creatable measures: nb_transactional_mention_rate, nb_informational_citation_rate, brand_transactional_negative_share, brand_informational_own_source_share. The older names (visibility_drop, sentiment_negative, brand_not_mentioned, competitor_surge, rank_drop) are accepted only to switch an EXISTING rule off — nothing evaluates them any more. cooldown_hours spaces out the announcement, not the evaluation: 0–168 (one week). Org owner/admin onlyadmin
delete_alert_ruleDelete an alert rule from a project. Org owner/admin onlyadmin
get_answer_changesProactive answer-change and competitor-displacement events — brand dropped, competitor entered, sentiment shift, claim changed, citation displaced — with derived severity and a project-wide summary. Filter by prompt_id / change_typeviewer
get_model_driftModel-drift events the sentinel detected — a provider/model whose answer distribution shifted against its own baseline (pre/post mean, delta %, engine, first seen, severity). Newest firstviewer

AI Analysis

ToolDescriptionMin Role
run_analysisRun AI-powered analysis: sentiment_drivers, content_gaps, opportunity_scoring, comprehensiveadmin
get_analysis_resultsRetrieve completed AI analysis results for a projectviewer

Criteria Map

ToolDescriptionMin Role
get_criteria_mapGet the project's selection criteria: per tracked engine, the criteria that engine says define the best offering in your category/industry — gates, segment criteria and signals, each with a layer and an evidence quote — plus the gate-clearance table against your approved facts, and answer_use: what answers to your non-brand Hybrid questions reason with, measured over real answersviewer
run_criteria_derivationRun the criteria-derivation battery: asks each tracked engine (one per provider, max 8) what defines the best offering in your category/industry, structures the answers, and upserts one criteria map per engine. Requires the project's Category + Industry settings; consumes one AI-analysis quota unit per run; refused, with nothing charged, when the platform has paused AI spending or the account cannot cover itadmin

AEO Program

ToolDescriptionMin Role
get_aeo_programGet the project's AEO Program status: six projection-ladder rungs and five parallel work tracks, every status derived from existing stored signals (intelligence scores, GEO audit, criteria maps, citation-gap placement, coverage report, citation mix) — never computed on demandviewer

Scorecard

ToolDescriptionMin Role
get_scorecardRead the project's Scorecard: the same read as the Scorecard page, so the numbers match it. Optional basis (cohort, the default, or full) and scenario (conservative, base or stretch; the default is the one chosen at the lock). With no locked baseline it says so and names the months a lock may use. The sales figures behind Business impact are returned for owners and admins only; any other token gets it marked restrictedviewer

Actions

ToolDescriptionMin Role
list_actionsList insight actions (auto-generated from AI analysis or manual)viewer
update_actionUpdate an action's status (pending, in_progress, completed, dismissed) or notesmember

Plan & Quotas

ToolDescriptionMin Role
get_plan_infoGet organization plan, feature flags, quota limits, and current usage countsviewer

GEO Audit

ToolDescriptionMin Role
run_geo_auditRun a Generative Engine Optimization audit on a URL — scores 8 categories: schema, entity clarity, content depth, answer structure, trust signals, technical SEO, freshness, AI crawler access (incl. JS-dependency)admin
run_site_geo_auditSite-level GEO audit: discovers the site's pages (sitemap → homepage links), audits up to the plan's page cap, aggregates category scores and adds site-wide checks. One quota unit per runadmin
list_geo_auditsList past GEO audit results for a projectviewer

GA4

ToolDescriptionMin Role
get_ai_trafficGet AI referral traffic data from Google Analytics 4 (sessions, users, pageviews from ChatGPT, Perplexity, Claude, Gemini)viewer
get_ga4_statusCheck GA4 connection status for a projectviewer
get_prompt_attributionPrompt-level closed-loop attribution: joins AI-referral traffic (the GA4 "AI-Assistant" channel) to the prompt(s) whose AI answer cited each page — per (prompt, engine, cited URL) rows with fractionally-attributed AI-assisted sessions / conversions / revenue. Every number is a floor. Accepts the analytics lens params (segment, intent, journey, topic, tag, group_id, orbit). Requires Fusion Insights + GA4; aiRevenue redacted for member/viewer tokensviewer

GSC

ToolDescriptionMin Role
get_search_performanceGet Google Search Console data (clicks, impressions, CTR, position) for top queriesviewer
get_gsc_statusCheck Google Search Console connection status for a projectviewer
get_search_contextMap real Search Console queries to the prompts they relate to — EXACT (the query's landing page is a page this prompt's AI answers cite) and HEURISTIC (topic-matched, with relevance 0–1 and matched terms); the two are never summed. Per-prompt query lists, best position, totals. Accepts the analytics lens params. Requires GSCviewer

Webhooks

ToolDescriptionMin Role
list_webhooksList webhook endpoints registered for the organizationadmin
get_webhook_deliveriesGet recent delivery logs for a webhook endpointadmin

Citation Intelligence

ToolDescriptionMin Role
get_citationsGet citation sources for a project with aggregated counts, category breakdowns, and per-engine mention-vs-citation splitviewer
analyze_citation_gapsIdentify sources that cite competitors but not your brand — actionable outreach targetsmember
get_domain_authorityGet domain authority scores for citation sources (frequency, recency, cross-model presence)viewer
get_contribution_gridGet the contribution grid: your citation mix mapped onto the framework's six external source families, with a presence/diversity verdict per family (absent / thin / present / concentrated)viewer

Crawler Intelligence

ToolDescriptionMin Role
get_crawler_dashboardThe robots.txt access check — which AI crawlers your robots.txt allows or blocks, when it was last checked (recentLogs[].checkedAt), and what changed since the previous nightly check (patterns: new_bot, blocked, unblocked). Not crawl traffic: for what crawlers actually fetched, use get_ai_crawl_analytics. From 23 October 2026 the check time is checkedAt (it was lastCrawledAt, which was always the check time, never a crawl) and an unblocking is unblocked (it was frequency_change)viewer
analyze_robotsAnalyze robots.txt and ai.txt for AI bot configuration with recommendationsadmin
get_ai_crawl_analyticsAI-bot crawl analytics from uploaded server access logs — per-bot hits with each bot's purpose (live_retrieval | search_crawl | training | robots_token | unknown; search_crawl is an AI search engine's own index crawler, its own class from 21 October 2026), purposeTotals kept as separate figures that are never summed, byOperator (hits per AI company, split by class), plus purposeTotals.otherKnown (purpose other_known: fetches by known crawlers that are not AI crawlers, such as OAI-AdsBot and Google-CloudVertexBot, left out of every per-bot row and AI figure), byPath (from 22 October 2026: the pages AI crawlers fetched most, up to 200, each with hits, distinct crawlers, the top crawler, the last fetch and the HTTP status counts; read over the same fetches as the AI figures, so with every page listed the pages' hits add up to totalEvents, and byPathTruncated is true when the site had more crawled pages than are listed), crawl→citation funnel with the lag's basis (lagBasisPages, citedBeforeLogsPages), daily trend. The stored kind (train/search) is the robots-guidance reading and is kept for compatibility. Pro Individual plan and aboveviewer
configure_crawl_log_sourceCreate or update the upload log source for a project (reuses the newest source of the given type). Run before uploading AI-bot access logs. Pro Individual plan and aboveadmin

Content Intelligence

ToolDescriptionMin Role
generate_faqsGenerate FAQ content from project prompts and brand facts (suitable for FAQ schema)admin
generate_schema_markupGenerate JSON-LD structured data for a URL using brand facts and page contentadmin
get_correctionsGet hallucination correction submissions (drafts, submitted, resolved)viewer
list_saved_faqsThe saved FAQs a project publishes to AI crawlers through Edge Delivery, in published order: each one's id, question and answer, whether you edited it (served as written, kept by every "Generate FAQs") and whether you removed it (not served, restorable), plus notServedReason (edge_off | faq_schema_off | null) when none is served right now. Every planviewer
update_saved_faqChange one saved FAQ's question and/or answer; it is then served exactly as written and kept by every later "Generate FAQs". Restore a removed FAQ first. Question at most 300 characters, answer at most 2,000member
remove_saved_faqStop publishing one saved FAQ. It is kept, never served and never brought back by "Generate FAQs"; restore_saved_faq puts it backmember
restore_saved_faqPut a removed FAQ back into what Edge Delivery publishes; it stays yours, kept by every later "Generate FAQs"member
submit_correctionHallucination-correction workflow: generate builds provider-specific correction-request templates from the issue context; create saves a draft correction submissionmember
generate_content_briefGEO-method Content Brief for a target page: measures the four proven citation levers (expert quotations, statistics, cited sources, dated references) and returns the below-target levers to change, ordered by evidence weight, with an honest expected-lift estimate. Deterministic — no per-generation LLM cost. Persists a draft brief. Professional+admin
get_content_briefsList persisted Content Briefs (levers, gap summary, coverage, expected lift, status draft/applied/verified, linked action id), newest firstviewer

Connectors

ToolDescriptionMin Role
list_connectorsList registered connectors (Serper, DataForSEO, Slack, Looker, Zapier, Shopify)admin
create_connectorCreate a connector for an organization. Counts toward the plan's connector limit; credentials are added in the dashboard afterwardsadmin
test_connectorTests the connection by calling the connector's service. Slack and Zapier receive a real test event; Serper, Brave Search, YouTube, Google Knowledge Graph and Stack Exchange run one search that counts against the service's API quotaadmin
sync_connectorRun a full sync for a connector; returns the sync status and records syncedadmin
delete_connectorDelete a connector and its stored credentialsadmin
manage_connectorDeprecated, not listed in tools/list (still callable) — use create_connector, test_connector, sync_connector or delete_connector. Create, test, sync, or delete a connectoradmin

Predictive & Edge

ToolDescriptionMin Role
get_visibility_forecastVisibility forecast via Holt-Winters ensemble (level + trend + weekly seasonality) with bootstrap-calibrated 95% prediction intervals. Returns winning model, cross-validated RMSE/MAE/MAPE, coverage probability, Ljung-Box residual test, and confidence quality rating. Accepts optional segment parameter.viewer
detect_anomaliesCompleteness-aware robust z-score anomaly detection (median/MAD) on visibility, sentiment, and mention-rate metrics. Skips partial-capture days (a day needs at least max(10, 80% of the full-day reference) snapshots, the reference read from the fuller capture days of the last 120 days; the result's coverage says per metric how many complete days there were and whether it was tested), excludes today, applies Benjamini-Hochberg FDR control across every tested point (all metrics pooled), marks persistent when the previous point also deviated notably. Accepts optional segment parameter.admin
get_benchmarksCompare project visibility against a measured industry benchmark (percentile rank); with none measured yet, no numbers and a plain noteviewer

Enterprise

ToolDescriptionMin Role
get_audit_logsSOC 2 compliance audit logs for an organization (user actions, data access, config changes)admin
get_revenue_attributionMulti-touch revenue attribution: first_touch, last_touch, linear, time_decay, position_basedmember

Query Universe

ToolDescriptionMin Role
list_building_blocksList building blocks for a project grouped by category (Core services, Modifiers). Optional include_proposed also returns contexts proposed from the website that nobody has accepted yet; they are left out by defaultviewer
create_building_blocksCreate building blocks in a project from a blocks array (Query Universe feature and building-block limit apply)member
update_building_blockUpdate one building block (block_id, project_id and updates are required)member
delete_building_blockDelete one building block from a project (block_id and project_id are required). Org owner/admin onlyadmin
manage_building_blocksDeprecated, not listed in tools/list (still callable) — use create_building_blocks, update_building_block or delete_building_block. Create, update, or delete building blocks; the delete action requires adminmember
compose_promptsGenerate prompt suggestions from building blocks (cap: 200). When questions per type are set, the types short of their number come firstviewer
get_coverage_reportGet or regenerate Query Universe coverage report (dimension distributions, gaps, recommendations)viewer
seed_building_blocksSeed building blocks from industry templatesadmin
get_orbit_modelGet the project's definition-orbit model: the four orbits (who-we-are, what-we-do, how-you-qualify, whom-we-serve), the block categories each maps to, per-orbit completeness, the identity record (canonical name, owner or "independent", what the brand makes), and the two registers a person keeps (inherited trust and the brand's own attributes, entered by hand)viewer
seed_orbit_blocksSeed building blocks into one definition orbit's canonical block categories — same validation and plan gates as the building-blocks APImember
backfill_promptsEnrich existing prompts with enhanced classification (intent, journey stage, freshness, risk, SDS tier)admin
analyze_company_siteDiscovery Autopilot: bounded crawl of the company's own site (up to 6 pages) plus one judge-pipeline extraction into a structured, evidence-quoted company profile for review. Consumes one AI-analysis quota unit; 5 analyses/hour per user; refused, with nothing charged, when the platform has paused AI spending or the account cannot cover itadmin

Agent-driven onboarding walkthrough: call analyze_company_site for a project, present the returned profile to the user for confirmation (items without an evidence quote are confidence low — treat them as suggestions to verify, never facts, and never write a certification the user has not explicitly confirmed), then apply the confirmed items with the write tools: create_building_blocks (blocks), set_brand_facts (certifications as gate evidence), add_competitor, and update_project (category + industry business context). Finish with compose_prompts to generate query candidates from the confirmed universe.

Reports

ToolDescriptionMin Role
generate_reportGenerate an AEO report for a project. Supports multiple formats (PDF, slide PDF, Excel, CSV) and report types (executive, standard, comprehensive, competitive, custom, per_prompt, aeo_program — the board-ready define→project→credibility program story). Returns report ID, download URL, AI brand score, and letter grade. The score and grade are null when the window has no captures (insufficient_data) or when one of the score's inputs could not be loaded (score_not_loaded: true); sections_not_loaded lists each part that could not be loaded — section keys, plus coverage, cyclePeriod and competitivePosition.admin
get_report_historyGet report generation history for a project. Returns past reports with metadata, scores, and download URLs. A failed generation's error_reason reads "This report did not generate.", and its metadata.error is no longer returned (removed 2026-09-24; GET /api/reports/history does the same).viewer
get_report_downloadGet a signed download URL for a specific report. URL expires after 1 hour.viewer
create_report_shareCreate a shareable link for a report. Supports optional password protection, expiry, and comment permissions.admin
list_report_sharesList all shared report links for a project, including view counts and status.member
revoke_report_shareRevoke (deactivate) a shared report link. The link will no longer be accessible.admin
list_scheduled_reportsList recurring scheduled reports for the organization (cadence, recipients, timezone/send hour; channel secrets redacted). Org owner/admin onlyadmin
create_scheduled_reportCreate a recurring scheduled report delivered by email at a chosen local time (types: quick, executive, standard, comprehensive, competitive, per_prompt, aeo_program). Delivery channels stay dashboard-only. Org owner/admin onlyadmin
update_scheduled_reportUpdate a scheduled report — pause/resume, recipients, cadence, timezone, send hour, or voice. Org owner/admin onlyadmin
delete_scheduled_reportDelete a recurring scheduled report so it stops being sent. Org owner/admin onlyadmin

Schedules

ToolDescriptionMin Role
list_schedulesList recurring snapshot-capture schedules for a project (name, frequency, next run, active state)viewer
create_scheduleCreate a recurring snapshot-capture schedule (daily/weekly/biweekly/monthly) across all active prompts and models. Nothing runs until the schedule's first due time; pass run_now: true to also enqueue one immediate first capture (spends credits now; default false)admin
delete_scheduleDelete a recurring snapshot-capture schedule for a projectadmin

Goals

ToolDescriptionMin Role
list_goalsList visibility goals with milestones and pace status. Filter by status or segment.viewer
create_goalCreate a goal with auto-computed milestones. Supports 7 metrics across 4 segments. Returns feasibility assessment.member
update_goalUpdate a goal's target, date, status, or notes.member

Insights

ToolDescriptionMin Role
list_insightsList intelligence insights generated by computation engines. Filter by type (11 types), severity, or status.viewer
update_insightAcknowledge, dismiss, or convert an insight to an action.member

Intelligence

ToolDescriptionMin Role
get_intelligence_scoresGet all 6 intelligence scores: BNCI, CMCS, MEI, SDI, CIPS, ETAS.member
get_intelligence_summaryGet unified intelligence summary with KPIs, timeline, recommendations, and action counts.viewer
get_fusion_insightsFuse AI visibility ↔ real traffic ↔ rank on your own page URLs. Returns a per-page fusion table + plain-language insights (cited-page→traffic, AI-vs-SEO divergence, AI-Overview share, first-party Google AI visibility from Search Console, social mention volume, …) with graceful degradation per connected source. Requires the fusion_insights feature (Professional+). Accepts optional segment.viewer
verify_actionTrigger scoped measurement for completed actions. Compares visibility before/after to measure real impact. Page-specific fusion actions also report the page's AI-referral sessions, Google position, and citation deltas.admin

Quick Audit

ToolDescriptionMin Role
quick_auditRun a 3-model brand check. The three engines are resolved from the live model registry, so the lineup follows your platform's current models rather than a fixed list. Reports whether each engine NAMES the brand in its answer, which is not whether it knows it — an engine that says it has never heard of a brand still names it — with an excerpt of each answering engine's opening lines so you can read what it said. percentage is the named rate over the engines that ANSWERED — null, never 0, when none did. Naming only — it does not score tone. An answer the engine cut off before it finished is marked cutOff: true on its model entry and counted as neither named nor not named (visibility.cutOff says how many). brand_name must be 2–80 characters: a longer name is refused as invalid arguments, where the web check instead cuts a name to 80 characters after cleaning it; a name carrying instruction-like phrasing is refused on both, and so is a name that, once cleaned, has fewer than 2 characters or no letter or digit. Each call, a cached answer included, counts toward its own hourly cap, the same size as your plan's captures-per-hour cap and separate from capture_snapshot's (see Rate Limits).member

A quick audit does not score tone (changed 17 September 2026): this tool reports whether each engine names the brand. It never ran the sentiment judge — but until this date it returned a tone regardless: sentiment carried the hardcoded string "neutral" on every answer that named the brand, identical for every brand and every answer, and the public web version of the same check scored a private seventeen-word list. An existing field's VALUE moved here, not its shape: sentiment is unchanged as a field and is now always null, with an additive sentimentBasis of not_scored on each model entry and a plain-language sentimentBasisNote on the payload. A caller that read sentiment as a verdict was reading a constant, not a measurement; for real tone use get_sentiment_breakdown or get_analytics, which are judge-scored over your tracked questions.

A quick audit reports over the engines that ANSWERED (changed 17 September 2026): visibility now carries answered and errored beside the existing mentioned and total, and the percentage is computed over answered rather than over the engines the audit tried. percentage is an existing field whose VALUE moved: it is null — never 0 — when no engine answered, with reason: "engines_unreachable" and a plain sentence in note. Before this, three refused calls were published as { mentioned: 0, total: 3, percentage: 0 } and cached for 24 hours, so a caller was told no engine mentions the brand when in fact none had been reached. A caller that branches on percentage must handle null and must not coerce it to 0: the two mean different things. total still means the engines we tried, and there is deliberately no asked field repeating it. A run in which nothing answered is not cached, so the next call retries rather than being handed the same refusal.

Caching: results are cached for 24 hours per brand. Before 17 September 2026 this tool's cache write violated a NOT NULL constraint and failed silently, so no result was ever reusable and every call ran three models afresh. The cached payload is now also checked against the surface that produced it, so this tool is never served a row written by the public web check, whose prompt and payload differ.

A quick audit reports NAMING, not knowing (changed 24 September 2026): an engine counts in mentioned when its answer contains the brand name, and an answer that says "I don't have reliable information about Zorvane" contains it — so a made-up brand can be named by every engine. The count is unchanged; what changed is that the payload now says what it is. percentage keeps its value: it is the named rate (mentioned ÷ answered, null when nothing answered). The payload carries an additive top-level namingNote, the same sentence every screen prints. Each model's excerpt is now the engine's opening lines — about 300 characters from the start of its answer, cut at a word boundary, with markdown emphasis and link syntax removed — for every engine that answered, named or not, and null only for an engine that did not answer. It used to be the first 200 characters untrimmed here and a window around the name on the web check, so an opening "I don't have reliable information about…" could be cut away. A call refused before any engine runs — the platform paused, the platform balance below its floor, a check that could not be completed, or an engine lineup that could cost more than a quick audit is allowed to — fails with one message, Quick audit is temporarily unavailable. Please try again later., whichever it was; it used to carry the refusing gate's internal detail. From the same date brand_name is cleaned the way the web check cleans it (control, format, bidi and zero-width characters removed, whitespace collapsed), the cleaned name is the one asked about, cached and returned, and it must be 2–80 characters before cleaning: the web check cuts a longer name to 80 characters after cleaning, this tool refuses it with an invalid-arguments error. A name that, once cleaned, has fewer than 2 characters or no letter or digit is refused on both. Each call, a cached answer included, also counts toward its own hourly cap, the same size as the plan's captures-per-hour cap and separate from capture_snapshot's. Results cached before this date, or under an earlier wording of namingNote, are recomputed on the next call rather than served.

A cut-off answer is neither named nor not named (changed 25 September 2026): each model entry carries an additive cutOff: true when the engine ran out of output budget before it finished — the gateway's finish_reason: "length", or the provider's native MAX_TOKENS, read from the response and never inferred from the text. Such an entry has mentioned: false and sits outside both sides of the count. visibility carries an additive cutOff count: percentage is mentioned over answered − cutOff, and it is null — with reason: "answers_cut_off" and a plain sentence in note — when every engine that answered was cut off, a different condition from engines_unreachable. The output budget per engine now follows the model: an engine the model registry describes as reasoning, or has not yet described, is asked with 1,500 output tokens where it was a flat 200 here and 500 on the web check (gemini-3.6-flash spent 479 of 500 on reasoning and returned 65 characters of junk), and the lineup is priced at each engine's own budget before any call. A result in which any engine was cut off is not cached, so the next call runs the engines again.

Capture Runs

ToolDescriptionMin Role
list_runsList capture runs — the receipt for each capture pass: expected vs actual snapshot counts, status, duration, shape hashes, trigger, and label. Filter by status, run_type (scheduled, manual, backfill or historical_synthesis), prompt group or since. Dollar cost fields carry their figures for org owner/admin tokens only; other tokens get the same fields as nullviewer
get_runGet one run's full detail: the run row, its snapshots, per-engine completion, the prompt × engine completion matrix, same-shape run history, and the previous same-shape run for diffing. Dollar cost fields carry their figures for org owner/admin tokens only; other tokens get the same fields as nullviewer
diff_runsDiff two capture runs: full apples-to-apples when shape hashes match, intersection-only plus a shape-drift block otherwise. Per-cell deltas: brand mentions, sentiment, rank, snapshot count. expected_comparable is false when either run has no expected count — see the note belowviewer

expected_snapshot_count can be null on list_runs, get_run and diff_runs, since 2026-09-06. A run refused before it was sized — a paused organisation, or a credit gate, both of which stop the run before its fan-out is computed — has no expected count, and the field says so rather than reporting 0. Zero is a different statement: it means the run was sized and had nothing to capture.

A client that renders actual / expected should print something like "not sized" for the null case rather than a fraction. diff_runs carries expected_comparable: boolean — false when either run has no expected count, because there is no delta to take against an absence. The per-cell diffs count what was actually captured and are unaffected.

A run cut short says why, per cause (added 25 September 2026): a run that captured fewer answers than it planned carries an additive metadata.shortfall on list_runs and get_run — one entry per cause, each { count, reason }, with count null when the run was refused before it was sized. The causes are model_not_served (an engine whose model the registry no longer serves, skipped before any call, never charged, not counted against the allowance or the daily cap), provider_declined (the AI provider could not take the answers; nothing was charged), platform_capacity and platform_pause (a platform-side pause), plan_cap (the daily cap, the included allowance or the pay-as-you-go cap) and provider_error. Two more from 23 October 2026, both on a scheduled run that never started, with count null: start_failed (the platform could not start it; it is retried every hour and the cycle is kept) and empty_group (the schedule's question group has no active questions). reason is the same plain sentence the Cycles pages print; nothing internal is in it. skipped_snapshot_count is the model_not_served count on a run that ran; a run refused before it ran keeps the whole planned count there. Runs recorded before that date carry no shortfall. Nothing was renamed or removed.

Admin — Platform Owner

These tools are physically absent from the tool list for anyone who is not a platform owner — they never appear in tools/list for a normal customer token.

ToolDescriptionMin Role
get_health_reportSystem health check across all platform componentsplatform_admin
get_platform_statsPlatform-wide statistics — org/user/project/snapshot counts, 30-day usage + cost rollups, per-provider costs, daily trends, top users/orgs by costplatform_admin
platform_balance_checkCurrent OpenRouter balance, burn rate, and runway forecastplatform_admin
platform_pause_orgPause or unpause an organization's snapshot captures (args: org_id, action, duration_hours, reason)platform_admin
platform_top_orgsTop organizations ranked by cost, token usage, and snapshot countplatform_admin
platform_near_limit_orgsOrganizations approaching their plan limits (>80% usage on any dimension)platform_admin
platform_cost_intelligencePer-org margin (revenue vs cost); optionally drill into one org for a project/user cost breakdownplatform_admin

All platform-owner tools are only available to users whose email is listed in the PLATFORM_ADMIN_EMAILS environment variable.


Resources

Resources are read-only data endpoints your AI assistant can browse for context. Three are static; the other eight are templated by ID.

URIDescription
aeo://projectsList of all projects in your organization
aeo://modelsAll available AI models grouped by provider
aeo://rate-limitsYour organization's effective rate limits
aeo://projects/{id}/summaryProject summary with key metrics
aeo://projects/{id}/snapshots/recentLast 10 snapshots for a project
aeo://projects/{id}/competitorsCompetitor list for a project
aeo://projects/{id}/geo-auditsRecent GEO audit results for a project
aeo://projects/{id}/ai-trafficAI referral traffic summary for a project
aeo://projects/{id}/actionsPending insight actions for a project
aeo://organizations/{id}/planCurrent plan, limits, and feature flags
aeo://models/{provider}Models from a specific provider

Prompts

Prompt templates generate structured reports from your data.

PromptDescriptionArguments
weekly_reportWeekly AI visibility report with trends, highlights, recommendations; engines are compared inside each question type (the blended LLM comparison is included for compatibility, marked not to rank on)project_id
competitor_analysisCompetitor comparison: share of voice, overlap, rankingsproject_id, days?
content_recommendationsContent improvement suggestions from snapshot analysesproject_id, limit?
visibility_summaryQuick current-state summary with today's metrics and alertsproject_id
geo_optimizationGEO optimization plan based on the latest audit resultsproject_id
ai_traffic_analysisAnalyze AI referral traffic trends with growth strategiesproject_id, days?

Rate Limits

Rate limits are enforced per token and tiered by your organization's plan:

PlanRequests / minuteRequests / hourCaptures / hour
Free / Starter (baseline)601,00010
Pro-Individual605005
Pro-SME (and legacy Professional)1202,00020
Enterprise-Brand (and legacy Enterprise)24010,00050
Enterprise-Agency36020,000100
Custom60050,000500

The per-minute and per-hour caps cover all tools (resource reads and prompt fetches count too); the captures cap applies to capture_snapshot, and quick_audit has its own hourly cap of the same size (from 24 September 2026 — before that quick_audit counted only toward the per-minute and per-hour caps). Unknown or missing plans fall back to the free-tier baseline — never a more permissive tier. The aeo://rate-limits resource advertises every tier's caps plus your org's effective limits, read from the same table the limiter enforces.

When rate limited, the tool returns an error with a retryAfterSeconds value.


Error Handling

Tool errors are returned as content with isError: true:

{
  "content": [{ "type": "text", "text": "{\"error\": \"...\", \"statusCode\": 401}" }],
  "isError": true
}
Status CodeMeaning
401Missing, invalid, expired, or revoked token
403Insufficient role or cross-org access denied
404Resource not found
429Rate limit exceeded
500Internal server error

When a tool fails because the data it reads could not be loaded, the error reads "We couldn't load this data just now. Try again in a few minutes." — never the database's own message. The same holds for a per-row error inside a successful result (set_brand_facts).


Audit Logging

Every tool call is logged for security and usage tracking:

  • Who: Token, user, organization
  • What: Tool name, input parameters (sanitized)
  • When: Timestamp and duration
  • Result: Success or error

Audit logs are viewable by organization admins.


Example Conversations

Check Mention Rate & Visibility Score

You: How is my brand doing on AI search engines today?

AI (calls list_projects then get_dashboard_metrics): Over the last 30 days your brand "TechShu" has a 30% mention rate and a Visibility Score of 49/100 across AI search engines, with a sentiment score of 72%. Average rank position is 3.2, up from 3.5 in the prior 30 days.

Capture a Snapshot

You: Run a snapshot for my "best CRM software" prompt

AI (calls list_prompts to find the prompt, then capture_snapshot): Captured responses from 8 AI models. Your brand was mentioned in 3 out of 8 responses. Sentiment was positive in 2 and neutral in 1.

Weekly Report

You: Generate my weekly visibility report

AI (invokes weekly_report prompt): Here's your weekly report for TechShu AEO Tracking...


OAuth 2.1 Developer Reference

If you're building an MCP client or integration that needs OAuth (rather than static tokens), here are the technical details.

Discovery

Your client should first fetch the Protected Resource Metadata to find the authorization server:

GET https://mcp.aeo.techshu.ai/.well-known/oauth-protected-resource

Then fetch the Authorization Server Metadata:

GET https://aeo.techshu.ai/.well-known/oauth-authorization-server

Dynamic Client Registration

Register your client automatically (RFC 7591):

POST https://aeo.techshu.ai/api/mcp/oauth/register
Content-Type: application/json

{
  "client_name": "My AI Tool",
  "redirect_uris": ["https://your-app.example.com/callback"],
  "grant_types": ["authorization_code"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}

Redirect URIs must use HTTPS. In production, localhost and 127.0.0.1 redirect URIs are refused, as are private or internal hosts, URIs that carry a user name or password, and URIs with a fragment.

Authorization Flow

  1. Generate a PKCE code verifier (43-128 character random string) and its S256 challenge
  2. Redirect the user to the authorization endpoint:
GET https://aeo.techshu.ai/api/mcp/oauth/authorize
  ?response_type=code
  &client_id=mcp_YOUR_CLIENT_ID
  &redirect_uri=https://your-app.example.com/callback
  &code_challenge=BASE64URL_S256_HASH
  &code_challenge_method=S256
  &scope=mcp:tools mcp:resources mcp:prompts
  1. User logs in, sees the consent screen, picks their organization and role cap, and approves
  2. User is redirected to your redirect_uri with ?code=AUTH_CODE

Token Exchange

Exchange the authorization code for tokens:

POST https://aeo.techshu.ai/api/mcp/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=AUTH_CODE
&client_id=mcp_YOUR_CLIENT_ID
&redirect_uri=https://your-app.example.com/callback
&code_verifier=YOUR_ORIGINAL_VERIFIER

Response:

{
  "access_token": "oat_...",
  "token_type": "bearer",
  "expires_in": 3600,
  "refresh_token": "ort_...",
  "scope": "mcp:tools mcp:resources mcp:prompts"
}

Refresh Tokens

When the access token expires, use the refresh token to get a new one:

POST https://aeo.techshu.ai/api/mcp/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=ort_YOUR_REFRESH_TOKEN
&client_id=mcp_YOUR_CLIENT_ID

Token Revocation

Revoke an access token or refresh token (RFC 7009):

POST https://aeo.techshu.ai/api/mcp/oauth/revoke
Content-Type: application/x-www-form-urlencoded

token=oat_OR_ort_TOKEN

Always returns HTTP 200, regardless of whether the token was valid.

OAuth Scopes

ScopeWhat It Grants
mcp:toolsAccess to all MCP tools
mcp:resourcesAccess to all MCP resources
mcp:promptsAccess to all MCP prompt templates

All three scopes are granted by default if no scope is specified.


Compatibility

PlatformAuth MethodsStatus
Claude.ai (web, desktop, mobile)OAuthVerified by AEO Optima Aug 18, 2026 (sign-in only)
Claude.ai with a fixed token (beta)Token in a request headerDocumented by the vendor, not verified by AEO Optima
Claude Code (CLI)Bearer tokenDocumented by the vendor, not verified by AEO Optima
ChatGPT (developer mode)OAuthDocumented by the vendor, not verified by AEO Optima
Grok (xAI API remote MCP tool)Bearer tokenNot documented by the vendor, not verified by AEO Optima
OpenAI Codex (CLI + IDE + desktop)Bearer tokenDocumented by the vendor, not verified by AEO Optima
CursorBearer tokenDocumented by the vendor, not verified by AEO Optima
WindsurfBearer tokenDocumented by the vendor, not verified by AEO Optima
VS Code + CopilotBearer tokenDocumented by the vendor, not verified by AEO Optima
Gemini CLIBearer tokenDocumented by the vendor, not verified by AEO Optima
Amazon Q DeveloperSee Amazon Q Developer's MCP guideNot documented by the vendor, not verified by AEO Optima
OpenAI Agents SDKBearer tokenDocumented by the vendor, not verified by AEO Optima
Anthropic APIBearer tokenDocumented by the vendor, not verified by AEO Optima
MCP API Reference — AEO Optima