MCP server
Connect an AI agent to Voidhash. It signs in as you, with no key to copy.
The Voidhash MCP server connects an AI agent to Voidhash. A compatible agent can read revenue, subscription and trial analytics and ad campaign performance, and inspect and edit paywalls, write components, and render previews. This page shows how to add the server to your agent, how it signs in, and how to confirm that it works.
Connect your agent
Add the server to your agent. It signs in through your browser the first time it uses Voidhash, so there is no key to copy or store.
| Agent | How to add the server |
|---|---|
| Claude Code | claude mcp add --transport http voidhash https://api.voidhash.com/api/mcp |
| Cursor | The Add to Cursor button under Connect an agent in Studio, or .cursor/mcp.json |
| Codex | codex mcp add voidhash --url https://api.voidhash.com/api/mcp |
| VS Code | The Add to VS Code button under Connect an agent in Studio |
| Claude Desktop | Settings → Connectors → Add custom connector, with the server URL |
To set up every agent on your computer at once, run:
npx voidhash-cli mcp installIt finds Claude Code, Cursor, Codex, VS Code and Claude Desktop and adds the server to each one you choose. It writes no keys.
Other agents need a remote MCP server that uses streamable HTTP and supports MCP sign-in (OAuth). Clients that use JSON configuration commonly accept this shape:
{
"mcpServers": {
"voidhash": {
"type": "http",
"url": "https://api.voidhash.com/api/mcp"
}
}
}Your agent acts as you
When the agent first calls the server, your browser opens and you sign in to Voidhash. From then on the agent acts as you: it can do what your role allows in each project of each organization you belong to, and nothing more. When your role changes, or you leave an organization, the agent's access changes on its next request.
Agents you sign in are listed under Settings → Connected apps in Studio, with the CLI. From there you can:
- make an agent read-only, so it can read but every change is refused;
- disconnect an agent, which then needs to sign in again.
An agent that goes unused for 90 days is signed out.
Every change an agent makes is recorded in the audit log as yours, with the agent named beside you.
An agent that runs on a server or on a schedule, with nobody there to sign in, uses a project
secret key instead. Create one with only the access it needs; see Limit what a secret key can
do. Send it as a bearer token:
Authorization: Bearer vh_sk_....
Server
The server runs at one URL:
https://api.voidhash.com/api/mcpIt uses streamable HTTP as its transport. It implements the stateless MCP protocol, version
2026-07-28. Each request stands on its own, with no initialization handshake or session to keep
alive. Clients that support only the earlier session-based versions cannot connect.
Tools
The server groups its tools into toolsets. A request lists, and can call, only the tools you (or the secret key) have permission for, so the same server serves a read-only reporting agent and a paywall designer.
Choosing a project
Every tool except list_projects takes an optional project argument, a project ID or slug.
list_projects lists the projects you can use, with their organizations. You can leave project
out when you have only one project, when the agent uses a secret key (which belongs to one project),
or when the client sends a default project in the X-Voidhash-Project header. Otherwise the tool
asks for one.
| Toolset | Tools | Permission |
|---|---|---|
| Analytics | list_insights, run_insight, acquisition_report | project:analytics:read |
| Ads | ads_overview, campaign_performance, ads_issues, ads_cohorts, list_ad_campaigns | project:ads:read (and project:analytics:read for Voidhash numbers) |
| Paywalls | list_paywalls, list_products, list_fonts, bash, list_components, read_component, get_component_build | project:paywalls:read (project:products:read for products) |
| Paywalls | begin_paywall_edit and every tool that uses its edit session, create_product, write_component | project:paywalls:write (project:products:write for products) |
Tools that only read are marked with MCP's read-only annotation, so clients can run them without
asking for confirmation. Tools whose change cannot be undone, such as revert_paywall_edit, are
marked destructive, so clients ask before running them. A read-only agent sees only the tools that
read.
Analytics
list_insights returns the built-in insights, such as revenue, MRR, active subscriptions, trials,
trial conversions and churn, with what each measures, its unit, and the time ranges, granularities
and filters it accepts. run_insight runs one insight with the same inputs as the
insights endpoint: a time range preset such as
last_30d or a custom start and end, a granularity, and an optional filter. It returns the
period it covered, a summary, and one value per bucket, with the unit:
{
"insightId": "builtin/revenue",
"unit": "USD",
"environment": "production",
"period": {
"start": "2026-10-01T00:00:00.000Z",
"end": "2026-10-08T00:00:00.000Z",
"granularity": "day"
},
"summary": { "value": 1250.4, "meaning": "total over the period" },
"series": [{ "start": "2026-10-01T00:00:00.000Z", "value": 180.25 }]
}Amounts are in US dollars and net of refunds, rates are percentages, and periods are in UTC.
run_insight reports production purchases only, unlike the insights endpoint. To include sandbox
purchases, filter on provider.environment yourself (1 is production, 2 sandbox); the result's
environment field shows whether the production default applied.
acquisition_report takes the same inputs as the
acquisition endpoint: a from and to
day, the level to group by (network, campaign, adset, ad or surface), and optionally a
network, campaign, ad set or ad filter, currency, time zone, revenue window, key conversion and
environment. Each group reports the visits its ads brought, the people who signed up after their
first touch, their app installs, trials, payers and revenue, with the ad platform's campaign, ad set
and ad IDs, so an agent can join them to the spend it reads from the ad platform. The report also
has a funnel by surface, where payers paid, and how much revenue can be traced to a first touch.
Amounts are in the requested currency. returningPeople were reached by a touch but were already
known, so they are not counted as acquired. Revenue comes from production unless you set
environment. See ad measurement for the definitions.
Ads
When the project has a connected Meta ad account, the ads tools report paid acquisition the way the Ads pages in Studio do. Every tool only reads.
| Tool | What it returns |
|---|---|
ads_overview | Spend, net revenue, people acquired, key conversions, cost per key conversion and ROAS, with the previous period; spend and revenue by day; the funnel by surface; where payers paid; each platform next to organic and other sources; issues to look at. |
campaign_performance | One row per campaign, ad group (Meta's ad set) or ad with delivery and its reason, destination, budget, the platform's numbers and Voidhash's numbers, plus totals over every matching row. |
ads_issues | Rejected ads, learning-limited ad groups, objects that are on but not delivering, account problems, spending limits close to the cap, failed syncs, and active ads whose links miss the tracking parameters. |
ads_cohorts | Weekly or monthly cohorts of the people your connected ad platform brought in (organic people are not included), with ROAS (or revenue per payer, or payers) at days 0 to 90 after acquisition, and the day each group pays back. |
list_ad_campaigns | The synced campaigns with delivery, reasons, destination, objective, optimization event, bid strategy and budget, and each ad account's currency, time zone, status and sync status. |
Agents that called the first version of campaign_performance need to change; see the list below.
Changes to campaign_performance:
adAccountIdandrevenueWindoware removed. A call that still passes one fails with a message naming its replacement:list_ad_campaignswithadAccountIdfor one account's campaigns, andads_cohortsfor revenue by day after acquisition. Revenue is to date.- Each row keeps the platform's numbers in
platformand Voidhash's invoidhash.roasis nowvoidhash.trueRoas,metaRoasisplatform.platformRoas, andcostPerAcquisitionisvoidhash.costPerSignup. - Rows cover synced campaigns, ad groups and ads only. People attributed to IDs no account has
synced are no longer separate rows, and account spend that no ad row accounts for (such as
deleted ads), formerly
unallocated, is no longer part of the totals; the overview's spend still includes it. leveltakesad_group(adsetis still accepted). A range is arangepreset or bothfromandto; one without the other is refused.
Two sources, never blended. Every row keeps two objects apart. platform holds what the ad
platform reports with its own attribution: spend, impressions, link clicks, CTR, its purchase value
and ROAS, and its results with their type. voidhash holds what Voidhash measured for the people
whose first touch came from the ad: visits, app installs, signups, trials, payers, key conversions,
and gross, refunded and net revenue to date. Spend is the one platform number Voidhash's ratios use.
| Metric | Definition |
|---|---|
| People acquired, signups | People who signed up after a first touch from the ad, counted once. |
| Key conversion | The step the project measures cost against: signup, trial or payer (payer by default). |
| Net revenue | Revenue after refunds from those people, to date, in the report currency. |
| True ROAS | Voidhash net revenue ÷ spend. The platform's ROAS (its purchase value ÷ spend) is shown beside it. |
| Cost per step | Spend ÷ the people Voidhash measured at the step: cost per signup, payer or key conversion. |
| Cost per link click | Spend ÷ the platform's link clicks; both numbers come from the platform. |
| Cohort ROAS | A cohort's cumulative net revenue ÷ the spend on the days its people were acquired. Curves only rise, except through refunds. |
Totals add only what adds up. Reach and frequency are per row and never summed, because one person can see ads from many rows, and results of different types, such as landing page views and app installs, are listed apart rather than added. Steps a project does not use are left out, so a web-only project has no installs and an app-only project has no visits, and website ads never report installs.
ads_overview, campaign_performance and ads_cohorts take a range preset (last_7_days by
default, last_13_weeks for cohorts; the last_* presets end yesterday) or both from and to
days, and optionally compare, platform, currency, timezone and environment.
list_ad_campaigns and ads_issues report current state and take no range. campaign_performance
reads reach and frequency per row only with includeReach, and hides ended objects only when they
had no delivery in the range. Money defaults to the ad accounts' currency, converted at each day's rate when you ask
for another, and days to the ad accounts' time zone. Revenue comes from production unless you choose
another environment. Days from provisionalFrom on are still changing, as the platform keeps
attributing conversions to them. Read warnings before acting on the numbers: each has a code,
such as sync_failed, currency_converted or reach_limited, and the details that go with it.
Spend in the overview is the ad accounts' total; the part no ad accounts for, such as deleted ads,
is listed separately.
Voidhash numbers need project:analytics:read as well. Without it, the tools still answer with the
platform's numbers and say what is left out, and ads_cohorts explains that it needs the
permission. Every role has both, and so does a secret key with the Read-only analytics access.
Verify the connection
Ask the agent a question that needs the server:
Which Voidhash projects can you see?
The agent should call list_projects. Then ask about one of them, such as "What was my revenue over
the last 30 days in my-project?", and the agent should call run_insight.
If the agent reports that it is not signed in, start its sign-in again; in Codex, run
codex mcp login voidhash. If a tool you expect is missing, your role does not allow it in that
project, or the agent is read-only.