AI Agents

MCP Server

The Bear Lumen MCP server exposes your AI cost intelligence as tools an AI agent can call. Connect it to Claude Desktop, Cursor, or Claude Code and ask about spend, margins, and usage in plain language.

What it is

@bearlumen/mcp-server is a Model Context Protocol server: a small program your MCP client launches over stdio. It wraps the Bear Lumen API and offers read-only tools across costs, margins, insights, usage, and attribution, every one of them listed below. Everything is scoped to the account that owns the configured API key, and nothing it exposes can modify your data.

The same server also runs as a hosted remote MCP server for agents that do not run on your machine, authenticated with OAuth instead of a pasted key.

Prerequisites

  • Node.js 20 or newer. The server wraps @bearlumen/node-sdk, which signs requests with WebCrypto and declares engines.node >= 20.
  • A Bear Lumen API key with the four read scopes below. Create one at app.bearlumen.com/developer/api-keys and select the CLI and MCP (read-only) preset. If you already use the CLI, bearlumen login creates a key with the same scopes.

For version pinning, upgrades, and uninstalling, see the install guide.

Required scopes

Every tool needs one of the four read scopes. A key that is missing one still connects, and the ping tool then reports which scopes are absent so the agent can tell you which preset to select. A key with only usage:write is an SDK ingestion key: it can send events and cannot read anything, so no tool will work with it.

ScopeGrantsNeeded by
costs:readCost summaries, breakdowns, trends, and per-run session trees.get_cost_*, get_costs_by_*, get_session_tree, get_insights_summary
revenue:readMargin and profitability analysis.get_margin_*, get_margins_by_end_user
usage:readRecorded usage events and aggregations.get_usage_summary, get_usage_events
dimensions:readCustom dimension definitions.list_dimensions, get_costs_by_dimension

The authentication guide covers the full scope catalog, key expiry, and rotation.

Configuration

The server reads BEARLUMEN_API_KEY (required) and, optionally, BEARLUMEN_BASE_URL to point at a non-production host. The older BEAR_LUMEN_* spellings are deprecated: still read, but scheduled for removal.

Every block below pins @bearlumen/[email protected]. An unpinned npx -y re-resolves the newest version on each launch, which means a future release would change your tools without you choosing it. Upgrading is editing the pinned version.

Claude Desktop

Add this to claude_desktop_config.json and restart the app:

JSON
{
  "mcpServers": {
    "bear-lumen": {
      "command": "npx",
      "args": ["-y", "@bearlumen/[email protected]"],
      "env": {
        "BEARLUMEN_API_KEY": "your-api-key-here"
      }
    }
  }
}

Cursor

Use the same JSON block in ~/.cursor/mcp.json (global) or .cursor/mcp.json (per project).

Claude Code

bash
claude mcp add bear-lumen \
  --env BEARLUMEN_API_KEY=your-api-key-here \
  -- npx -y @bearlumen/mcp-server@0.3.0

Any MCP client

Run the server directly over stdio:

BEARLUMEN_API_KEY=your-api-key-here npx -y @bearlumen/mcp-server@0.3.0

Remote MCP server (for deployed agents)

When the agent runs somewhere you cannot set an environment variable (a hosted Claude Desktop connector, a team workspace, an agent platform), connect to the hosted server at https://mcp.bearlumen.com/mcp instead of launching one locally. It speaks Streamable HTTP, is stateless, and exposes the same tools as the stdio server, and it never holds a shared key: every request carries the caller's own credential.

Client configuration

In Claude Code:

claude mcp add --transport http bear-lumen https://mcp.bearlumen.com/mcp

In Claude Desktop, add it under Settings, Connectors, as a custom connector with that URL. Clients that take a JSON config use the HTTP shape:

JSON
{
  "mcpServers": {
    "bear-lumen": {
      "type": "http",
      "url": "https://mcp.bearlumen.com/mcp"
    }
  }
}

The first tool call returns 401 with a WWW-Authenticate header, and an MCP client that supports OAuth follows it: a browser window opens on https://app.staging.bearlumen.com/oauth/authorize, you sign in if you are not already, review the four read scopes, and approve. That creates an API key in your account named after the client, which you can see and revoke on the API Keys page like any other. It expires after 30 days; the client re-runs the flow when it does.

OAuth discovery

The remote server is an OAuth resource server and publishes where its authorization server lives, so a client needs nothing but the URL:

JSON
GET https://mcp.bearlumen.com/.well-known/oauth-protected-resource

{
  "resource": "https://mcp.bearlumen.com",
  "authorization_servers": ["https://api.bearlumen.com"],
  "bearer_methods_supported": ["header"],
  "scopes_supported": ["costs:read", "revenue:read", "usage:read", "dimensions:read"],
  "resource_name": "Bear Lumen"
}

The authorization server metadata is at https://api.staging.bearlumen.com/.well-known/oauth-authorization-server. Clients register themselves dynamically (public clients, no secret), must use PKCE with S256, and receive a bearer token that is an ordinary sk_live_ API key. Requests without a valid token get 401 plus the WWW-Authenticate header that points back at the discovery document above; a key that is missing a scope gets 403 with error="insufficient_scope". The authentication guide describes the flow in full.

You can also run this HTTP mode yourself: the package ships a second binary, bear-lumen-mcp-http. Its configuration is documented under "Running as a remote server" in the package README on npm.

Deployed agents without MCP

An agent you build in code does not need MCP to read cost data. The Node and Python SDKs expose every tool below as a method, so a deployed agent can call them directly with a read-only key from the environment:

TypeScript
import { BearLumen, getBearLumen } from '@bearlumen/node-sdk';

// Reads BEARLUMEN_API_KEY from the environment: a key created with the
// "CLI and MCP (read-only)" preset, so it can read and cannot send events.
BearLumen.init();
const bear = getBearLumen();

const summary = await bear.costs.summary({ timeWindow: 'last-30-days' });
const byModel = await bear.costs.byModel({ lastDays: 30 });
const losing = (await bear.margins.byEndUser({ lastDays: 30 })).end_users
  .filter((u) => u.margin_amount < 0);
Python
import bearlumen

# Reads BEARLUMEN_API_KEY from the environment: a key created with the
# "CLI and MCP (read-only)" preset, so it can read and cannot send events.
bearlumen.init()
bear = bearlumen.get_client()

summary = bear.costs.summary(time_window="last-30-days")
by_model = bear.costs.by_model(last_days=30)
losing = [u for u in bear.margins.by_end_user(last_days=30)["end_users"]
          if u["margin_amount"] < 0]

The Reading costs reference lists every read method in both languages.

The tools

Once connected, the agent can call any of these. Every date-windowed tool accepts start_date / end_date as ISO YYYY-MM-DD and defaults to the trailing 30 days when omitted.

  • ping: verify the key and connectivity, and report the organization, key name, environment (live or test), granted scopes, and expiry. The tool description tells the agent to compare the scopes against the four above and to name the CLI and MCP (read-only) preset when one is missing.
  • get_cost_summary: total spend now vs the previous period.
  • get_cost_trend: cost over time.
  • get_costs_by_model, get_costs_by_provider, get_costs_by_feature, get_costs_by_end_user: cost broken down by that axis.
  • get_costs_by_outcome: cost per declared outcome, with completed, failed, and unresolved units side by side, plus the cost of one completed unit.
  • get_costs_by_dimension: cost grouped by any axis, including agent, workflow, or a custom metadata key.
  • get_session_tree: the call tree for one run, with own and subtree cost per span, so you can see which branch spent the money. It takes a session_id rather than a date window.
  • get_margin_summary, get_margins_by_end_user, get_margin_trend: revenue vs cost and profitability.
  • get_insights_summary: a digest of top movers and outliers.
  • get_usage_summary, get_usage_events: usage volume and raw events.
  • list_dimensions: the custom dimensions you can group by.

Teaching your agent to use it

The package ships a SKILL.md file that documents when and how to use each tool: the date conventions, the difference between your own user IDs and Bear Lumen's internal IDs, how a null cost differs from a real zero, which scopes the key needs, and worked examples such as "find our unprofitable customers." Give it to your agent as a skill or in its system prompt for the best results.

Prefer a terminal?

The Bear Lumen CLI exposes the same query surface as command-line commands, with a one-to-one mapping to these tools.