{
  "serverInfo": {
    "name": "usage-lab",
    "title": "Usage Lab",
    "version": "0.1.0",
    "description": "Usage metering for AI and SaaS: idempotent usage events, meters and monthly per-customer rollups.",
    "websiteUrl": "https://usage-lab.pages.dev/docs/mcp/"
  },
  "transport": {
    "type": "streamable-http",
    "url": "https://usage-lab.pages.dev/mcp"
  },
  "protocolVersions": [
    "2026-07-28",
    "2025-11-25",
    "2025-06-18",
    "2025-03-26"
  ],
  "authentication": {
    "required": false,
    "schemes": [
      "bearer"
    ],
    "description": "Your own Usage Lab API key as Authorization: Bearer <key>; needed for account tools only. Free key: https://usage-lab.pages.dev/signup/"
  },
  "tools": [
    {
      "name": "get_docs",
      "title": "Usage Lab quickstart",
      "description": "Quickstart for the Usage Lab metering API and this MCP server: how to get a free API key, connect, create a meter, record idempotent usage events and read rollups. No API key needed.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "annotations": {
        "title": "Usage Lab quickstart",
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "list_meters",
      "title": "List meters",
      "description": "List the meters on your Usage Lab account (key, name, aggregation sum | count | unique_count). Needs your API key (Authorization: Bearer).",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "annotations": {
        "title": "List meters",
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "create_meter",
      "title": "Create a meter",
      "description": "Create a meter once (POST /api/v1/meters). aggregation: sum (add up value, e.g. tokens), count (number of events, e.g. tool calls) or unique_count (distinct unique_value, e.g. active users). Re-creating an existing key returns meter_exists (harmless). Free plan: 3 meters. Needs your API key.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,63}$",
            "description": "1-64 chars of letters, digits, _ . - (e.g. agent_tool_calls)."
          },
          "aggregation": {
            "type": "string",
            "enum": [
              "sum",
              "count",
              "unique_count"
            ]
          },
          "name": {
            "type": "string",
            "description": "Optional display name (defaults to key)."
          },
          "stripe_event_name": {
            "type": "string",
            "description": "Optional Stripe Billing Meter event_name for Stripe push (Pro/Ultra)."
          }
        },
        "required": [
          "key",
          "aggregation"
        ]
      },
      "annotations": {
        "title": "Create a meter",
        "readOnlyHint": false,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "record_usage_events",
      "title": "Record usage events",
      "description": "Record 1-100 usage events in one all-or-nothing batch (POST /api/v1/usage). Every event MUST carry its own idempotency_key; retrying with the same keys is safe (results say created / duplicate / conflict). Needs your API key.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "events": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": {
              "type": "object",
              "properties": {
                "idempotency_key": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 255,
                  "description": "Required. A stable id for this event (e.g. sha256 of run_id:step:tool_call_id, or your provider response id). Reuse it on retries: same key + same payload returns duplicate and counts once; same key + different payload is a conflict and the original is kept."
                },
                "meter": {
                  "type": "string",
                  "description": "Meter key or id. Optional only if the account has exactly one meter."
                },
                "subscription": {
                  "type": "string",
                  "maxLength": 200,
                  "description": "Required. Your customer or subscription id (who to bill)."
                },
                "value": {
                  "type": "number",
                  "description": "Required for sum meters (e.g. tokens). Defaults to 1 for count meters."
                },
                "unique_value": {
                  "type": [
                    "string",
                    "number"
                  ],
                  "description": "Required for unique_count meters (e.g. a user id)."
                },
                "timestamp": {
                  "type": [
                    "string",
                    "number"
                  ],
                  "description": "ISO-8601 or unix seconds/ms. Defaults to now. Max 30 days old, max 5 minutes in the future."
                },
                "properties": {
                  "type": "object",
                  "description": "Optional JSON stored with the event, e.g. {\"traffic_class\":\"ai_agent\",\"tool\":\"search\"}."
                }
              },
              "required": [
                "idempotency_key",
                "subscription"
              ]
            }
          }
        },
        "required": [
          "events"
        ]
      },
      "annotations": {
        "title": "Record usage events",
        "readOnlyHint": false,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "get_meter_rollups",
      "title": "Get monthly rollups",
      "description": "Monthly totals per customer for one meter, recomputed from raw events (GET /api/v1/meters/{meter}/rollups). Returns total_quantity and per-subscription quantity and event_count. Needs your API key.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "meter": {
            "type": "string",
            "description": "Meter key or id."
          },
          "month": {
            "type": "string",
            "pattern": "^\\d{4}-(0[1-9]|1[0-2])$",
            "description": "YYYY-MM (UTC). Defaults to the current month."
          },
          "subscription": {
            "type": "string",
            "description": "Optional: only this customer/subscription."
          }
        },
        "required": [
          "meter"
        ]
      },
      "annotations": {
        "title": "Get monthly rollups",
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "get_account",
      "title": "Get account",
      "description": "Your account: plan, event and meter limits, event_count and first_event_at (GET /api/v1/account). Needs your API key.",
      "inputSchema": {
        "type": "object",
        "properties": {}
      },
      "annotations": {
        "title": "Get account",
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    }
  ],
  "resources": [],
  "prompts": [],
  "serverCard": "https://usage-lab.pages.dev/mcp/server-card"
}