Anchored Growth MCP

Tool reference

Generated — do not edit by hand. Produced from the server's own tools/list by scripts/dump_tools_schema.py --write-docs, so it cannot describe a contract the server does not serve.

Every tool is read-only, tenant-scoped, and writes one audit row per call before returning. tenant_id is optional everywhere: omit it and the server uses the company bound to your API key.

Read the alerts array in every response before acting on it. It is how this service discloses small samples, borrowed priors, placeholder maths and stale data. The full vocabulary is served as the ag://reference/alerts resource.

get_campaign_health

Campaign health assessment

Returns Anchored Growth's computed health assessment for a single campaign: composite score, risk tier, raw metrics, alerts, and company-level AI signals.

Use this when you need to evaluate whether a specific campaign is performing as expected, diagnose underperformance, or summarize health for stakeholders.

reply_rate is derived from the raw send and reply counters, so it is always consistent with the metrics block. Read the alerts array before trusting health_score: it discloses small samples, placeholder thresholds, and stale data.

Parameter Type Required Description
campaign_id string yes AG sequence ID — the campaign to score. Required.
tenant_id string or null no Anchored Growth company ID (UUID). OPTIONAL — omit it and the server uses the company bound to your API key, which is almost always what you want. Supply it only when calling with a multi-tenant bootstrap credential or over stdio. Supplying a company other than the one your key is bound to returns permission_denied.
window last_30_days or all_time no Scoring window. Use 'all_time' for imported or historical campaigns that have lifetime sends but no recent activity — 'last_30_days' would return insufficient_data for those. NOTE: the underlying metrics are all-time aggregates in both cases; the metrics_are_all_time_not_windowed alert discloses this when a windowed view was requested. Default last_30_days.

Annotations: destructiveHint=false, idempotentHint=true, openWorldHint=false, readOnlyHint=true

Output schema: declared (structuredContent is returned)

get_campaign_recommendations

Recommendation profiles

Returns Anchored Growth's pre-baked recommendation profiles for a tenant. Each profile has a code (e.g. 'TA-1', 'DOW-2', 'BWC-1'), a metric description, and a per-position breakdown (marketing / vp / c_suite / etc.) with optimal word count, best time of day, best day of week, recommended tone combination, and quality-graded confidence scoring.

Recommendations are tenant-scoped (company-level), NOT per-campaign. Use this when you need to answer 'what does AG's intelligence engine recommend doing differently?' rather than 'how is THIS campaign performing?'. The two tools are complementary.

Parameter Type Required Description
tenant_id string or null no Anchored Growth company ID (UUID). OPTIONAL — omit it and the server uses the company bound to your API key, which is almost always what you want. Supply it only when calling with a multi-tenant bootstrap credential or over stdio. Supplying a company other than the one your key is bound to returns permission_denied.
top_n integer (1–100) no Maximum recommendation profiles to return, ordered by total responses descending. Default 10.

Annotations: destructiveHint=false, idempotentHint=true, openWorldHint=false, readOnlyHint=true

Output schema: declared (structuredContent is returned)

get_bandit_state

Bayesian bandit state

Returns Anchored Growth's Thompson-sampler / Beta-posterior bandit state for a tenant. Each arm is a (channel, position) bucket (e.g. 'email#vp', 'linkedin#c_suite') with Bayesian posterior parameters (alpha, beta), observation count, posterior mean and variance, and provenance.

This is the actual Bayesian inference state that drives every send-time channel decision in the AG platform. Use it to answer 'what is the underlying statistical state behind AG's recommendations?' — the alpha/beta values are auditable, so a technical caller can verify the inference is real Bayesian update rather than a language model's guess.

Check backed_by_own_data and cold_start per arm before relying on a posterior: an arm may be carrying a borrowed cross-tenant prior rather than this tenant's own outcomes. last_updated is null when the stored row has no usable timestamp — the server will not invent one.

State is tenant-scoped, not per-campaign.

Parameter Type Required Description
tenant_id string or null no Anchored Growth company ID (UUID). OPTIONAL — omit it and the server uses the company bound to your API key, which is almost always what you want. Supply it only when calling with a multi-tenant bootstrap credential or over stdio. Supplying a company other than the one your key is bound to returns permission_denied.
top_n integer (1–500) no Maximum arms to return, ordered by observation count descending. total_arm_count reports the true total, and the results_truncated alert fires when it exceeds this cap. Default 50.

Annotations: destructiveHint=false, idempotentHint=true, openWorldHint=false, readOnlyHint=true

Output schema: declared (structuredContent is returned)

get_drift_state

Model drift state (CUSUM)

Returns Anchored Growth's CUSUM (Cumulative Sum) drift-detection state for a tenant: baseline reply rate, recent observed rates, accumulated CUSUM statistics, alarm threshold, alarm flag with human-readable reason, and a retrain-needed flag.

Call this BEFORE relying on get_campaign_recommendations or get_bandit_state, to check whether the underlying model is still calibrated.

IMPORTANT: read monitoring_status, not just alarm_active. alarm_active: false means 'no alarm' only when monitoring_status is 'active'. A status of 'insufficient_volume' means the tenant does not yet have enough weekly outcomes for the detector to run, and 'skipped'/'unavailable' mean it did not run at all — in those cases the absence of an alarm is NOT evidence that the model is calibrated.

State is tenant-scoped (one snapshot per tenant).

Parameter Type Required Description
tenant_id string or null no Anchored Growth company ID (UUID). OPTIONAL — omit it and the server uses the company bound to your API key, which is almost always what you want. Supply it only when calling with a multi-tenant bootstrap credential or over stdio. Supplying a company other than the one your key is bound to returns permission_denied.

Annotations: destructiveHint=false, idempotentHint=true, openWorldHint=false, readOnlyHint=true

Output schema: declared (structuredContent is returned)

get_action_audit_log

Tool-call audit trail

Returns the canonical audit trail of prior MCP tool calls for a tenant. Every other tool in this server writes exactly one row to the audit log per call, BLOCKING the response on the audit write — so the audit log is the complete, verifiable record of every interaction.

Each entry surfaces: timestamp, run_id, tool_name, actor type & ID, SHA-256 input/output hashes (payloads themselves are NEVER stored — only the hashes), latency in ms, and the error_type if the call failed. The response also includes a tool_breakdown count map and an error_rate over the returned window.

Calling this tool ITSELF writes an audit row (the audit invariant applies recursively), so the next call will show this one. That's by design — it's the cleanest possible proof that the audit-blocks-response discipline is real.

There is no cross-tenant view; the audit log is partitioned by tenant_id and there is no overload that bypasses that.

Parameter Type Required Description
tenant_id string or null no Anchored Growth company ID (UUID). OPTIONAL — omit it and the server uses the company bound to your API key, which is almost always what you want. Supply it only when calling with a multi-tenant bootstrap credential or over stdio. Supplying a company other than the one your key is bound to returns permission_denied.
tool_name string or null no Filter to one tool's calls, e.g. 'get_bandit_state'. Omit for all tools.
limit integer (1–200) no Maximum audit entries, newest first. Default 50.

Annotations: destructiveHint=false, idempotentHint=true, openWorldHint=false, readOnlyHint=true

Output schema: declared (structuredContent is returned)

get_recipient_intelligence

Per-contact intelligence

Returns a per-contact composite view: recent bandit decisions for THIS specific contact joined with the position-level recommendation guidance for the position bucket the contact maps to.

Use this to answer 'tell me about '. Without this tool the agent would call get_workflow_decisions, then look at the latest decision's positionProfile, then call get_campaign_recommendations and filter the position breakdown by hand. This tool collapses that into one round-trip and makes the join explicit in the contract.

When no decisions exist for the contact, inferred_position is null, the recent_decisions list is empty, and no_decisions_for_contact fires. When the contact's position has no recommendation data, position_unmapped_no_guidance_available fires and position_guidance is empty.

Tenant-scoped: contact_id is applied AFTER the tenant fetch; there is no overload that bypasses tenant isolation.

Parameter Type Required Description
contact_id string yes The prospect to profile, matched against their email address. Required.
tenant_id string or null no Anchored Growth company ID (UUID). OPTIONAL — omit it and the server uses the company bound to your API key, which is almost always what you want. Supply it only when calling with a multi-tenant bootstrap credential or over stdio. Supplying a company other than the one your key is bound to returns permission_denied.
decision_limit integer (1–50) no Maximum recent decisions to include. Default 5.

Annotations: destructiveHint=false, idempotentHint=true, openWorldHint=false, readOnlyHint=true

Output schema: declared (structuredContent is returned)

get_workflow_decisions

Per-contact decision history

Returns Anchored Growth's per-contact bandit decision history for a tenant. Each decision is one verifiable inference event: the model version that produced the recommendation, whether the Thompson sampler explored or exploited, the recommended channel (email / linkedin), tone, word-count range, best send day & hour, delay hours, confidence score, and the workflow gating verdict (AUTOMATE / AUTOMATE_WITH_WARNING / MANUAL).

Use this when you need to answer 'why did AG send THIS specific contact via channel X with tone Y?' — it's the receipts layer below get_bandit_state. Combine the optional contact_id filter with a tenant_id to drill into one prospect's decision history.

Decisions are returned newest-first, capped by limit. The always-on disclosure 'recommendations_are_company_scoped_not_per_campaign' is included for consistency with the other tools — decisions ARE per-contact, but the inference state behind them is company-scoped.

Parameter Type Required Description
tenant_id string or null no Anchored Growth company ID (UUID). OPTIONAL — omit it and the server uses the company bound to your API key, which is almost always what you want. Supply it only when calling with a multi-tenant bootstrap credential or over stdio. Supplying a company other than the one your key is bound to returns permission_denied.
contact_id string or null no Filter to one prospect's decision history. Omit to return the tenant's most recent decisions across all contacts. Matched against the contact's email address.
limit integer (1–200) no Maximum decisions to return, newest first. Default 50.

Annotations: destructiveHint=false, idempotentHint=true, openWorldHint=false, readOnlyHint=true

Output schema: declared (structuredContent is returned)