# Tanso MCP Integration > Tanso is a monetization engine for B2B SaaS. It handles pricing, feature entitlements, > usage metering, billing, and margin analytics — all from a single platform. Define your > plans and features once, then let Tanso enforce access, track consumption, generate > invoices, and compute per-customer gross margin automatically. > > For the full REST API and product documentation, see the companion file: llms.txt --- ## Connection & Authentication Protocol: Streamable HTTP (MCP) Auth: API key via `X-API-Key` header (same key used for the REST API) Prerequisite: MCP must be enabled on the Tanso instance (`app.mcp.enabled=true`) | Environment | Endpoint | |-------------|---------------------------------------| | Production | `https://api.tansohq.com/mcp` | | Sandbox | `https://sandbox.api.tansohq.com/mcp` | ### Sample MCP client config ```json { "mcpServers": { "tanso": { "url": "https://api.tansohq.com/mcp", "headers": { "X-API-Key": "sk_live_your_api_key_here" } } } } ``` The server identifies itself as `tanso-mcp`. No additional handshake or session management is required — each tool call is independently authenticated. --- ## Concepts Quick Reference | Concept | Description | |----------------|-----------------------------------------------------------------------------| | Feature | A single capability your product offers (e.g. `api_access`, `ai_messages`) | | Plan | A bundle of features with pricing (e.g. "Pro Tier — $99/mo") | | Customer | A billing entity identified by an external reference ID from your system | | Subscription | Links a customer to a plan; manages billing periods and entitlements | | Event | A usage record (e.g. "API call made") that drives metering and billing | | Entitlement | A customer's right to use a feature, derived from their active subscription | | Invoice | A billing document generated per cycle; statuses: PENDING, DUE, PAID, PAST_DUE, VOID | | Credit Pool | A prepaid balance a customer can draw down against for metered features | --- ## Tool Reference Tanso exposes 34 tools across 7 categories. They are grouped below by access level. ### Read-Only Tools (13) These tools retrieve data and have no side effects. #### Plans **listPlans** List all active plans with their pricing and linked features. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | *(none)* | — | — | — | **listFeatures** List all features defined in your account. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | *(none)* | — | — | — | **getFeature** Get details for a single feature by its unique key. | Parameter | Type | Required | Description | |------------|--------|----------|------------------------------------------------------| | featureKey | string | yes | The unique feature key, e.g. `api_access` | #### Customers **getCustomer** Get customer details by their external reference ID. Returns name, email, active subscriptions, and credit pools. | Parameter | Type | Required | Description | |---------------------|--------|----------|----------------------------------------------------------| | customerReferenceId | string | yes | The customer's external reference ID (your system's ID) | #### Entitlements **checkEntitlement** Check if a customer has access to a specific feature. Returns whether access is allowed, the usage limit, current usage, and remaining quota. | Parameter | Type | Required | Description | |---------------------|--------|----------|----------------------------------------------------------| | customerReferenceId | string | yes | The customer's external reference ID | | featureKey | string | yes | The feature key to check, e.g. `api_access` | **listCustomerEntitlements** List all entitlements for a customer. Returns every feature the customer has access to, along with usage limits and current consumption. | Parameter | Type | Required | Description | |---------------------|--------|----------|----------------------------------------------------------| | customerReferenceId | string | yes | The customer's external reference ID | **evaluateEntitlement** Simulate an entitlement check with optional usage context. Records a zero-usage audit event but does NOT consume actual usage. Use this to check if proposed usage would be allowed before ingesting a real event. | Parameter | Type | Required | Description | |---------------------|--------|----------|----------------------------------------------------------| | customerReferenceId | string | yes | The customer's external reference ID | | featureKey | string | yes | The feature key to evaluate | | requestedUsage | string | no | Number of usage units to simulate, e.g. `100` | #### Billing **listCustomerInvoices** List all invoices for a customer. Returns invoice dates, amounts, status (PENDING, DUE, PAID, PAST_DUE, VOID), and line items. | Parameter | Type | Required | Description | |---------------------|--------|----------|----------------------------------------------------------| | customerReferenceId | string | yes | The customer's external reference ID | #### Credits **getCreditPools** List all credit pools for a customer. Returns each pool's name, total credits, used credits, and remaining balance. | Parameter | Type | Required | Description | |---------------------|--------|----------|----------------------------------------------------------| | customerReferenceId | string | yes | The customer's external reference ID | **getCreditBalance** Get the balance of a specific credit pool. | Parameter | Type | Required | Description | |---------------------|--------|----------|----------------------------------------------------------| | customerReferenceId | string | yes | The customer's external reference ID | | poolId | string | yes | The credit pool ID | #### Stripe Integration **getStripeIntegrationStatus** Returns the current Stripe integration status for the account. Shows whether an API key is registered, whether a webhook exists, the current Stripe mode, and currency. Call this first to determine which setup steps remain. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | *(none)* | — | — | — | Returns: `{ hasApiKey, maskedApiKey, hasWebhook, maskedWebhookSecret, stripeMode, stripeEnabled, currency, setupComplete }` **discoverStripeData** Discovers existing data in the connected Stripe account. Lists products, customers, and subscriptions from Stripe and shows which items are already mapped to Tanso entities. Use this to preview what will be imported before running `importStripeData`. Pre-check: A Stripe API key must be registered. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | *(none)* | — | — | — | Returns: Lists of `DiscoveredProduct` (name, id, alreadyMapped), `DiscoveredCustomer` (name, email, id, alreadyMapped), and `DiscoveredSubscription` (id, customerId, productId, status, alreadyMapped). **getStripeImportStatus** Checks the status of a Stripe import job by its ID. Returns progress details including total, processed, and failed item counts. | Parameter | Type | Required | Description | |-----------|--------|----------|----------------------------------------------------------| | jobId | string | yes | The import job ID (UUID format) | --- ### Write Tools (4) These tools create or modify data. They have side effects noted in each description. #### Customers **createCustomer** Creates a new customer in your billing system. This permanently creates a customer record. | Parameter | Type | Required | Description | |--------------------------|--------|----------|----------------------------------------------------| | customerReferenceId | string | yes | A unique reference ID for this customer, e.g. `user_abc123` | | email | string | yes | Customer's email address | | firstName | string | no | Customer's first name | | lastName | string | no | Customer's last name | **updateCustomer** Updates an existing customer's details. Only provided fields are updated; omitted fields remain unchanged. | Parameter | Type | Required | Description | |---------------------|--------|----------|----------------------------------------------------------| | customerReferenceId | string | yes | The customer's external reference ID | | firstName | string | no | New first name | | lastName | string | no | New last name | | email | string | no | New email address | | phoneNumber | string | no | New phone number | #### Subscriptions **createSubscription** Creates a subscription for a customer on a specific plan. The plan must be in ACTIVE status. Generates the first invoice. For IN_ADVANCE plans, entitlements are granted after invoice payment. For IN_ARREARS plans, entitlements are granted immediately. | Parameter | Type | Required | Description | |---------------------|--------|----------|----------------------------------------------------------| | customerReferenceId | string | yes | The customer's external reference ID | | planId | string | yes | The plan ID to subscribe to (use `listPlans` to find IDs)| #### Events **ingestEvent** Ingests a usage event for billing and metering. Records usage that affects billing calculations and entitlement limits. Events are idempotent — sending the same idempotency key twice will be rejected. | Parameter | Type | Required | Description | |---------------------|--------|----------|----------------------------------------------------------| | eventIdempotencyKey | string | yes | Unique key to prevent duplicates, e.g. `evt_abc123` | | eventName | string | yes | Name of the event, e.g. `api_call` | | occurredAt | string | yes | ISO-8601 timestamp, e.g. `2026-03-16T10:30:00Z` | | customerReferenceId | string | yes | The customer's external reference ID | | featureKey | string | yes | The feature key this event is tracked against | | usageUnits | string | no | Number of usage units consumed (defaults to `1`) | --- ### Sensitive Tools (6) — require `confirmAction: true` These tools perform destructive or financially significant operations. You MUST pass `confirmAction: true` to execute them. If `confirmAction` is `false` or omitted, the tool returns a `confirmation_required` error without performing the action. #### Subscriptions **cancelSubscription** Cancels a customer's subscription. This will end the customer's access to plan features. | Parameter | Type | Required | Description | |---------------|---------|----------|----------------------------------------------------------| | subscriptionId| string | yes | The subscription ID to cancel | | cancelMode | string | no | `END_OF_PERIOD` (default, graceful) or `IMMEDIATE` | | confirmAction | boolean | yes | Must be `true` to execute | **changeSubscriptionPlan** Changes a customer's subscription to a different plan. Upgrades take effect immediately with prorated billing. Downgrades are scheduled for the end of the current billing period. | Parameter | Type | Required | Description | |---------------|---------|----------|----------------------------------------------------------| | subscriptionId| string | yes | The subscription ID to change | | newPlanId | string | yes | The new plan ID to switch to | | changeType | string | yes | `UPGRADE` (immediate) or `DOWNGRADE` (end of period) | | confirmAction | boolean | yes | Must be `true` to execute | #### Billing **markInvoicePaid** Marks an invoice as paid. Updates the invoice status and may trigger Stripe synchronization. Use this for manual payment reconciliation. | Parameter | Type | Required | Description | |---------------|---------|----------|----------------------------------------------------------| | invoiceId | string | yes | The invoice ID to mark as paid | | confirmAction | boolean | yes | Must be `true` to execute | #### Stripe Integration **registerStripeApiKey** Registers a Stripe API key for the account. If a key already exists, deletes the old one first. The key must start with `sk_test_` or `sk_live_`. | Parameter | Type | Required | Description | |---------------|---------|----------|----------------------------------------------------------| | stripeApiKey | string | yes | The Stripe secret API key (starts with `sk_test_` or `sk_live_`) | | confirmAction | boolean | yes | Must be `true` to execute | **setupStripeIntegration** Sets up the full Stripe integration: creates a webhook endpoint and switches mode to STRIPE_DRIVEN. Idempotent — skips webhook if already registered, skips mode switch if already STRIPE_DRIVEN. The webhook creation implicitly validates the API key (Stripe API call will fail if key is bad). Pre-check: an API key must already be registered. | Parameter | Type | Required | Description | |---------------|---------|----------|----------------------------------------------------------| | confirmAction | boolean | yes | Must be `true` to execute | Returns: `{ success, webhookCreated, modeChanged, stripeMode }` **importStripeData** Imports Stripe data by auto-creating Tanso Plans, Features, Customers, and Subscriptions from the connected Stripe account. Skips items already mapped. Pre-check: A Stripe API key must be registered. Warns if Stripe mode is not STRIPE_DRIVEN. | Parameter | Type | Required | Description | |---------------|---------|----------|----------------------------------------------------------| | confirmAction | boolean | yes | Must be `true` to execute | Returns: `{ jobId, status, totalItems, processedItems, failedItems, errorDetails? }` --- ### Admin Read-Only Tools (2) These tools retrieve catalog data for administrative purposes. #### Features **adminListFeatures** List all features in the account with their IDs, names, keys, descriptions, and enabled status. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | *(none)* | — | — | — | #### Plans **adminListPlans** List all plans in the account with their IDs, keys, names, prices, billing intervals, and statuses. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | *(none)* | — | — | — | --- ### Admin Write Tools (8) These tools create or modify catalog data. They have side effects noted in each description. #### Features **adminCreateFeature** Creates a new feature in the product catalog. | Parameter | Type | Required | Description | |-------------|--------|----------|--------------------------------------------------| | name | string | yes | Display name, e.g. `API Access` | | key | string | yes | Unique key, e.g. `api_access` | | description | string | no | Description of the feature | **adminUpdateFeature** Updates an existing feature. Only provided fields are changed. Constraint: The `key` must remain unique within the account. | Parameter | Type | Required | Description | |-------------|---------|----------|--------------------------------------------------| | featureId | string | yes | The feature ID (UUID) | | name | string | no | New display name | | key | string | no | New unique key | | description | string | no | New description | | isEnabled | boolean | no | Enable or disable the feature | #### Plans **adminCreatePlan** Creates a new plan in the product catalog. New plans start in DRAFT status. To activate, set status to ACTIVE via `adminUpdatePlan` (requires name, description, priceAmount, intervalMonths, and at least one linked feature). | Parameter | Type | Required | Description | |----------------|--------|----------|------------------------------------------------------| | key | string | yes | Unique key, e.g. `pro_tier` | | name | string | yes | Display name, e.g. `Pro Tier` | | priceAmount | string | yes | Base price amount, e.g. `99.00` | | description | string | no | Description of the plan | | intervalMonths | string | no | Billing interval in months (default: `1`) | | billingTiming | string | no | `IN_ADVANCE` (default) or `IN_ARREARS` | **adminUpdatePlan** Updates an existing plan. Only provided fields are changed. Constraints: Once a plan is ACTIVE, `key`, `priceAmount`, `intervalMonths`, and `billingTiming` are locked and cannot be changed. ARCHIVED plans only allow status changes (back to ACTIVE). All fields are mutable while the plan is in DRAFT. | Parameter | Type | Required | Description | |----------------|--------|----------|------------------------------------------------------| | planId | string | yes | The plan ID (UUID) | | key | string | no | New unique key | | name | string | no | New display name | | priceAmount | string | no | New base price amount | | description | string | no | New description | | intervalMonths | string | no | New billing interval in months | | billingTiming | string | no | `IN_ADVANCE` or `IN_ARREARS` | | status | string | no | `DRAFT`, `ACTIVE`, or `ARCHIVED`. Allowed transitions: DRAFT→ACTIVE (requires name, description, priceAmount, intervalMonths, ≥1 linked feature), ACTIVE→ARCHIVED, ARCHIVED→ACTIVE. | **adminGetPlanWithFeatures** Get a plan's full details including all linked features and credit allocations. | Parameter | Type | Required | Description | |-----------|--------|----------|------------------------------------------------------| | planId | string | yes | The plan ID (UUID) | #### Plan-Feature Rules **adminGetFeatureRule** Get the pricing/cost rule for a plan-feature link. | Parameter | Type | Required | Description | |-----------|--------|----------|------------------------------------------------------| | planId | string | yes | The plan ID (UUID) | | featureId | string | yes | The feature ID (UUID) | **adminLinkFeatureToPlan** Links a feature to a plan with optional pricing rules. The `valueJson` parameter accepts a JSON string with **nested** pricing and cost config. Omit `valueJson` entirely for a boolean (on/off) gate. **Format:** `{"pricing": {}, "cost": {}}` **Pricing models** (inside `"pricing"` key): *Flat-rate* (`model: "usage"`): | Field | Type | Required | Default | Description | |------------------|--------|----------|------------|------------------------------------------------| | `model` | string | yes | — | Must be `"usage"` | | `usage_unit_type`| string | yes | — | Unit label, e.g. `"api_calls"`, `"messages"` | | `price_per_unit` | number | yes | — | Price charged per usage unit | | `max_usage` | number | no | *(none)* | Usage cap; must be ≥ 0 | | `reset_mode` | string | no | `"reset"` | `"reset"` (zero each cycle) or `"accumulate"` (carry over) | *Graduated / Tiered* (`model: "graduated"`): | Field | Type | Required | Default | Description | |------------------|--------|----------|------------|------------------------------------------------| | `model` | string | yes | — | Must be `"graduated"` | | `usage_unit_type`| string | yes | — | Unit label, e.g. `"api_calls"` | | `tiers` | array | yes | — | At least one tier object (see below) | | `max_usage` | number | no | *(none)* | Usage cap; must be ≥ 0 | | `reset_mode` | string | no | `"reset"` | `"reset"` or `"accumulate"` | Each tier object: | Field | Type | Required | Description | |------------------|----------------|----------|------------------------------------------| | `up_to` | number or `"inf"` | yes | Upper bound of this tier | | `price_per_unit` | number | yes | Price per unit in this tier; must be ≥ 0 | | `flat_fee` | number | no | Fixed fee added when this tier is entered; must be ≥ 0 | **Cost models** (inside `"cost"` key, optional — for internal margin analysis): *Simple* (`model: "simple"`): | Field | Type | Required | Default | Description | |------------------|--------|----------|--------------|------------------------------------------| | `model` | string | yes | — | Must be `"simple"` | | `cost_per_unit` | number | yes | — | Internal cost per usage unit; must be ≥ 0| | `cost_unit` | string | no | `"CURRENCY"` | `"TOKENS"`, `"CREDITS"`, or `"CURRENCY"` | *Model-aware* (`model: "model_aware"`): | Field | Type | Required | Default | Description | |-----------------------|--------|----------|--------------|----------------------------------------------------| | `model` | string | yes | — | Must be `"model_aware"` | | `default_cost_per_unit`| number| yes | — | Fallback cost per unit when model is not in map | | `model_costs` | object | yes | — | Map of model name → cost per unit, e.g. `{"gpt-4": 0.00006}` | | `cost_unit` | string | no | `"CURRENCY"` | `"TOKENS"`, `"CREDITS"`, or `"CURRENCY"` | **Examples:** - Boolean gate: omit `valueJson` - Flat-rate with cap: `{"pricing":{"model":"usage","price_per_unit":0.10,"usage_unit_type":"api_calls","max_usage":10000}}` - Graduated with flat fees and accumulation: `{"pricing":{"model":"graduated","usage_unit_type":"api_calls","reset_mode":"accumulate","tiers":[{"up_to":100,"price_per_unit":0.10,"flat_fee":5.00},{"up_to":"inf","price_per_unit":0.05}]}}` - Flat-rate with simple cost: `{"pricing":{"model":"usage","price_per_unit":0.10,"usage_unit_type":"api_calls"},"cost":{"model":"simple","cost_per_unit":0.03,"cost_unit":"CURRENCY"}}` - Flat-rate with model-aware cost: `{"pricing":{"model":"usage","price_per_unit":0.01,"usage_unit_type":"api_calls"},"cost":{"model":"model_aware","default_cost_per_unit":0.00003,"model_costs":{"gpt-4":0.00006,"claude-3-opus":0.000075},"cost_unit":"CURRENCY"}}` > Legacy flat format (cost fields mixed into the pricing object) is also accepted and normalized to nested format on save. | Parameter | Type | Required | Description | |-----------|---------|----------|------------------------------------------------------| | planId | string | yes | The plan ID (UUID) | | featureId | string | yes | The feature ID (UUID) | | type | string | no | Rule type. Must be `BASE`. Omit valueJson for a boolean (on/off) gate; provide valueJson with a pricing model for metered billing. | | valueJson | string | no | JSON string with pricing model config (see schemas above) | | isEnabled | boolean | no | Whether the rule is enabled (default: true) | **adminUpdateFeatureRule** Updates an existing plan-feature rule. Only provided fields are changed. | Parameter | Type | Required | Description | |-----------|---------|----------|------------------------------------------------------| | planId | string | yes | The plan ID (UUID) | | featureId | string | yes | The feature ID (UUID) | | type | string | no | Rule type. Must be `BASE` if provided. | | valueJson | string | no | JSON string with updated pricing model config | | isEnabled | boolean | no | Enable or disable the rule | --- ### Admin Sensitive Tools (1) — require `confirmAction: true` These tools perform destructive catalog operations. You MUST pass `confirmAction: true` to execute them. If `confirmAction` is `false` or omitted, the tool returns a `confirmation_required` error without performing the action. #### Plan-Feature Rules **adminUnlinkFeatureFromPlan** Removes a feature from a plan by deleting the plan-feature rule. | Parameter | Type | Required | Description | |---------------|---------|----------|--------------------------------------------------| | planId | string | yes | The plan ID (UUID) | | featureId | string | yes | The feature ID (UUID) | | confirmAction | boolean | yes | Must be `true` to execute | --- ## Confirmation Pattern Seven tools (`cancelSubscription`, `changeSubscriptionPlan`, `markInvoicePaid`, `adminUnlinkFeatureFromPlan`, `registerStripeApiKey`, `setupStripeIntegration`, `importStripeData`) require an explicit `confirmAction: true` parameter. This guard exists to prevent AI agents from accidentally performing irreversible financial, access-control, catalog, or integration operations. If you call a sensitive tool with `confirmAction: false` (or omit it), you will receive: ```json {"error": "confirmation_required", "message": "Set confirmAction to true to execute this destructive action"} ``` The action is NOT performed. Retry the same call with `confirmAction: true` to proceed. --- ## Common Agent Workflows ### Look up a customer's status 1. `getCustomer(customerReferenceId)` — retrieve profile, subscriptions, and credit pools 2. `checkEntitlement(customerReferenceId, featureKey)` — verify access to a specific feature 3. `listCustomerInvoices(customerReferenceId)` — review billing history ### Onboard a new customer 1. `listPlans()` — find the plan ID to subscribe the customer to 2. `createCustomer(customerReferenceId, email)` — register the customer 3. `createSubscription(customerReferenceId, planId)` — activate the subscription ### Record usage 1. `checkEntitlement(customerReferenceId, featureKey)` — confirm the customer has quota remaining 2. `ingestEvent(eventIdempotencyKey, eventName, occurredAt, customerReferenceId, featureKey)` — record the usage ### Simulate usage before committing 1. `evaluateEntitlement(customerReferenceId, featureKey, requestedUsage)` — check if the proposed usage would be allowed 2. If allowed, proceed with `ingestEvent` ### Change or cancel a subscription 1. `getCustomer(customerReferenceId)` — confirm the customer and their current subscription 2. `changeSubscriptionPlan(subscriptionId, newPlanId, changeType, confirmAction: true)` — upgrade or downgrade 3. Or: `cancelSubscription(subscriptionId, cancelMode, confirmAction: true)` — cancel ### Check credit balance 1. `getCreditPools(customerReferenceId)` — list all pools and their balances 2. `getCreditBalance(customerReferenceId, poolId)` — drill into a specific pool ### Set up a product catalog 1. `adminCreateFeature(name, key)` — create each feature (repeat for all features) 2. `adminCreatePlan(key, name, priceAmount)` — create the plan (starts in DRAFT) 3. `adminLinkFeatureToPlan(planId, featureId, type: "BASE", valueJson)` — link each feature with pricing rules (repeat for all features) 4. `adminUpdatePlan(planId, status: "ACTIVE")` — activate the plan (requires name, description, priceAmount, intervalMonths, ≥1 linked feature) 5. `adminGetPlanWithFeatures(planId)` — verify the complete plan configuration ### Connect Stripe and import data 1. `getStripeIntegrationStatus()` — check current state (API key, webhook, mode) 2. `registerStripeApiKey(stripeApiKey, confirmAction: true)` — store the Stripe secret key 3. `setupStripeIntegration(confirmAction: true)` — create webhook + switch to STRIPE_DRIVEN mode 4. `discoverStripeData()` — preview products, customers, and subscriptions in Stripe 5. `importStripeData(confirmAction: true)` — auto-create Tanso entities from Stripe data 6. `getStripeImportStatus(jobId)` — verify the import completed successfully --- ## Error Handling All tools return JSON. On failure, the response shape is: ```json {"error": "", "message": ""} ``` | Error Type | Meaning | |-------------------------|------------------------------------------------------------| | `not_found` | The referenced customer, feature, subscription, or invoice does not exist | | `invalid_request` | A parameter is malformed or a business rule was violated | | `serialization_error` | Internal error serializing the response | | `confirmation_required` | A sensitive tool was called without `confirmAction: true` | | `precondition_failed` | A prerequisite is not met (e.g. no Stripe API key registered) | | `stripe_api_error` | A Stripe API call failed (invalid key, network error, etc.) | | `duplicate_event` | An event with the given idempotency key already exists | | `ingestion_failed` | The event could not be processed | On success, write tools return `{"success": true}` or `{"success": true, "message": "..."}`. Read tools return the requested data as JSON objects or arrays.