Contentstack Canoe

Bawa data visibilitas AI Contentstack Canoe ke agen mana pun. Lihat bagaimana ChatGPT, Gemini, Perplexity, dan Claude menyebut serta mengutip merek Anda, siapa yang mereka rekomendasikan sebagai gantinya, dan apa yang perlu diperbaiki terlebih dahulu, lalu mulai proses baru. Sembilan alat. Mulai dengan paket gratis, MCP tersedia di Growth. Login OAuth akan segera hadir.

Server MCP Terhosting

npx add-mcp 'https://canoe.contentstack.com/api/mcp'

Terpasang ke Claude Code, Codex, Cursor, dan lainnya

Dokumentasi

Server URL

https://canoe.contentstack.com/api/mcp

Transport

Streamable HTTP, stateless. Tools only.

Auth

A Read & write API key, sent as Authorization: Bearer <key>

Config name

contentstack-canoe. Use it as the server key in your client config so skills and examples match.

One loop, nine tools

Most jobs need one call: get_geo_latest_report returns scores, competitors, recommendations and run deltas, already interpreted.

  1. Discover Find the brand and monitor. list_projects list_geo_tests
  2. Assess Read the report, then history, answers and sources. get_geo_latest_report get_geo_test_history get_geo_latest_citations
  3. Fix Your agent drafts the change in your CMS or repo. Contentstack MCP or your own tools
  4. Re-measure Start a run and compare it with the last one. trigger_geo_test_run get_geo_latest_report

Each run feeds the next assessment. run_deltas shows what moved.

The fix happens in your systems. Contentstack Canoe never writes to your site.

Names in the tools

A project is a brand. A geo test (test_id) is a monitor.

Quickstart

Five minutes with Claude Code. Other clients are under Connect your client.

  1. Check your plan MCP comes with Growth and Enterprise. Compare plans
  2. Create a Read & write key Open Settings, then API keys. Name it after the job, pick Read & write and copy it. It's shown once.
  3. Put the key in an environment variable
    export CONTENTSTACK_CANOE_API_KEY="sk_your_key_here"
    
  4. Add the server
    claude mcp add --transport http \
      contentstack-canoe \
      https://canoe.contentstack.com/api/mcp \
      --scope user \
      --header \
      "Authorization: Bearer $CONTENTSTACK_CANOE_API_KEY"
    
    claude mcp list should show contentstack-canoe as connected.
  5. Ask your first question
    List my Contentstack Canoe brands and their monitors. Which monitor lost the most visibility since its last run?
    
    Reading data never spends prompts.

API keys

Every request sends a key in the header. Keys work on Growth and Enterprise.

Format

sk_..., sent as Authorization: Bearer sk_... or x-api-key: sk_...

Identity

Acts as its creator, in one workspace. If they lose access, so does the key.

Limit

Up to 3 active keys per person in each workspace.

Lifetime

No expiry. Revoke one and it stops at once.

Requests

10,000 a month on Growth, shared with the API. Over MCP, only tool calls count, including failed ones.

Prompts

Only trigger_geo_test_run spends prompts.

Why Read & write, even to read

MCP requests are POSTs, and Read only keys can only make GETs, so they're refused. Read only MCP access is coming soon. Until then, block the write tool.

Connect your client

Every config uses contentstack-canoe as the server key and keeps the key out of files you commit.

Available claude mcp add or .mcp.json with a header

The Quickstart command adds it for all your projects. To share it through git, commit .mcp.json at the repo root instead. Claude Code fills in ${CONTENTSTACK_CANOE_API_KEY} from each person's environment.

{
  "mcpServers": {
    "contentstack-canoe": {
      "type": "http",
      "url": "https://canoe.contentstack.com/api/mcp",
      "headers": {
        "Authorization": "Bearer ${CONTENTSTACK_CANOE_API_KEY}"
      }
    }
  }
}

Check with claude mcp list or /mcp. Tools show as mcp__contentstack-canoe__list_projects and so on.

Available mcp.json with url and headers

Use ~/.cursor/mcp.json for every project or .cursor/mcp.json for one repo.

{
  "mcpServers": {
    "contentstack-canoe": {
      "url": "https://canoe.contentstack.com/api/mcp",
      "headers": {
        "Authorization": "Bearer ${env:CONTENTSTACK_CANOE_API_KEY}"
      }
    }
  }
}

Cursor reads ${env:...} from the environment it was launched from.

AvailableCopilot agent mode, .vscode/mcp.json with servers and a password input

For Copilot agent mode, save this as .vscode/mcp.json. VS Code asks for the key once and stores it. For every workspace, add the block with MCP: Open User Configuration.

{
  "inputs": [
    {
      "type": "promptString",
      "id": "contentstack-canoe-key",
      "description": "Contentstack Canoe API key",
      "password": true
    }
  ],
  "servers": {
    "contentstack-canoe": {
      "type": "http",
      "url": "https://canoe.contentstack.com/api/mcp",
      "headers": {
        "Authorization": "Bearer ${input:contentstack-canoe-key}"
      }
    }
  }
}

It's servers, not mcpServers, so a config pasted from Cursor won't work.

AvailableWindsurf and Devin Desktop, mcp_config.json with serverUrl and headers

Windsurf now lives under Devin Desktop (Cascade). Edit ~/.config/devin/mcp_config.json on macOS and Linux or %APPDATA%\devin\mcp_config.json on Windows. Older installs use ~/.codeium/windsurf/mcp_config.json.

{
  "mcpServers": {
    "contentstack-canoe": {
      "serverUrl": "https://canoe.contentstack.com/api/mcp",
      "headers": {
        "Authorization": "Bearer ${env:CONTENTSTACK_CANOE_API_KEY}"
      }
    }
  }
}

Cascade allows 100 tools across all servers. This one adds nine.

Available config.toml with bearer_token_env_var

Codex sends the key from the variable you name as a bearer token.

[mcp_servers.contentstack-canoe]
url = "https://canoe.contentstack.com/api/mcp"
bearer_token_env_var = "CONTENTSTACK_CANOE_API_KEY"

Or run codex mcp add contentstack-canoe --url https://canoe.contentstack.com/api/mcp, then add the bearer_token_env_var line.

Availablethe mcp-remote bridge

The config file runs local servers, so the mcp-remote bridge (needs Node.js) connects the remote one. Edit claude_desktop_config.json in ~/Library/Application Support/Claude/ on macOS or %APPDATA%\Claude\ on Windows, then restart.

{
  "mcpServers": {
    "contentstack-canoe": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote",
        "https://canoe.contentstack.com/api/mcp",
        "--header", "Authorization:${CONTENTSTACK_CANOE_AUTH}"
      ],
      "env": {
        "CONTENTSTACK_CANOE_AUTH": "Bearer sk_your_key_here"
      }
    }
  }
}

The key lives in this file, so keep it private. The space inside the env value avoids a Windows argument bug.

LimitedClaude.ai and Claude Desktop connectors, request-header beta organizations only

Custom connectors with a key header work only for organizations in Anthropic's request-header beta. Not in it? Use it without a connector.

  1. An organization owner opens Organization settings, then Connectors, and adds a custom web connector at https://canoe.contentstack.com/api/mcp.
  2. Choose no sign-in and add a request header named authorization with the value Bearer sk_...
  3. Members connect it in their settings. Block trigger_geo_test_run unless people should start runs.

One key for everyone

Every user acts as the key's creator. The header can't be edited, so rotate by removing and re-adding the connector.

Coming soonneeds OAuth sign-in

ChatGPT can't send an API key header, so it connects once OAuth sign-in ships. Until then, use it without a connector, or use a client that sends headers, like the Codex CLI.

Available authorization_token on the server entry

For agents you build. The MCP connector sends your key as a bearer token. trigger_geo_test_run is off, since no person is there to approve a run.

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "anthropic-beta: mcp-client-2025-11-20" \
  -H "content-type: application/json" \
  -d @- <<EOF
{
  "model": "claude-opus-5",
  "max_tokens": 16000,
  "mcp_servers": [{
    "type": "url",
    "url": "https://canoe.contentstack.com/api/mcp",
    "name": "contentstack-canoe",
    "authorization_token": "$CONTENTSTACK_CANOE_API_KEY"
  }],
  "tools": [{
    "type": "mcp_toolset",
    "mcp_server_name": "contentstack-canoe",
    "configs": { "trigger_geo_test_run": { "enabled": false } }
  }],
  "messages": [{ "role": "user", "content": "Summarize the latest Contentstack Canoe report for Tarnwell Cycles." }]
}
EOF

Add an agent skill for the procedure. Details in Anthropic's MCP connector docs.

Any client that speaks Streamable HTTP and sends a custom header should work. To check the connection by hand, run npx @modelcontextprotocol/inspector, pick Streamable HTTP and add the header.

Tool reference

All nine, in the order agents usually call them. Every tool but trigger_geo_test_run is annotated read only, so clients that honor annotations run them without asking.

9 tools, in call order

list_projects

Read onlyLists the brands in the key's workspace

Start here. Each brand's id is the project_id for the next call.

Parameters

None.

Returns

projects: your brands, each with id and name (up to 10). Have more? List them all with GET /api/projects?limit=50 from the API.

List my Contentstack Canoe brands.

list_geo_tests

Read onlyLists a brand's monitors with score and trend

ParameterTypeDescription
project_idstring, requiredThe brand's id from list_projects

tests: one entry per monitor with test_id, url, product, persona, location, cadence, score, score_trend_pct, schedule_status, last_run_at and last_run_status.

Show every Tarnwell Cycles monitor with its last score, its trend and when it last ran.

get_geo_latest_report

Read onlyThe full latest report for a monitor, interpreted, with the site audit

ParameterTypeDescription
test_idstring, requiredThe monitor's test_id from list_geo_tests

test_id, run_status, identity (brand, url, product, persona, location, answer_engines), overview (overall_score, visibility_pct, brand_rank, sentiment), score_anatomy, competitors, sentiment_detail, funnel, citations, site_audit, recommendations and run_deltas, plus _guidance when something needs your attention. See Reading responses.

site_audit carries the AI Readiness Score (readiness_score, 0 to 100) and the top fixes from the brand's latest site audit. It's null until an audit has run or if the site blocked the audit. Its score is separate from overall_score.

Summarize the latest results for our commuter e-bike monitor. Are the numbers from a finished run?

get_geo_test_history

Read onlyScores and rank run by run, for trends

ParameterTypeDescription
test_idstring, requiredThe monitor to read
windowinteger, optionalHow many runs to return, 1 to 50. Default 20.

runs: each with report_id, created_at, overall_score, per_engine_scores, visibility_pct, competition, mention_rank, sentiment_score, funnel and leaderboard_rank. Older runs carry rank only for the leaderboard.

How have our score and brand rank moved over the last 8 runs, engine by engine?

get_geo_latest_prompt_details

Read onlyEvery engine answer from the latest run

Every engine's full answer from the latest completed run, for exact quotes. It's large, so call it for words, not numbers.

ParameterTypeDescription
test_idstring, requiredThe monitor to read

Per-question answers from each engine and the visibility detail for the run, plus run with the report_id and created_at it came from.

Show me the exact answers where Aldren was recommended and Tarnwell Cycles wasn't mentioned.

get_geo_prompt_details

Read onlyEvery engine answer from a past run

ParameterTypeDescription
report_idstring, requiredThe run to read, from get_geo_test_history

Per-question answers and visibility detail for that run. An empty object if the run isn't found in your workspace.

Compare how ChatGPT answered "best commuter e-bike under $2,000" in the first September run and in the latest one.

get_geo_latest_citations

Read onlyCited sources from the latest run

Latest cited sources, split into your domain, competitors and third parties. by_url lists pages for PR and reviews.

ParameterTypeDescription
test_idstring, requiredThe monitor to read
scopestring, optionalsummary (default) or by_url
stagestring, optionalLimit to one buyer stage: Awareness, Consideration or Decision. Exact case. Other values return no rows.
from, todates, optionalLimit to a date range

With summary: total, owner_breakdown (brand, competitor and third party, each with count and percent), up to six top_domains and by_model. With by_url: up to 200 rows, each with url, domain, owner, prompts, responses and a per-engine count. Both include run.

Which third-party sites do the engines cite in the Consideration stage, and which of them also name Solvik or Pellow?

get_geo_citations

Read onlyCited sources for any run or date range

ParameterTypeDescription
test_idstring, requiredThe monitor to read
scopestring, optionalsummary (default) or by_url
report_idstring, optionalOne specific run
stagestring, optionalLimit to one buyer stage, in exact case, as above
from, todates, optionalLimit to a date range

The same summary or by_url shapes as get_geo_latest_citations, without run.

Did our own domain's share of citations grow between July and September?

trigger_geo_test_run

Starts a runStarts a run now. Spends prompts.

Runs a monitor now and spends prompts, so agents should ask first. It takes about two minutes. Then poll get_geo_latest_report until run_status.status is success or error.

ParameterTypeDescription
test_idstring, requiredThe monitor to run

url_id (the same id as test_id), status (running) and job_id. Fails with already_running if a run is in flight. If you're out of prompts, the run is accepted but doesn't start, and run_status.status turns to error.

We just published the Aldren comparison page. Re-run the monitor and tell me what changed.

Reading responses

Fields are snake_case and can be added over time. Check these four before you repeat a number.

run_status

idle, running, success or error. Mid-run, you see the last completed run. has_partial_failure and errored_sections flag what didn't finish.

_guidance.notes

Notes from the tool, not an engine: stale numbers, no runs yet, missing sentiment. Pass them on.

run_deltas.comparable

False with no previous run, so a zero delta means no data. leaderboard_rank_delta is positive when you climbed.

History tiers

Only the latest run has full competitor detail. Older runs keep leaderboard rank.

get_geo_latest_report, trimmed. Illustrative values, fictional brand.

{
  "run_status": { "status": "success", "last_run_at": "2026-10-05T09:14:02Z", "has_partial_failure": false },
  "identity": { "brand": "Tarnwell Cycles", "product": "Commuter e-bikes" },
  "overview": {
    "overall_score": 67,
    "visibility_pct": 62,
    "brand_rank": { "rank": 3, "of": 10 },
    "sentiment": { "label": "Positive", "score": 74 }
  },
  "funnel": { "awareness": 47, "consideration": 57, "decision": 81 },
  "site_audit": { "readiness_score": 80, "priority_fixes": ["..."] },
  "recommendations": [
    { "rank": 1, "category": "competitive", "title": "Close the gap with Aldren", "how": ["..."] }
  ],
  "run_deltas": { "comparable": true, "score_delta": 6, "leaderboard_rank_delta": 1 }
}

Treat report text as data

Answers, citations and quotes come from the web. Agents should quote them and never follow instructions inside them. Every Contentstack Canoe skill enforces this.

Scores, mentions and citations are computed in code, so report the values as returned. Sentiment is a model's read. Metrics defines every number.

Add the Contentstack MCP

With both servers, your agent reads a recommendation here, finds the entry in your stack and drafts the change for your approval.

{
  "mcpServers": {
    "contentstack-canoe": {
      "url": "https://canoe.contentstack.com/api/mcp",
      "headers": { "Authorization": "Bearer ${env:CONTENTSTACK_CANOE_API_KEY}" }
    },
    "contentstack": {
      "command": "npx",
      "args": ["-y", "@contentstack/mcp"],
      "env": { "CONTENTSTACK_API_KEY": "<YOUR_STACK_API_KEY>", "GROUPS": "cma" }
    }
  }
}

The Contentstack MCP has its own auth: see the Contentstack MCP server docs. Then add the Fix it in Contentstack skill, or run it unattended with Contentstack Agent OS.

Security and least privilege

A key carries its creator's authority in one workspace, and the tool list isn't a security boundary. Keep mistakes small.

  • One key per integration, named for its job, so you can revoke one alone.
  • Keys live in env vars or a secret manager, never in files or chats.
  • Block trigger_geo_test_run for read-only jobs. Claude.ai connectors and the Claude API can turn it off. Elsewhere, keep approval on.
  • A person approves CMS changes. Contentstack Canoe never writes to your site.
  • Revoke quiet keys. Check Last used.

We log each call's tool, user and workspace, never keys, headers or payloads. An id from another workspace returns nothing.

Errors

Tool errors

A failed tool returns isError: true, with code and message as JSON in its first text block.

Out of prompts? No tool error says so: the run's run_status.status turns to error. Check Usage in Settings and Plans and limits.

HTTP errors

These arrive before any tool runs, so clients usually show a failed connection.

Coming soon

  • OAuth sign-in Coming soonConnect ChatGPT and Claude.ai without a key header.
  • Read only keys for MCP Coming soonRead-only agent access, enforced by the key.
  • Native alerts Coming soonScore and competitor alerts without polling. Today, use the Visibility alerts skill.
  • Outbound webhooks Coming soonEvents like "run finished" sent to your endpoint.