The tool surface
The MCP server is the product. Streamable HTTP, authorized by OAuth 2.1 or a console API key. Three tools: build a profile for a site, ask what is rising in its market, and check the balance.
Connecting
Two ways in, both as Authorization: Bearer.
OAuth 2.1
Point a client at /api/mcp and it discovers the rest. An unauthenticated call answers 401 with a WWW-Authenticate header naming /.well-known/oauth-protected-resource, which names this deployment as its own authorization server.
- Authorization code with PKCE, S256 only
- Dynamic client registration — no manual allowlist
- Public clients; there is no client secret to hold
- Access tokens last an hour; refresh tokens rotate on use
Approving a client is a decision a signed-in human makes on a consent screen that names it. Revoke it any time from API keys in the console.
Console API key
Issue one under API keys and send it as the bearer token. Simpler for a script you control, and the only option that carries a per-key spend cap — enforced server-side before a call runs, so a runaway loop stops at the ceiling rather than at a support ticket.
get_trends1 creditWhat is rising right now in one website's market: trending searches, breakout terms, what people are asking AI assistants about, and the news driving it. Reads live search demand, news and AI-assistant demand, and labels each rising term on_topic when it matches the site's own subject vocabulary. Everything else that is rising comes back too, labelled off-topic, because a national rise often creates demand inside a niche. Returns terms ranked on-topic first, then breakout, then momentum, each with momentum (0-100), velocity, a breakout flag, and context: the headlines or summary that explain why it is rising. Costs 1 credit. An empty result is not charged.
Input schema
{
"type": "object",
"properties": {
"site_id": {
"type": "string",
"description": "The site to work against. Use analyze_site first if you do not have one."
},
"on_topic_only": {
"type": "boolean",
"description": "Return only the terms that match the site's subject. Defaults to false."
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 50,
"description": "Maximum number of terms to return."
}
},
"required": [
"site_id"
],
"additionalProperties": false
}analyze_sitefree · rate limitedRead a website and build the profile its trends are read against: what the site is, and the subject vocabulary that decides which rising terms are on-topic for it. Crawls a handful of the site's own pages, weighted towards what it publishes rather than its homepage, because a homepage is written for a stranger and says little about the subject. Pass site_id to refresh an existing profile instead of creating one; a refresh replaces the subject vocabulary but keeps the geos and switches. Free, rate limited to 10 calls an hour.
Input schema
{
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "The site's URL, including the scheme."
},
"site_id": {
"type": "string",
"description": "Refresh this existing profile rather than creating a new one."
}
},
"required": [
"url"
],
"additionalProperties": false
}get_balancefreeCredit balance broken out by source, the plan, the period end, this key's spend cap, and the credit cost of every tool. Credits are consumed in order: monthly allotment, then overage, then prepaid. Free.
Input schema
{
"type": "object",
"properties": {},
"additionalProperties": false
}Calling it
Issue a key in the console, then point any MCP client at the endpoint. Errors come back structured — a code, a message, and the details an agent needs to decide what to do next. Trends describe demand at the moment of the call, so re-run rather than working from a saved list.
curl -sS https://your-deployment/api/mcp \
-H "Authorization: Bearer tw_live_..." \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_trends",
"arguments": { "site_id": "site_inkline", "on_topic_only": true }
}
}'What comes back
A ranked list: on-topic terms first, then breakout terms, then by momentum. Every term carries the same fields.
A response with fit_check: "not_run" means the profile has no subject vocabulary, so nothing could be marked on-topic. Run analyze_site again.

