# Campaign Commander Agent API and MCP > Political operations platform. One organization credential, bound to the organization that owns it, drives the MCP server. Connect to MCP with OAuth 2.1 (the supported self-service flow) or an existing API key in a compatible secret store; the versioned REST Agent API is API-key-only and an OAuth access token is not a direct versioned-API credential. This is a Campaign Commander integration document, not a published industry standard. ## Connect Read this block first: the compact machine bootstrap a compatible host needs to connect; no login or secret is required. Origin contract: the manifest canonical, protocol endpoint, and full-reference links identify the canonical production deployment and are REFERENCE ONLY; never redirect a noncanonical connection flow through them. These paths resolve against the URL from which this document was retrieved, which for production is the canonical origin. A copied or mirrored document is not an authorization authority; retrieve the chosen canonical service's discovery afresh. Bootstrap (compact, machine-readable; version 1): - version: 1 - resolveRelativeTo: the URL from which this document was retrieved - preferredMcpAuthentication: oauth2 - paths: - bootstrap: /llms.txt - manifest: /docs/agent-manifest.json - mcp: /api/mcp - protectedResourceMetadata: /.well-known/oauth-protected-resource - authorizationServerMetadata: /.well-known/oauth-authorization-server - publicClient: token_endpoint_auth_method=none, pkce=S256 - verify: initialize -> tools/list -> get_capabilities Resolve each path on the selected host against the actual retrieval URL, never a hardcoded host or another domain, and never a guessed callback: const docsUrl = new URL(documentResponse.url); const mcpUrl = new URL(connection.paths.mcp, docsUrl). - Register a public client at the advertised registration_endpoint with the host's own real registered callback; no client secret (token_endpoint_auth_method=none). Authorize with the authorization-code grant, a fresh random state, and PKCE S256; the resource parameter equals the discovered MCP resource: the resolved MCP URL (connection.paths.mcp). - Validate field ownership: the protected-resource metadata's resource equals the resolved mcpUrl.href (the MCP URL ending in /api/mcp, never the bare origin) and its authorization_servers names the selected authorization server, whose issuer is that same service origin; the authorization-server metadata's issuer equals the selected service origin (never the resource URI path). Discover the real authorization_endpoint, token_endpoint, and registration_endpoint from that issuer-bound server. - The user signs in and approves the requested scopes. Business access requires an organization-bound credential; no-organization personal identity is not available on this endpoint. Manifest tools[].scopes and the scope inventory are supported, not granted scopes; only get_capabilities proves the real granted scopes, the organization, and setup state. - Missing scope, compact recovery: an eligible OAuth actor receives the standard HTTP 403 insufficient_scope and may begin a NEW, explicit, user-approved consent from the exact tool metadata; the optional hint is not required. Role-ineligible or inactive actors remain plain refusals with no promised automatic privilege. An API key is replaced only by a new, appropriately scoped key minted by an authorized owner/admin and stored in masked settings, a vault, or the environment, never widened silently, and never pasted into chat. Direct REST stays API-key-only; an OAuth access token is an MCP credential. Host setup: use a host that supports remote MCP and interactive OAuth. Sign in, choose your organization, approve the requested scopes, and call get_capabilities to confirm access. A link cannot install or authorize a host connection. - Give your agent this documentation link. A host that can make HTTP requests and can add an MCP connection with OAuth can read this document and start a connection; you do not need to manually mint an API key, and reading this document requires no JavaScript, cookies, login, screenshot, private vendor instruction, or document read key. A documentation link cannot give a host a capability or connection UI it lacks; it must report that limitation rather than claim to connect. - Connect with OAuth for the supported self-service MCP flow: this server publishes protected-resource metadata at the MCP origin, supports dynamic client registration, and requires the authorization-code grant with PKCE S256 (a public client, token_endpoint_auth_method=none). The user signs in, chooses the organization the credential is bound to, and approves the requested scopes on a consent screen. No manually supplied client secret is required. - A host that cannot present an API key and cannot run this OAuth flow must report that constraint; do not look for an API-key field the host does not offer, and do not treat a supplied screenshot or vendor-specific private instruction as a requirement of this protocol. Some hosts require their own connection UI. - Send exactly one JSON-RPC message per POST to the resolved MCP URL (connection.paths.mcp). JSON-RPC batch arrays are not supported, including singleton arrays and requests combined with notifications. The server is stateless: GET and DELETE return 405. - After the host performs its token handling, initialize, complete the normal SDK initialization notification if applicable, then call tools/list, then call the get_capabilities tool with {}. It reads the real granted scopes, the organization binding, and whether setup is complete; never fabricate confirmation. - Direct REST access is API-key-only: an OAuth access token is an MCP credential and is not a direct credential for the versioned API. Read the public OpenAPI document at https://www.campaigncommanderapp.com/openapi.json for the full HTTP surface. ## Documents - [Human API docs](https://www.campaigncommanderapp.com/docs/api) - [Public OpenAPI 3.1 document](https://www.campaigncommanderapp.com/openapi.json) - [Full agent reference](https://www.campaigncommanderapp.com/llms-full.txt) - [Structured agent manifest](https://www.campaigncommanderapp.com/docs/agent-manifest.json) - [MCP endpoint](https://www.campaigncommanderapp.com/api/mcp) ## Workflows - `billing-read`: Billing: inspect funds and transaction history. Read funds, ledger history and existing Auto Top-Up configuration without initiating a payment or changing settings. - `billing-configure`: Billing: configure existing Auto Top-Up. Change an explicitly requested replenishment configuration, then read the persisted settings back. This is not a deposit or card-entry workflow. - `connect`: Connect and discover capabilities. Authenticate, then read exactly what this credential may do before doing anything else. Nothing here changes data. - `setup-repair`: Inspect and repair organization setup. Read the sender and organization settings, show the exact missing fields, and save a complete packet so sends are accepted. - `personal-profile`: Personal profile and preferences. Read and change the credential owner's OWN personal profile and preferences: name, personal phone, time zone, country, sender defaults, SMS signature, quiet hours, opt-in preferences, and notification preferences. The effect is user-wide: these settings belong to the person across every organization they belong to. - `audience`: Build and confirm an audience. Find or create contacts, resolve a natural-language audience to a saved list, size it, and snapshot its membership. Everything here is free and reversible. - `email`: Email: draft, test, send, report. Build an email piece, verify the audience and cost, send one proof, send or schedule the live campaign, then read recipients and delivery events back. - `sms`: SMS: readiness, draft, send, report. Check texting readiness, draft a text or MMS, preview the audience, send one proof, send or schedule, then read recipients, events, and outcomes. - `transactional`: Transactional email and templates. Manage reusable transactional templates, then send a one-off system email. Templates are a save, not a send; the send is a confirm-gated paid action. - `brand-registration`: Texting brand registration: preview, optional approval, submit, status. Read the stored brand filing state, preview a would-be packet, optionally route it through the configured approval policy, submit the paid filing, and read the status back. - `campaign-registration-readiness`: Texting campaign registration: read readiness and run the free site preflight. Read the stored campaign-registration state, save a compliance draft, and run the free website-compliance preflight. Paid campaign filing is available through submit_texting_campaign_registration. - `mail`: Physical mail: draft, preview, launch. Create a physical-mail piece with base64 artwork, size the audience, launch the campaign, and read its status. Mail is the one channel that cannot be recalled. - `voice`: Voice and the power dialer. Prepare voice assets and campaigns, place calls, and run the operator-first power dialer. Readiness (a voice-enabled number and the operator's personal phone) is required before the first call. - `contact-import`: Import a contact or suppression file. Upload one or more CSV/XLSX workbooks, preview what will change, answer every uncertain decision, commit, and read the persisted counts and per-row outcomes back. Nothing is imported by parsing a file alone; the commit is the mutation. - `form-intake`: Website form intake: record a submission and read the receipt back. Record a website form submission as a contact through the same consent and suppression engine the website endpoint uses, then read the persisted receipt back by the external id. Nothing is sent and nothing is charged. - `team-roster`: Team: read the roster and current pending invitations. Read the authorized organization's team roster and its CURRENT pending invitations without making changes. To invite, re-queue, or cancel an invitation, or to manage an ordinary member, use the team-management workflow. - `contact-fields`: Contact fields: discover the registry and pin a field's type. Read the organization's contact-field registry and, when a field should be typed, save an explicit key/label/type definition and read it back. A definition save changes field metadata only; it does not convert, clear, or repair any stored value. - `team-management`: Team: read the roster and manage invitations and ordinary members. Read the authorized organization's roster and current pending invitations, then invite, re-queue, or cancel an invitation, or change, suspend, reactivate, or remove an ordinary (non-owner) member, with each management action read back from the live state. This is ordinary owner/admin authority inside the credential's organization; the organization owner is never a target. Inventory: 134 MCP tools, 154 public API operations, 18 workflows. ## Known limitations - Campaign (texting) registration: Reading the stored campaign-registration readiness and running the free website-compliance preflight are available through get_texting_campaign_registration and check_texting_campaign_site. Paid campaign filing is available through submit_texting_campaign_registration (POST /api/v1/registration/campaign/submit) when the credential holds registration:submit and the active organization owner has completed setup. An uncertain carrier outcome is never retried blindly. - Member and team management: An authorized owner/admin credential can read the organization's roster and its CURRENT pending invitations through list_team_members and list_team_invitations (scope team:read, owner/admin only), and can invite, re-queue, and cancel a team invitation and change, suspend, reactivate, or remove an ordinary (non-owner) member through a narrow set of team:manage tools and /api/v1/team operations. The management surface is ordinary organization authority only: the organization owner cannot be acted on, self-actions are refused, promotion to owner is refused, the last active admin cannot be suspended or removed, and platform is_admin alone is not authority. An invitation write queues a source email event, which is NOT proof of delivery. Two gaps remain: an invitee's own identity-plane actions (accepting, previewing, or dismissing their own invitation) and the credential lifecycle (creating, listing, rotating, or revoking API keys and OAuth connected apps) still have no tool and stay in the signed-in product. Do not present invitee-side acceptance or credential management as a runnable step. - Credentials and connected apps: Creating, listing, rotating, or revoking API keys and OAuth connected apps has no tool. A key is minted and revoked by a signed-in owner in Account Settings. - Sending domain and DNS configuration: Reading an organization's sending-domain authentication state, previewing a configuration, and creating, rechecking, or resuming the domain identity are available through get_sending_domain, preview_sending_domain, and configure_sending_domain and the versioned /api/v1/communications/sending-domain operations. The Agent API returns the exact DNS records an owned domain requires. Publishing those records at the customer's own DNS host stays with the customer, and provider-hosted DNS changes, domain deletion or detach, and custom MAIL FROM are out of scope. Do not present MAIL FROM as configured. - Funding and payment-method management: Balance and ledger reads and existing Auto Top-Up configuration are available through billing tools. Adding or removing a payment method, initiating a deposit, and recording an offline payment have no tool. Card entry stays in the secure payment interface, never in a chat or tool argument. - Calling execution, media, and reach: A member's connected agent can read the prepared calling queues it may work and save the member's own operator phone (calls:read and calls:operate). Placing, advancing, media, or billing a call, buying or provisioning a number, and the full personal-settings, key-management, and account portals remain unavailable to a member credential and stay in the signed-in product. Do not present starting, advancing, or billing a call as a runnable step for a member connection. - Phone numbers and defaults: Purchasing a toll-free or local number and setting the organization's default campaign phone are available through purchase_phone_number and set_default_phone_number. Local numbers are automatically attached to the organization's current 10DLC campaign when one is approved. - Import list cleaning: A commit never cleans and never charges. Cleaning exactly the contacts a single import saved is a SEPARATE, bounded paid step: clean_import_cohort acts on the cohortId a preview-backed commit returns and on nothing else, so a file's cleaning permission never triggers a whole-organization run. A commit that asks for cleaning reports the channels as REQUESTED and NOT PERFORMED by the commit. An import that is not preview-backed captures no cohort, so there is nothing for the cohort-scoped step to act on. - Large import files and staged uploads: An MCP contact import travels base64-encoded inside one JSON-RPC body, and the request body cap is 4.5 MB, so the inline aggregate is bound near 2.6 MiB decoded. A larger file can be sent in bounded chunks with stage_contact_import_upload, which stores the bytes and returns a durable staging id. Pass that staging_id to preview_contact_import or commit_contact_import in a JSON body to import the staged file. The dashboard multipart import and the multipart REST route remain available for callers that prefer them. - Form-intake write atomicity: A website form submission commits its contact mutation and its stored receipt in a single serialized transaction per organization. It checks for an existing same-key receipt before mutating, re-validates the prepared contact and email/phone matches at commit time, and writes the receipt in the same transaction. A same-key concurrent duplicate commits a single mutation and replays the first winner's receipt, and a receipt failure rolls the contact write back. A stored receipt records the outcome of the first accepted write, not proof that the current contact still matches that request, as later edits can update the contact. After an interrupted keyed request, read the stored receipt for that external_id before retrying. Submissions without an external_id perform the contact action without deduplication or replay. - Member and volunteer delegated credentials: Operational portal credentials require an active owner or admin membership in the organization, matching the dashboard's access boundary. Eligible owners and admins can read and update their own personal profile and preferences, which apply across every organization they belong to. Members with calling access can use OAuth calling-workspace tools (calls:read and calls:operate), while broader member or volunteer credential delegation is not available. Do not present general member or volunteer operational access as available. - Contact-field value typing and advanced filter parity: An agent can DISCOVER the contact-field registry (list_contact_fields) and SAVE an explicit key/label/type definition (upsert_contact_field), and the versioned route GET|PUT /api/v1/contacts/fields backs both. But saving a definition changes field METADATA only: it does NOT convert, clear, or repair any contact's stored value, and it does not change a stored value's type; a value that no longer matches the new type keeps its stored text. Writing a TYPED field VALUE onto a contact, and the advanced typed-filter surface (typed operators such as gt/gte/lt/lte/neq/contains over typed values), still have no tool and no Agent API operation. Only the flat text/number custom-value write on create_contact/update_contact is available. Do not present a definition save as a value conversion, and do not present registry discovery or a definition save as advanced filter parity. - Connect through a host that supports remote MCP and OAuth 2.1. Sign in, choose your organization, and approve the requested scopes. After initialization and tool discovery, call get_capabilities to confirm your organization, granted scopes, and setup state. Configure the host connection once; tool access depends on your current role and granted scopes. - The self-service MCP connection uses OAuth authorization-code flow with PKCE S256 and public-client registration (token_endpoint_auth_method=none). No manually supplied client secret or manually minted API key is required. Use the host's connection settings to complete sign-in and consent. - Business access requires an organization-bound credential and eligible membership. Follow each tool's role, scope, setup, billing, and confirmation requirements; connecting does not grant additional permissions or complete business setup. - An authorized owner/admin credential can read the organization roster and current pending invitations and manage ordinary (non-owner) team members. An invitee's own identity-plane actions and credential lifecycle actions (creating, listing, rotating, or revoking API keys and OAuth connected apps) have no MCP tool. Billing balance, ledger and existing Auto Top-Up configuration tools are available. Consult each capability gap for its remaining limitation. - A registered texting brand alone is not SMS campaign approval or full texting readiness. Reading the stored campaign-registration readiness and running the free website-compliance preflight are available through get_texting_campaign_registration and check_texting_campaign_site; paid campaign filing is available through submit_texting_campaign_registration when the credential holds registration:submit. Check get_sms_readiness before treating a brand as ready to text. - For hosts that support API-key authentication, configure an existing valid Campaign Commander API key only in the host's secret settings, vault or environment. Hosts that require OAuth should use the MCP OAuth connection flow; no API-key entry field is assumed. Never paste a credential into chat or a tool argument, and do not treat an unauthenticated 401 as proof that an account is disconnected. - A campaign registration's already_filed flag means a carrier campaign reference is recorded, not approval, delivery, or a charge, and a missing reference does not prove the carrier received nothing. confirmation_required or submitting mean an existing attempt must not be filed again; reconcile it with support. None of these flags establish whether a review fee was charged, so a missing carrier identity is never permission to submit. - Each tool publishes its complete required scope set. An eligible active/full-access OAuth actor missing an in-role scope receives the standard HTTP 403 insufficient-scope challenge and may receive an optional matching tool-result hint. The host must support interactive OAuth reauthorization to request new, explicit, user-approved consent; use its connection settings if it does not start that flow automatically. Security policy is published in _meta.securitySchemes, not a top-level securitySchemes field; hosts that require the top-level field must support this metadata location to use it.