Skip to main content

Disclosed sponsored slots for MCP servers and AI agent tools. Ships data, never directives. Fail-open by design.

Project description

lulu-ads

Monetize your MCP server or agent tool with one labeled sponsored line.

Lulu Ads attaches a disclosed, labeled data field to your tool responses. The host model (Claude, Cursor, any agent) decides on its own judgment whether it's relevant enough to surface — we never instruct a model to display anything. If it renders and gets clicked, you earn 70% on CPA. If it doesn't — nobody pays, nothing breaks.

Zero-friction start (MCP)

Add the Lulu Ads MCP server and ask your agent to do the rest:

claude mcp add --transport http lulu-ads https://ads.getlulu.dev/mcp

Then just say:

monetize my server

The agent will fetch the right integration guide for your stack, register a publisher (with your consent), wire up the one-liner below, and verify it produced a live slot.

Quickstart (Python)

pip install lulu-ads
# pip install lulu-ads
from lulu_ads import LuluAds
ads = LuluAds(publisher_id="pub_123", api_key="lk_...")

result = search_flights("TLV", "BKK", dates)
result["sponsored"] = await ads.sponsored_slot(
    context={"tool": "search_flights", "category": "travel.flights"},
    timeout_ms=150,
)
return result

One line for FastMCP servers — credentials come from the environment, the call itself takes no arguments:

export LULU_ADS_PUBLISHER_ID=pub_123
export LULU_ADS_API_KEY=lk_...
mcp.add_middleware(LuluAdsMiddleware())

Quickstart (TypeScript)

npm install @getlulu/ads
// npm install @getlulu/ads
import { LuluAds } from "@getlulu/ads";
const ads = new LuluAds({ publisherId: "pub_123", apiKey: "lk_..." });
result.sponsored = await ads.sponsoredSlot({ context: { tool: "search_flights" } });

Guarantees (enforced in code, not just promised)

Guarantee How
A tool call can never break because of ads every failure path returns None/null; hard 150ms timeout
Always disclosed label: "Sponsored" is set by the SDK and cannot be removed
No prompt injection, ever we ship a data field; there is no display instruction anywhere
No PII leaves your server context accepts an allowlisted key set only
Quality-gated every creative passes Dali scoring (≥70) before it can fill a slot
Intent, not identity targeting uses the session's stated intent; no user profiles exist
Misconfigured? Still safe missing creds → client is inert, returns nothing, never crashes

Framework adapters

Full details, exclude-lists, and every supported stack: docs/integrations.md.

LangGraph / LangChain (langchain>=1.0) — middleware, no manual attach step:

from langchain.agents import create_agent
from lulu_ads.integrations.langchain import LuluAdsAgentMiddleware

agent = create_agent(model, tools, middleware=[LuluAdsAgentMiddleware()])

CrewAI (crewai>=1.9.1) — one call at startup, before you kick off a crew:

import lulu_ads.integrations.crewai as lulu_crewai
lulu_crewai.install()

TypeScript MCP servers — wrap the server once, before registering tools:

import { withLuluAds } from "@getlulu/ads";
withLuluAds(server);

Runtime owners (chat bots, WhatsApp/Telegram agents, anything that owns the final message the user sees) — append a disclosed suffix after generation, as harness code, never as a model instruction:

from lulu_ads import format_suffix
final_message = model_output + format_suffix(sponsored)

Get a publisher ID

Three ways:

  • Ask an MCP-connected agent to call the create_publisher tool on https://ads.getlulu.dev/mcp
  • Early beta signup: https://getlulu.dev/publishers
  • POST https://ads.getlulu.dev/publishers with {"name", "contact_email", "server_url"}

See docs/quickstart.md for the full walkthrough and docs/contract.md for the wire-level API.

Docs: https://getlulu.dev/docs · Built by Lulu · Quality gate: Dali

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lulu_ads-0.1.0.tar.gz (8.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lulu_ads-0.1.0-py3-none-any.whl (8.9 kB view details)

Uploaded Python 3

File details

Details for the file lulu_ads-0.1.0.tar.gz.

File metadata

  • Download URL: lulu_ads-0.1.0.tar.gz
  • Upload date:
  • Size: 8.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for lulu_ads-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f33d635be97f54dae138d700d8ce5debaf93c23afc37b772b6b3ec7b9d2a7491
MD5 2296a11a46f9691e8451eefe1d6c6f12
BLAKE2b-256 140ca9bb84bfe5cdd7eee66d4ddb4517b4c8a0e25db12ae7bdd413ca6a7edcd1

See more details on using hashes here.

File details

Details for the file lulu_ads-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: lulu_ads-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 8.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for lulu_ads-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0cb633d5aad8b59217c890309928b3fa0c6eefa741dfdbfe2913842818e0228b
MD5 4f27a07b1a2bcfef3b44ed5a2ff5ab1d
BLAKE2b-256 52112e86c0ac7f885ddb57c5fbc66929b6f6ccb3b0398b1031a867c7ae3c0e33

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page