# MarginFront MCP Integration — Complete Reference > Usage-based billing for AI agent companies. The MCP server lets AI coding assistants (Claude Code, Cursor, VS Code, etc.) manage your MarginFront account in plain English — track events, query costs, manage customers, and debug billing issues. ## Connection Details **Transport:** stdio (runs locally via npx) **Auth:** API key via MF_API_SECRET_KEY environment variable **API Base:** MF_API_BASE_URL (default: https://api.marginfront.com/v1) **npm package:** @marginfront/mcp ## Setup ### Claude Code Add to `.mcp.json` in your project root: ```json { "mcpServers": { "marginfront": { "command": "npx", "args": ["-y", "@marginfront/mcp"], "env": { "MF_API_SECRET_KEY": "mf_sk_your_key_here" } } } } ``` ### Claude Desktop Add to `claude_desktop_config.json`: ```json { "mcpServers": { "marginfront": { "command": "npx", "args": ["-y", "@marginfront/mcp"], "env": { "MF_API_SECRET_KEY": "mf_sk_your_key_here" } } } } ``` ### Cursor Add to `.cursor/mcp.json` in your project root: ```json { "mcpServers": { "marginfront": { "command": "npx", "args": ["-y", "@marginfront/mcp"], "env": { "MF_API_SECRET_KEY": "mf_sk_your_key_here" } } } } ``` ### VS Code / Windsurf / Codex Add to `.vscode/mcp.json` (note: `servers` not `mcpServers`): ```json { "servers": { "marginfront": { "command": "npx", "args": ["-y", "@marginfront/mcp"], "env": { "MF_API_SECRET_KEY": "mf_sk_your_key_here" } } } } ``` ## Core Concepts - **Agent**: Your AI product (e.g., a support bot, research assistant). Has an agentCode used in events. - **Customer**: Who you're billing. Has an externalId matching your system's user ID. - **Signal**: What you measure — a deliverable or outcome (e.g., "messages", "reports-generated"). NOT internal API calls. - **Event**: A record that agent X did Y quantity of signal Z for customer W. Carries model/provider for cost calculation. - **Pricing Plan**: How much you charge per unit of each signal. - **Subscription**: Links a customer to an agent via a pricing plan. Defines billing cycle. - **Invoice**: Auto-generated from subscriptions. ## Required Event Fields Every usage event requires these 5 fields: - **customerExternalId** (string) — your customer's ID in your system (e.g., "acme-001") - **agentCode** (string) — your agent's code from the dashboard (e.g., "cs-bot") - **signalName** (string) — the metric being tracked (e.g., "messages", "reports") - **model** (string) — model identifier (e.g., "gpt-4o", "claude-sonnet-4", "twilio-sms") - **modelProvider** (string) — provider name, lowercase (e.g., "openai", "anthropic", "twilio") ### For LLM events, also include: - **inputTokens** (number) — prompt / input tokens - **outputTokens** (number) — completion / output tokens ### For non-LLM or variable-quantity events: - **quantity** (number, default: 1) — numeric count (pages, SMS, minutes, etc.) ### Optional: - **usageDate** (string, ISO 8601) — when the event happened, defaults to now - **metadata** (object) — free-form key-value pairs, stored but not used for billing ## Tool Catalog (13 tools) ### Read-Only Tools #### verify Check that the API key is valid and see which organization it belongs to. - Parameters: none - Returns: organization name, verified status - Use when: first connecting, to confirm setup works #### list_customers List your customers with optional search and pagination. - Parameters: - page (number, optional, default: 1) - limit (number, optional, 1-100, default: 20) - search (string, optional) — search by name or external ID - Returns: customer names, IDs, status #### get_customer Get detailed info about a single customer by their MarginFront UUID. - Parameters: - customerId (string, required) — the MarginFront UUID, NOT the externalId - Returns: full customer details including subscriptions and metadata #### list_invoices List invoices with optional filters. - Parameters: - status (string, optional) — "draft", "pending", "paid", "overdue", or "void" - customerId (string, optional) — filter by customer UUID - page (number, optional, default: 1) - limit (number, optional, 1-100, default: 20) - Returns: invoice status, amounts, customer details #### get_invoice Get detailed info about a single invoice. - Parameters: - invoiceId (string, required) — invoice UUID - Returns: full invoice with line items and payment history #### list_events List usage events with optional filters. - Parameters: - page (number, optional, default: 1) - limit (number, optional, 1-100, default: 20) - customerId (string, optional) — filter by customer UUID - agentId (string, optional) — filter by agent UUID - signalId (string, optional) — filter by signal UUID - startDate (string, optional) — ISO 8601 date, events after this - endDate (string, optional) — ISO 8601 date, events before this - Returns: model, tokens, cost, customer, timestamp for each event #### get_usage_analytics Get aggregated usage analytics for a date range. - Parameters: - startDate (string, required) — ISO 8601 start date (e.g., "2026-04-01") - endDate (string, required) — ISO 8601 end date (e.g., "2026-04-13") - groupBy (string, optional) — "agent", "customer", "signal", "model", or "day" - Returns: summary (totals, unique counts) + time-series data #### list_subscriptions List customer subscriptions. - Parameters: - status (string, optional) — "active", "canceled", "past_due", or "trialing" - customerId (string, optional) — filter by customer UUID - page (number, optional, default: 1) - limit (number, optional, 1-100, default: 20) - Returns: status, plan details, billing dates ### Write Tools #### record_usage Record a single usage event. - Parameters: - customerExternalId (string, required) - agentCode (string, required) - signalName (string, required) - model (string, required) - modelProvider (string, required) - inputTokens (number, optional) — for LLM events - outputTokens (number, optional) — for LLM events - quantity (number, optional, default: 1) — for non-LLM or variable-quantity events - usageDate (string, optional) — ISO 8601, defaults to now - metadata (object, optional) — free-form key-value pairs - Returns: event ID, calculated cost, timestamp - Note: for LLM events pass tokens; for non-LLM (SMS, scraping) pass quantity #### record_usage_batch Record multiple usage events at once (1-100 per request). - Parameters: - records (array, required, 1-100 items) — each item has same fields as record_usage - Returns: batch result with success/failure counts and per-record status - Note: can mix LLM and non-LLM events in the same batch #### create_customer Create a new customer in MarginFront. - Parameters: - name (string, required) — customer's display name - externalId (string, optional) — your system's ID for this customer - email (string, optional) - phone (string, optional) - Returns: created customer with MarginFront UUID - Note: set externalId so you can reference it in usage events ### Diagnostic Tool #### get_needs_attention List usage events where the model+provider combination isn't in the pricing table. These events are saved with cost = null. - Parameters: - startDate (string, optional, default: 30 days ago) - endDate (string, optional, default: now) - Returns: groups by model and provider with event counts - Important: events ARE saved (not lost). Use map_model to fix, then costs backfill automatically. Do NOT re-send the events. ### Destructive Tool #### map_model Map an unknown model to a known one in the pricing table and backfill costs for all affected events. Creates a permanent mapping — future events with the same source model auto-resolve. - Parameters (identify target by ID or by model+provider pair): - sourceModel (string, required) — unknown model name to map FROM - sourceProvider (string, required) — unknown provider to map FROM - targetPricingId (string, optional) — UUID of target pricing row to map TO - targetModel (string, optional) — known model name to map TO (use with targetProvider) - targetProvider (string, optional) — known provider to map TO (use with targetModel) - Returns: confirmation with number of events backfilled and mapping ID - Idempotent: yes (safe to retry) - Note: this creates a permanent org-scoped mapping. It does NOT modify the global pricing table. ## Common Workflows ### 1. Verify Connection Prompt: "Verify my MarginFront connection" Tools: verify Expected: organization name and "verified: true" ### 2. Explore Customers Prompt: "Show me my MarginFront customers" Tools: list_customers → get_customer (for details on a specific one) ### 3. Record a Single LLM Event Prompt: "Record a usage event: customer acme-001 used the cs-bot agent, signal messages, model gpt-4o from openai, 500 input tokens, 120 output tokens" Tools: record_usage Fields: customerExternalId=acme-001, agentCode=cs-bot, signalName=messages, model=gpt-4o, modelProvider=openai, inputTokens=500, outputTokens=120 ### 4. Record a Non-LLM Event Prompt: "Record an event: customer acme-001 used cs-bot, signal sms-sent, model sms-send from twilio, quantity 1" Tools: record_usage Fields: customerExternalId=acme-001, agentCode=cs-bot, signalName=sms-sent, model=sms-send, modelProvider=twilio, quantity=1 ### 5. Record a Batch of Events Prompt: "Record 3 events for customer acme-001 on cs-bot: 2 messages on gpt-4o and 1 SMS on twilio" Tools: record_usage_batch ### 6. Check What Needs Attention Prompt: "Are there any MarginFront events with unknown models?" Tools: get_needs_attention Follow-up: if results found, use map_model to create a mapping ### 7. Fix Unknown Models Prompt: "Map the model 'gpt-4o-2024-08-06' from 'openai' to the known model 'gpt-4o' from 'openai'" Tools: map_model Result: creates permanent mapping, backfills costs on all affected events ### 8. Get Usage Analytics Prompt: "Show me MarginFront usage analytics for this month" Tools: get_usage_analytics with startDate=2026-04-01 and endDate=2026-04-13 ### 9. Check Invoices Prompt: "Show me all pending invoices" Tools: list_invoices with status=pending ### 10. Golden Path Setup (via MCP prompts) Step 1: "Create a MarginFront customer called Acme Inc with external ID acme-001" Step 2: "Record a test event for customer acme-001 on agent cs-bot, signal messages, model gpt-4o from openai, 100 input tokens, 50 output tokens" Step 3: "Show me the usage analytics for today" Note: Agents, signals, pricing plans, and subscriptions are typically created through the dashboard UI, not through MCP. MCP is best for: recording events, querying data, debugging cost issues, and creating customers. ## Error Types - **Authentication error (401)**: API key is invalid or expired. Check MF_API_SECRET_KEY env var. - **Not found (404)**: The resource (customer, invoice, etc.) doesn't exist. Check the UUID. - **Validation error (400)**: A required field is missing or invalid. The error message says which field. - **Signal not found**: The signalName doesn't match any signal created for the agent. Check spelling and whitespace. - **NEEDS_COST_BACKFILL**: The model+provider wasn't recognized. Event IS saved with cost=null. Use get_needs_attention then map_model to fix. - **Rate limit (429)**: Too many requests. Wait and retry. Success responses return data objects. Failures return `{ error: "message" }`. ## Important: Never Break the Core Product MarginFront instrumentation must never prevent the host application from running. If MarginFront is unreachable or returns an error, the AI agent must continue functioning. When recording events via MCP: - If record_usage fails, log the error and move on - Events with unrecognized models are saved with cost=null (not dropped) - Use get_needs_attention to find and fix these later