# Add Lulu Ads to this MCP server You are an AI coding agent integrating the lulu-ads SDK into an existing MCP server or agent tool. Follow these steps exactly. ## 0. Fastest path — use the Lulu Ads MCP (recommended) If you can add MCP servers, add ours and let its tools drive the whole flow: ```bash claude mcp add --transport http lulu-ads https://ads.getlulu.dev/mcp ``` Then call `get_integration_guide(framework=...)`, `create_publisher(...)` (with the human's consent — it registers their email), integrate, and confirm with `verify_integration(publisher_id)`. If you cannot add MCP servers, continue below. ## 1. Identify the language - Python (FastMCP or raw MCP SDK) → `pip install lulu-ads` - TypeScript/JavaScript → `npm install lulu-ads` ## 2. Get credentials (ask the human if not provided) The human needs a publisher account (free): https://getlulu.dev/publishers or `curl -X POST https://ads.getlulu.dev/publishers -H 'content-type: application/json' -d '{"name":"","contact_email":"","server_url":""}'` Response contains `publisher_id` and a one-time `api_key`. Store them as env vars `LULU_ADS_PUBLISHER_ID` and `LULU_ADS_API_KEY` — never hardcode the key. ## 3a. FastMCP server (preferred: one line) ```python import os from lulu_ads.middleware import LuluAdsMiddleware mcp.add_middleware(LuluAdsMiddleware( publisher_id=os.environ["LULU_ADS_PUBLISHER_ID"], api_key=os.environ["LULU_ADS_API_KEY"], exclude_tools=(), # add tool names that must never carry sponsored content )) ``` ## 3b. Any Python tool (per-tool) ```python import os from lulu_ads import LuluAds ads = LuluAds(os.environ["LULU_ADS_PUBLISHER_ID"], os.environ["LULU_ADS_API_KEY"]) # inside the tool, right before returning a dict result: result["sponsored"] = await ads.sponsored_slot( context={"tool": "", "category": ""} ) ``` ## 3c. TypeScript tool ```ts import { LuluAds } from "lulu-ads"; const ads = new LuluAds({ publisherId: process.env.LULU_ADS_PUBLISHER_ID!, apiKey: process.env.LULU_ADS_API_KEY!, }); // inside the tool handler, before returning: const sponsored = await ads.sponsoredSlot({ context: { tool: "" } }); if (sponsored) (result as Record).sponsored = sponsored; ``` Note: `lulu-ads` is published unscoped on npm (not `@getlulu/ads`) — install with `npm install lulu-ads` and import `{ LuluAds }` from `"lulu-ads"` exactly as above. **Alternative — TypeScript MCP server built on `@modelcontextprotocol/sdk`.** Instead of calling the client per-tool, wrap the server once: ```ts import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { withLuluAds } from "lulu-ads"; const server = new McpServer({ name: "my-server", version: "1.0.0" }); withLuluAds(server); // call before registerTool — reads env vars ``` ## 4. Rules — do not deviate - NEVER add text telling the model/host to display the sponsored field. It is data; the host decides. Adding display instructions violates platform policies and gets servers delisted. - NEVER attach sponsored content to error responses. - NEVER pass user emails, names, IDs, or message content in `context` (the SDK drops non-allowlisted keys anyway). - The call is fail-open; do not wrap it in additional retry or error handling. ## 5. Verify Run the server, call any tool, and confirm the response includes `"sponsored": {"label": "Sponsored", ...}` (or nothing, if no fill — also correct). Done. Docs: https://getlulu.dev/docs.md · Human contact: tal@getlulu.dev