/docs/mcp

MCP Server, Agent-First Interface

Every Content Architect feature is callable over the Model Context Protocol. The web UI is one client; AI agents are equal-class clients of the same API surface. Mutations route through the Agent Inbox so every agent-initiated action is policy-gated, idempotent, and audit-logged.

Endpoint

URL: POST /api/mcp
Transport: Streamable HTTP (MCP spec)
Auth: Authorization: Bearer <agent_token>

Get a token

Owners issue tokens from Settings → API (coming soon). For local development:

npx tsx --env-file=.env.local scripts/issue-mcp-token.ts <brand_id> [name]

The raw token is shown once at creation. Store it; it can't be recovered. Tokens are scoped per brand, allow a subset of agent_types, and carry a per-minute rate limit independent of the brand-wide daily cap.

Explore interactively with MCP Inspector

The MCP Inspector is Anthropic's official browser-based debugger. No install needed:

npx @modelcontextprotocol/inspector

# In the UI:
#   Transport: Streamable HTTP
#   URL:       http://localhost:3000/api/mcp
#   Headers:   Authorization: Bearer vsp_test_...

The Inspector renders the tool catalog, lets you fill in arguments from the live JSON Schema, and shows raw JSON-RPC responses. Recommended for any new tool you build.

Connect from Claude Desktop / Cursor

stdio MCP clients (Claude Desktop, Cursor) connect via the mcp-remote bridge:

// claude_desktop_config.json   (or cursor mcp.json)
{
  "mcpServers": {
    "ads-architect": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "http://localhost:3000/api/mcp",
        "--header",
        "Authorization: Bearer vsp_test_..."
      ]
    }
  }
}

Safety model

HOTL gate

Every mutation creates an agent_proposal. A human reviewer or auto-approve policy must approve before the action ships downstream.

Audit log

Every state transition is one row in agent_decisions , proposed, approved, edited, rejected, executed, failed. Latency tracked per transition.

Idempotency

Mutation tools use an idempotency key so re-running the same logical call upserts one row instead of piling up duplicates.

Rate limits

Each token has its own per-minute budget. Brand-wide daily_cap is enforced independently. 429 on exceed.

Scoped tokens

Tokens carry an allowed_agent_types allowlist. Tools outside the scope return a clear error.

dry_run

Mutation tools accept dry_run=true to preview the would-be payload without writing.

Tool catalog

The runtime catalog is also discoverable by calling tools/list via JSON-RPC, or interactively via MCP Inspector.

list_influencersList influencers
read

Search the brand's influencer DB with optional filters and pagination.

When to use
  • Finding existing influencers by handle, name, tier, or grade.
  • Before proposing outreach, to check if the influencer is already on file.
When NOT to use
  • When you already have an influencer ID (use get_influencer once it ships).
  • To search the public web, this only returns influencers already in our DB.
Arguments
searchstringname or @handle substring
tiernano | micro | mid | macro | mega
gradeA++ | A+ | A | B | C | X
categorystring
minFollowersinteger ≥ 0
maxFollowersinteger ≥ 0
pageinteger ≥ 1
perPageinteger 1–100
Returns
{ influencers: Influencer[], total: number }
list_inboxList agent-inbox proposals
read

List proposals in the brand's agent-inbox. Use this to self-correct: see which of your past proposals were approved, edited, or rejected.

When to use
  • Reviewing your own past proposals to learn what stuck and what didn't.
  • Filter by status='rejected' to read rejection reasons from the decision log.
  • Filter by agent_type to scope to a single agent (e.g. 'dm_generation').
Arguments
statuspending | approved | edited | rejected | auto_approved | expired | executed | failed | alldefault: pending
agent_typestringe.g. 'dm_generation', 'influencer_discovery'
limitinteger 1–200default: 50
Returns
AgentProposal[]
get_agent_first_metricsGet agent-first ratio metrics
read

Daily breakdown of how often this brand's proposals got approved unchanged. Use this for self-evaluation and drift detection.

When to use
  • Self-evaluation: see if your proposals get approved more than they get edited.
  • Drift detection: a falling agent_first_ratio means the agent is increasingly wrong.
Arguments
daysinteger 1–365default: 30
Returns
Array of { agent_type, day, proposed/approved/edited/rejected counts, agent_first_ratio, avg_review_latency_ms }
Notes
  • agent_first_ratio = (approved + auto_approved) / (approved + auto_approved + edited + rejected). Higher = the agent is getting it right unaided.
generate_dmGenerate DM / email draft
write (HOTL gate)

Generate three AI DM/email variants for an influencer on a campaign. Routes through the Agent Inbox, a human reviewer (or auto-approve policy) must approve before the message ships.

When to use
  • Drafting outreach for an enrolled influencer on a campaign.
  • Channel resolution is automatic: prefers email when Gmail is connected + influencer has one, else Instagram DM.
When NOT to use
  • When the influencer isn't yet enrolled in the campaign, enroll them first.
  • When you want to send immediately without review, that's not how this surface works. Every send goes through Agent Inbox.
Arguments
influencerId*uuid
campaignId*uuid
tonefriendly | professional | casualdefault: friendly
languageen | kodefault: en
channeldm | emailforce a channel; default auto-picks based on contact methods
dry_runbooleanpreview model output without writing to DB or creating a proposal
Returns
{ dry_run, draft_id, proposal_id, channel, variants, subject, grade, proposal_data }
Notes
  • Idempotent on the underlying dm_draft: re-running for the same (campaign, influencer) upserts the same row.
  • The created proposal is stamped with the calling token's id for forensics.

Architecture reference