SkillAgentSearch skills...

lulu-ads

Monetize MCP servers and AI agent tools with disclosed sponsored slots. Ships data, never directives. Fail-open by design.

Install / Use

claude mcp add Lulu-The-Narwhal -- npx -y github:Lulu-The-Narwhal/lulu-ads

If the server publishes to npm under a different name, use that package instead — check the repo README.

About this skill
🔌

MCP Server

Model Context Protocol server

Quality Score

74/100

Category

Marketing

Supported Platforms

Claude Code
Claude Desktop
<div align="center">

lulu-ads

The monetization layer for the agent economy.

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

PyPI npm License: MIT Backend Publisher beta Rev share Lulu MCPs

Quickstart · Integrations · Supported hosts · Supported surfaces · stdio servers · Guarantees · API contract · Hosted docs · Blog · Become a publisher

<img src="https://raw.githubusercontent.com/Lulu-The-Narwhal/lulu-ads/master/assets/lulu-ads-hero.jpg" alt="Lulu, the Lulu Ads narwhal mascot, celebrating on a Tel Aviv billboard — the agent economy has a monetization layer now" width="640" />

70% to publishers · CPA only · 800ms fail-open · 0 prompt injections, by design

Sponsored <br><sub>↑ live rendered sponsor card — real rotating ad demand, refreshes every ~60s. Any claimed listing can embed this in its own README.</sub>

</div>

Lulu Ads attaches a disclosed, labeled data field to your tool's own result. The host model — Claude, Cursor, any agent — decides on its own judgment whether it's relevant enough to surface. We never instruct it to.

<table> <tr> <th>What the SDK ships (a data field)</th> <th>What the host renders (its choice)</th> </tr> <tr> <td>
{
  "sponsored": {
    "label": "Sponsored",
    "text": "Direct flights TLV–BKK from $412",
    "url": "https://ads.getlulu.dev/c/9f2a1c"
  }
}
</td> <td>

Sponsored — Direct flights TLV–BKK from $412 ads.getlulu.dev/c/9f2a1c

</td> </tr> </table>

Zero-friction start — add the MCP server and let your agent do the rest:

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

monetize my server

It'll fetch the right integration guide for your stack, register a publisher (with your consent), wire up the one-liner, and verify a slot went live.

If it renders and gets clicked, you earn 70% on CPA. If it doesn't — nobody pays, nothing breaks.

No prompt injection — we ship a data field; the host decides.

Quickstart

Python

pip install lulu-ads
# or: uv add lulu-ads
# or: poetry add 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"},
)
return result

FastMCP servers get it in one call — credentials come from the environment, and every tool (present and future) gets both the plain sponsored data field AND, in hosts that support it (e.g. Claude.ai), the rendered Sponsored-card widget, automatically:

export LULU_ADS_PUBLISHER_ID=pub_123
export LULU_ADS_API_KEY=lk_...
from lulu_ads.enable import enable_lulu_ads

enable_lulu_ads(mcp, endpoint_url="https://my-server.example.com/mcp")

Just want the data field, no widget? The plain middleware still works on its own:

mcp.add_middleware(LuluAdsMiddleware())

TypeScript

npm install lulu-ads
# or: pnpm add lulu-ads
# or: yarn add lulu-ads
# or: bun add lulu-ads
import { LuluAds } from "lulu-ads";
const ads = new LuluAds({ publisherId: "pub_123", apiKey: "lk_..." });
result.sponsored = await ads.sponsoredSlot({ context: { tool: "search_flights" } });

MCP servers built on the official TS SDK get the same one-call treatment — data field AND widget on every tool, automatically:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { enableLuluAds } from "lulu-ads/mcp";

const server = new McpServer({ name: "my-server", version: "1.0.0" });
await enableLuluAds(server, { endpointUrl: "https://my-server.example.com/mcp" });

No publisher ID yet? See docs/quickstart.md — three ways to get one, none of them gated on the others.

Tiered pricing (ads on a free tier, ad-free on paid)? Pass enabled — your own subscription check decides the value, no separate deployment or scattered conditionals needed:

result["sponsored"] = await ads.sponsored_slot(
    context={"tool": "search_flights"},
    enabled=user.tier != "paid",  # False resolves instantly, no network call
)
result.sponsored = await ads.sponsoredSlot({
  context: { tool: "search_flights" },
  enabled: user.tier !== "paid",
});

Framework integrations

| Stack | One-liner | Docs | |---|---|---| | FastMCP (Python), data + widget | enable_lulu_ads(mcp, endpoint_url=...) | | | FastMCP (Python), data only | mcp.add_middleware(LuluAdsMiddleware()) | | | MCP TS SDK, data + widget | await enableLuluAds(server, { endpointUrl }) | | | LangChain / LangGraph (Python) | middleware=[LuluAdsAgentMiddleware()] | | | CrewAI (Python) | lulu_crewai.install() | | | MCP TS SDK, data only | withLuluAds(server) | | | Skybridge (TypeScript) | withLuluAdsSkybridge(server) | | | Runtime owners (chat bots, WhatsApp/Telegram agents) | model_output + format_suffix(sponsored) | | | Any other runtime / language | sponsored_slot(context) over the raw contract | |

Result widgets — templates for your OWN tool output (0.8.5)

One widget, every host. The frame speaks three bridges — stable MCP Apps (ui/initialize, 2026-01-26), the draft-era fallback, and ChatGPT's window.openai — and the SDK registers both template keys (_meta.ui.resourceUri + openai/outputTemplate) and both CSP dialects automatically. Verified rendering live on claude.ai and ChatGPT, including the rendered-impression beacon (impressions count what a human actually saw, never mere API output). After upgrading, refresh your connector in ChatGPT's plugin settings — it caches tool metadata.

The SPONSORED strip's own format is separately configurable via sponsor_template= (independent of template=, this widget's own body layout):

register_result_widget(
    mcp, "search_flights",
    template="table-card",
    mapping={"rows": "flights", "columns": [...]},
    endpoint_url="https://my-server.example.com/mcp",
    sponsor_template="flip-card",  # or "carousel", "scratch-reveal" -- "card" is the default
)

Supported hosts

The plain sponsored JSON field is the always-on baseline: it ships on every tool result, on every MCP host, because it's nothing more than an extra key on a dict — no host-specific support is required for it to work, and the model decides on its own whether to surface it. The rendered MCP Apps widget above that is additive, and only paints where a host has actually implemented the ui/initialize handshake. This table says exactly which is which per host, based on our own production verification where we have it and a fresh survey (2026-08-25) everywhere else — a host only gets a "Live" widget status here when we've confirmed it ourselves or the vendor has published concrete, checkable implementation detail, never on a generic "should work" assumption.

<p> <a href="https://claude.ai"><img src="https://raw.githubusercontent.com/Lulu-The-Narwhal/lulu-ads/master/assets/hosts/claude.svg" alt="Claude" height="24"></a> &nbsp; <a href="https://chatgpt.com"><img src="https://raw.githubusercontent.com/Lulu-The-Narwhal/lulu-ads/master/assets/hosts/openai.png" alt="ChatGPT" height="24"></a> &nbsp; <a href="https://www.copilotkit.ai"><img src="https://raw.githubusercontent.com/Lulu-The-Narwhal/lulu-ads/master/assets/hosts/copilotkit.png" alt="CopilotKit" height="24"></a> &nbsp; <a href="https://code.visualstudio.com"><img src="https://raw.githubusercontent.com/Lulu-The-Narwhal/lulu-ads/master/assets/hosts/vscode.png" alt="VS Code" height="24"></a> &nbsp; <a href="https://cursor.com"><img src="https://raw.githubusercontent.com/Lulu-The-Narwhal/lulu-ads/master/assets/hosts/cursor.svg" alt="Cursor" height="24"></a> &nbsp; <a href="https://github.com/aaif-goose/goose"><img src="https://raw.githubusercontent.com/Lulu-The-Narwhal/lulu-ads/master/assets/hosts/goose.png" alt="Goose" height="24"></a> &nbsp; <a href="https://grok.com"><img src="https://raw.githubusercontent.com/Lulu-The-Narwhal/lulu-ads/master/assets/hosts/xai-grok.png" alt="Grok (xAI)" height="24"></a> &nbsp; <a href="https://windsurf.com"><img src="https://raw.githubusercontent.com/Lulu-The-Narwhal/lulu-ads/master/assets/hosts/windsurf.svg" alt="Windsurf" height="24"></a> &nbsp; <a href="https://cline.bot"><img src="https://raw.githubusercontent.com/Lulu-The-Narwhal/lulu-ads/master/assets/hosts/cline.svg" alt="Cline" height="24"></a> &nbsp; <a href="https://zed.dev"><img src="https://raw.githubusercontent.com/Lulu-The-Narwhal/lulu-ads/master/assets/hosts/zedindustries.svg" alt="Zed" height="24"></a> </p>

<sub>Hosts we've looked at — logos are not a support claim on their own; read the Status column below for what each one actually does. (Continue.dev is in the table but not the strip above: it's a discontinued product, kept here only for completeness.)</sub>

| Host | MCP tool-calling | Rendered widget | Status | |---|---|---|---| | Claude (claude.ai) | Yes | Yes | Live, verified in production — real rendered-impression beacons observed on live traffic. | | ChatGPT | Yes | Yes | Live, verified in production. | | CopilotKit (@ag-ui/mcp-apps-middleware) | Yes | In progress | Fix in review, PR #8, unverified end-to-end — a tool-discovery bug was found and fixed, but the fix has not been tested against a full chat UI (no LLM available in that pass) and is not yet released to npm/PyPI. Do not treat CopilotKit as supported until that PR lands and is verified live. The plain sponsored field is unaffected by this bug and already flows today. | | VS Code (native MCP + GitHub Copilot Chat agent mode) | Yes | Reported live | Microsoft's own 2026-01-26 blog post and current docs describe VS Code as "the first major AI code editor with full MCP Apps support" and document concrete, checkable implementation detail (sandboxed iframes, CSP domain config, the ui/initialize handshake, the App SDK) — credible, but this is a vendor claim we have not independently reproduced ourselves. Plain MCP tool-calling (Copilot Chat agent mode) has been GA since v1.102. | | Cursor | Yes | Reported, unverified | Named as an MCP Apps implementer on the upstream modelcontextprotocol.io Extension Support Matrix — a third-party listing, not Cursor's own docs, so weaker evidence than VS Code/Goose's vendor-published detail above. We actually tried to verify this ourselves live (2026-08-25) and got blocked before

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars3
CategoryMarketing
Updated1d ago
Forks0

Languages

TypeScript

Security Score

92/100

Audited on Sep 8, 2026

1 low