AdKit MCP

Native ads for AI—semantic matching, not keyword hacks.

LLM-ready sponsor inserts via MCP

MCP-compatible Python 3.10+ Qdrant Dual-plane security

The 10-second explanation

Most ad systems are brittle because they match strings. LLM apps need meaning-based matching.

AdKit is a lightweight semantic ad engine: your LLM app requests relevant sponsor inserts using natural language context, and AdKit matches ads semantically using embeddings + vector search. It applies typed constraints (topics, locale, vertical, exclusions, policy flags). Your agent calls a tiny MCP tool surface: match, explain, health, capabilities.

What you get: higher relevance, cleaner architecture, and guardrails that keep production sane.

The business outcomes (exec-friendly)

Monetize without ruining trust.

📈

Relevance-first ads

Ads that feel native to the conversation or page, not jarring interruptions.

Fast sponsor onboarding

Add sponsors without hand-built rules or constant maintenance.

📋

Auditability

Answer "why did this ad show up?" with a full audit trace.

🔒

Security boundary by design

Runtime stays read-only. No surprises in production.

If your AI product is going to scale, you can't have monetization tied to fragile heuristics and ad-hoc scripts.

Who this is for

AdKit is for teams building:

🤖

AI assistants and copilots

Customer support, internal ops, sales, shopping—any agent that benefits from relevant sponsor inserts.

🔍

RAG search / Q&A products

Systems that want "sponsored context" alongside organic retrieval results.

💡

Content experiences

"You might also like" or affiliate inserts based on meaning—not keywords.

How it works (simple, non-nerdy)

Your app sends context

Chat turns, page content, query text—anything the user is currently doing.

AdKit matches semantically + enforces constraints

Embeds the context locally, retrieves candidates from Qdrant, then filters by targeting and policy.

You render a sponsor insert

Inline, sidebar, banner, feed—your UI stays in control.

Why AdKit is safer than "just add ads"

Dual-plane architecture (the part you should brag about)

Most "monetization plugins" become a security disaster because runtime can mutate data. AdKit splits responsibilities: Data Plane (runtime) = read-only ad matching; Control Plane (admin) = ingestion, provisioning, admin operations. That separation is the difference between a prototype and something you can put into production.

Data Plane

Ad matching, read-only retrieval

Called by: LLMs / Agents

uv run ad-mcp-data
  • ads_match — semantic ad matching with constraints, returns candidates + match_id
  • ads_explain — audit trace for a prior match
  • ads_health — liveness/readiness (Qdrant + embedding)
  • ads_capabilities — supported placements, constraint keys, model, schema

Control Plane

Provisioning, ingestion, admin ops

Called by: Humans, CI/CD, backoffice

uv run ad-mcp-control
  • collection_ensure — create/align collection
  • collection_info — collection metadata
  • collection_migrate — schema migrations
  • ads_upsert_batch — batch ad ingestion
  • ads_delete — delete an ad by id
  • ads_bulk_disable — disable ads by filter
  • ads_get — fetch a single ad

For repository structure and setup details, see the Technical Deep Dive.

Key capabilities

🌐

Semantic matching (not strings)

Ads match the meaning of the context, not keywords.

Typed targeting constraints

Topics, locale, verticals, exclusions, policy flags (e.g., sensitive / age-restricted handling).

🔍

Explainability

Every match can return an audit trace via ads_explain: why eligible, why others rejected, filters applied, similarity score.

🔒

Minimal MCP tool surface

Runtime exposes only allowlisted tools: ads_match, ads_explain, ads_health, ads_capabilities. No destructive ops at runtime. Period.

Implementation timeline (reduce friction)

Typical setup (local → production)

Day 0: Run Qdrant + AdKit locally, load demo ads

Install uv, start Qdrant, sync dependencies, create the collection, and seed demo ads.

bash
# Install uv (macOS/Linux)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Start Qdrant
docker run -d --name qdrant -p 6333:6333 -p 6334:6334 qdrant/qdrant

# Sync deps, create collection, seed ads
uv sync
uv run ad-index create
uv run ad-index seed
uv run ad-index info      # Verify: Points count should be 5

# Run Data Plane (LLM-facing)
uv run ad-mcp-data

Day 1–2: Integrate MCP calls into your agent/RAG pipeline

Wire ads_match into your agent’s tool surface. Pass conversation context, page content, or query text.

Week 1: Add your sponsor inventory + targeting rules

Use the Control Plane to ingest ads, set topics, locale, verticals, and exclusions.

Week 2: Tighten policy + monitoring, ship to production

Configure policy flags, add monitoring, and deploy. You control placement and rendering—AdKit just returns candidates.

You control placement and rendering. AdKit just returns candidates.

Security & governance (this closes exec deals)

AdKit is built with a hard boundary:

  • • Runtime matching is read-only
  • • Tools are explicitly allowlisted
  • • Admin operations are isolated in a separate control service/process
  • • Optional auth scopes for each plane (MCP_DATA_KEY, MCP_ADMIN_KEY)

This is what you want if you’re selling into enterprise environments or regulated verticals.

FAQs (objections you’ll get)

Keywords break the moment language shifts. Semantic retrieval keeps relevance consistent without constant rule maintenance.
No. Context embedding is local (FastEmbed) and storage is your Qdrant instance.
Yes—typed exclusions and policy flags are first-class.
Yes—ads_explain returns an audit trace tied to a specific match.