Boost BossDocs
Docs/Integration doors/MCP server

Lumi SDK for MCP

Add three lines to any MCP tool handler. Sponsored content gets appended to your tool's response and rendered natively by the MCP host (Claude Desktop, Cursor, Cline, Continue, Zed, Windsurf). Time to first ad: under 10 minutes.

★ Start hereUpdated Jun 2026·4 min read
v0.1 — beta. Integrate over HTTP today; the npm wrapper is being republished.

The Boost Boss MCP backend is live. Integrate by calling it directly over HTTP from your MCP tool handler (see Direct integration below) — it works end-to-end against the sandbox with publisherId: "pub_test_demo" and apiKey: "sk_test_demo", no signup required. The @boostbossai/lumi-mcp convenience wrapper (the LumiMCP class shown further down) is temporarily unpublished and being re-released; until it's back, use the direct call — it's only a few lines. The full demand side (real advertiser inventory) is in early beta; expect lower fill rates than mature ad networks until our Founding Publisher cohort fills out. Email info@boostboss.ai to join.

Prerequisites

  • A Boost Boss publisher account — sign up if you haven't.
  • An MCP server that exposes at least one tool. @modelcontextprotocol/sdk ≥ 1.0 supported; older MCP server libraries work but aren't actively tested.
  • Node.js ≥ 18 (or any runtime that supports fetch).
  • Bearer token from your publisher dashboard (settings → API keys).

Direct integration (works today)

Call the Boost Boss MCP endpoint from inside your MCP server's tool handler and fold the sponsored result into your tool's response. No package required — any runtime with fetch.

// Inside your MCP tool handler:
const res = await fetch('https://boostboss.ai/api/mcp', {
  method:  'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    jsonrpc: '2.0', id: 1, method: 'tools/call',
    params: {
      name: 'get_sponsored_content',
      arguments: {
        context_summary:   'user is deploying a Node.js API',   // the live intent
        format_preference: 'native',                           // native | image | video | any
        publisher_id:      process.env.BBX_PUBLISHER_ID,        // 'pub_test_demo' for sandbox
        developer_api_key: process.env.BBX_API_KEY,             // 'sk_test_demo' for sandbox
        session_id:        sessionId,
        host_app:          'my-mcp-server',
        surface:           'mcp',
      },
    },
  }),
});
const json    = await res.json();
const payload = JSON.parse(json.result.content[0].text);
if (payload.sponsored) {
  // Append one line to your tool response, e.g.:
  // `${payload.sponsored.disclosure}: ${payload.sponsored.headline} — ${payload.sponsored.cta_url}`
}

The @boostbossai/lumi-mcp wrapper (the LumiMCP class in the examples below) is being republished — until it's back, the direct call above is the supported path.

Initialization

import { LumiMCP } from '@boostbossai/lumi-mcp';

const lumi = new LumiMCP({
  publisherId: process.env.BBX_PUBLISHER_ID,
  apiKey:      process.env.BBX_API_KEY,
  transport:   'stdio',        // 'stdio' | 'http' (auto-detect by default)
  debug:       false             // log every ad request to stderr
});
OptionTypeRequiredDescription
publisherIdstringyesYour pub_xxx identifier from the dashboard.
apiKeystringyesBearer token. Keep server-side; never embed in client code.
transport"stdio" | "http"noAuto-detected from your MCP server config. Override only if you need to.
debugbooleannoLogs every fetchAd call and response to stderr. Default: false.
timeoutMsnumbernoNetwork timeout per request. Default: 2500.

Core API

lumi.fetchAd(opts)

Fetches a sponsored content payload contextually matched to opts.context. Returns null if no fill (no advertiser matched, frequency cap hit, etc.) — your tool should still return its primary output normally.

const ad = await lumi.fetchAd({
  context:   'stripe customer creation',  // the user's intent or tool topic
  placement: 'citation',                 // 'card' | 'citation' | 'toolrec'
  toolName:  request.params.name             // optional, used for analytics
});

if (!ad) {
  return { content: result };               // no fill — return primary output only
}

Parameters

FieldTypeRequiredDescription
contextstringyesFree text that describes what the user is doing. Used for contextual matching.
placementstringnoMCP placement: card (inline sponsored card), citation (sponsored source), or toolrec (tool/skill recommendation). Default: "card".
formatstringnoPreferred ad format. Default: "native".
toolNamestringnoName of the MCP tool being called. Improves analytics.
userRegionstringnoISO region (US, EU, APAC). If omitted, inferred from request.

ad.toMCPBlock()

Converts the ad payload to an MCP content block ready to append to your tool's content array. Handles disclosure label, image rendering, and click-tracking link transparently.

return {
  content: [
    ...result,
    ad.toMCPBlock()       // appends a sponsored block, never replaces
  ]
};

lumi.trackImpression(ad)

Fires the impression beacon. Called automatically by toMCPBlock() — only invoke manually if you're using a custom rendering path.

lumi.trackClick(ad)

Fires the click beacon. The click URL embedded in toMCPBlock() already redirects through Boost Boss for tracking — only invoke manually if you build your own link.

lumi.trackConversion(ad, conversion)

Fires a conversion event tied to a previously-served ad. Use when the user takes the action your campaign was bidding on (signup, purchase, tool invoke, lead). The conversion shares the auction context with the original impression so attribution and CPA billing work end-to-end.

// Inside any tool handler, after the user completes the desired action:
await lumi.trackConversion(ad, {
  type:       "signup",        // matches campaigns.conversion_event_types
  value:      29.99,             // USD; optional but required for ROAS
  currency:   "USD",          // ISO 4217; defaults to USD
  externalId: "order_98123",  // optional — your CRM/order id
});

Fire-and-forget — never throws. Failures emit an error event on the SDK and are surfaced via the silent-failure observability endpoint (/api/stats?type=recon).

Rendering the ad

You don't render anything yourself. toMCPBlock() returns a structured MCP content block, and the host (Claude Desktop, Cursor, etc.) renders it natively in whatever style fits its UI. The block looks roughly like this on the wire:

{
  "type": "text",
  "text": "\n\n— Sponsored —\nStripe Atlas helps you launch a US company...",
  "_meta": {
    "boostboss": { "impressionId": "imp_...", "adId": "ad_..." }
  }
}
Disclosure is non-negotiable.

The "— Sponsored —" prefix is part of every block. toMCPBlock() bakes it in; do not remove it. Stripping the disclosure is a policy violation that suspends Credit earning.

Event handling

The MCP integration is server-side, so there's no onClick/onClose like the JS snippet — clicks are tracked via redirect URL, impressions via the toMCPBlock() render. If you want server-side hooks for analytics:

lumi.on('impression', ({ adId, advertiserId, cpm }) => {
  metrics.increment('lumi.impressions');
});

lumi.on('no_fill', ({ context }) => {
  console.debug('no fill for context:', context);
});

lumi.on('error', ({ code, message }) => {
  metrics.increment('lumi.errors', { code });
});

Error handling

fetchAd() never throws on the bid path — network failures, timeouts, and policy rejections all resolve to null. Your tool's primary output is never delayed by Lumi.

Error codeMeaningWhat to do
BBX_AUTHInvalid or revoked API keyCheck dashboard → API keys; rotate if compromised.
BBX_RATE_LIMIT1k requests/minute exceededEmail support@boostboss.ai for a higher cap.
BBX_TIMEOUTNetwork or upstream timeoutNo-op; ad just won't render. Lumi never blocks your tool response.
BBX_NO_FILLNo matching advertiserExpected sometimes; not an error condition.
BBX_POLICYContent matched a policy blockCheck dashboard → policy audit log for the rule that fired.

Testing

Use a sandbox publisher ID in development — every ad request gets a fixed test creative back, no real demand-side calls happen, and impressions never accrue revenue.

const lumi = new LumiMCP({
  publisherId: 'pub_test_demo',
  apiKey:      'sk_test_demo',
  debug:       true
});

The sandbox always returns a creative (no null), so you can exercise toMCPBlock() rendering paths reliably. Switch to your live publisher ID + API key before going to production.

Going live

Production checklist before flipping to live keys:

  • Replace sandbox publisherId and apiKey with the live values from your dashboard.
  • Set debug: false for production — avoids stderr noise on cold start.
  • Run one live tool call end-to-end and verify the impression appears in your dashboard within 30 seconds.
  • Optional: email info@boostboss.ai with the MCP server's listing URL so we can add it to our supply-side allowlist — speeds up advertiser approvals. Self-serve seller submission via the dashboard is on the roadmap; for now this is a manual step.

Troubleshooting

fetchAd always returns null.

Check three things in order: (1) is your apiKey live (not sk_test_) when expecting real fills, (2) does the context string have any actual content (empty contexts get auto-rejected), (3) check the dashboard policy audit log — your account may be in review.

The host doesn't render the sponsored block.

Some MCP hosts collapse adjacent text blocks. If toMCPBlock() output is concatenated into your tool's text, the host may render it as one long string. Add a separator block ({ type: 'separator' } on supported hosts) between your output and the ad, or return them as distinct content array entries.

Disclosure label appears in a different language than my user.

Pass userLanguage to fetchAd — Lumi serves disclosure in 40+ languages but defaults to en.

I'm getting BBX_RATE_LIMIT at low volume.

The 1k/minute cap is per-publisher; if you're behind a load balancer with many MCP server instances, all share the same cap. Email support to raise.

I want to disable Lumi for a specific tool.

Just don't call fetchAd in that tool's handler. Lumi is opt-in per tool; nothing is auto-injected.

Changelog

See the API reference changelog for SDK release notes and protocol changes.