docs.g1.network

MCP Ad Format Specification v1.0

Version
1.0
Status
Draft (g1.network, 2026-05-11). Phase 0.5 deliverable.
Abstract
Programmatic ad format для AI-agent surfaces. OpenRTB 2.6 + imp.mcp extension + ext.agent identifier + markdown bid response.

Status: Draft (g1.network, 2026-05-11). Phase 0.5 deliverable. Authors: g1-adtech team Submission target: IAB Tech Lab draft extension (no acceptance dependency — we ship our own). Implements: OpenRTB 2.6 + imp.mcp extension + ext.agent + bid response markdown payload. Reference implementation: @theg1team/openrtb v0.1.0 (g1-platform/packages/openrtb/). Spec lifetime: SemVer; breaking changes = major bump + 12mo deprecation notice.


Abstract

MCP Ads define a programmatic ad format for AI-agent surfaces — surfaces где user interaction happens through an LLM-backed client (Claude.ai, Cursor, agent-served chat, MCP-protocol tools) rather than a traditional web/PWA/app surface. The format extends OpenRTB 2.6 with an imp.mcp BidRequest extension carrying conversational context, an ext.agent identifier identifying the AI client, and a structured BidResponse payload (markdown + image URL + JSON metadata) suitable for inline rendering inside an LLM response stream.

Three properties make MCP Ads different from traditional ad formats и motivate this spec:

  1. Inventory location — the ad surface is не a DOM tree or video player; it’s a token stream rendered by an LLM client. Display semantics are textual + image links, no iframe/SafeFrame/MRAID.
  2. Targeting signal — the primary signal is the conversational context at the moment of the ad request, not page URL / search query / app screen.
  3. Billing trust root — beacons are unreliable (AI clients may strip URLs, cache, dedup). Billing source-of-truth is an explicit SDK render-confirmation POST; beacons are 0.5x weight fallback only.

This spec specifies wire format, AI client authentication, render-confirmation semantics, user opt-out, localization, brand safety, frequency capping, and compliance disclosure.


1. Terminology

AI client / client app — a software product that renders MCP Ads inside its responses (e.g., Claude.ai web/desktop, Cursor IDE, third-party agent surface). Identified by client_app slug; whitelisted server-side before serving.

MCP gatewaymcp.g1.network; the entry point for AI clients calling ads_serve_for_context. Validates the client JWT and forwards to RTB.

Conversation — an AI-client-managed session с stable identifier (conversation_id UUID v4). Bounds frequency-cap, vertical-lock, и skip-flag scope.

BidRequest (BR) / BidResponse (BResp) — OpenRTB 2.6 message envelopes. Per this spec, imp.mcp extension carries MCP-specific signals; bid.ext.mcp carries the response payload.

Render confirmation (RC)POST /api/v1/mcp-ads/render-confirm from the AI client SDK with signed imp_id + render timestamp. RC is the billing source of truth.

Beacon — HTTP GET pixel embedded in the markdown body, fired only by AI clients that preserve URLs. Counted as 0.5x impression weight (fallback only); no charge if RC missing.

Sponsored label — mandatory localized disclosure (“Sponsored”, “Реклама”, “Werbung”, …) rendered inline по FTC Endorsement Guides + EU DSA Article 26.


2. Scope

In scope:

Out of scope (deferred):


3. Architecture overview

        ┌─────────────────────┐
        │ AI client (e.g.      │
        │ Claude.ai, Cursor)   │
        └──────────┬──────────┘
                   │ 1. ads_serve_for_context (MCP tool call)
                   │    headers: x-mcp-ads-client-token (JWT)

        ┌─────────────────────┐
        │ mcp.g1.network       │  ← OAuth client_credentials issuer
        │ gateway              │  ← JWT validation
        └──────────┬──────────┘
                   │ 2. BidRequest (OpenRTB 2.6 + imp.mcp)

        ┌─────────────────────┐
        │ rtb.g1.network       │  ← contextual targeting + vertical lock
        │                      │  ← own LLM context verifier (Claude Haiku)
        │                      │  ← DV/IAS pre-flight (creative side)
        │                      │  ← per-client_app QPS quota + burst
        └──────────┬──────────┘
                   │ 3. BidResponse (markdown + image + JSON metadata)

        ┌─────────────────────┐
        │ AI client renders    │
        │ inline + 'Sponsored' │
        │ label localized      │
        └──────────┬──────────┘
                   │ 4a. render-confirm POST (billing source of truth)
                   │ 4b. (fallback) beacon GET on markdown URL

        ┌─────────────────────┐
        │ adserver.g1.network  │  ← record impression
        │                      │  ← signed click_token redirect on click
        └─────────────────────┘

4. BidRequest extensions

4.1 imp.mcp

The mcp extension lives at Imp.ext.mcp in the OpenRTB 2.6 BidRequest. Presence of imp.mcp signals an MCP impression и triggers MCP-specific bidding/serving paths.

FieldTypeRequiredDescription
context_summarystring ≤2048yesLLM-friendly excerpt of recent conversation turns. Used для contextual targeting + re-classification on EVERY bid (no caching).
conversation_idstring (UUID v4)yesStable per-conversation identifier. Drives freq cap + competitive separation (vertical lock) + skip flag scope.
message_indexint ≥0yes0-indexed message count within conversation. Used для ad density rule (см. § 8).
agentAgentExtyesAI agent identity (см. § 4.2).
localestring (BCP-47)optionalConversation locale (e.g., en-US, pt-BR, ja-JP). Drives Sponsored label localization.
user_id_hashstring (64 hex chars)optionalSHA-256 hash of stable g1-side user_id. Drives skip flag lookup в mcp_ads_user_prefs (см. § 7). Required для skip-eligible inventory.
extobjectoptionalReserved for non-IAB extensions (e.g., vendor-specific scoring hints).

4.2 ext.agent (AgentExt)

The agent identity is part of imp.mcp.agent (and MAY be additionally surfaced at top-level ext.agent for non-MCP envelopes referencing the same AI client).

FieldTypeRequiredDescription
kind"web" | "mcp"yesmcp = AI-agent-served surface; web = traditional inventory (legacy compat).
modelstringoptionalModel name as known to the AI client (e.g., claude-opus-4-7, gpt-4o). Used для audit + ML segmentation.
client_appstringyesApproved AI client app slug (matches mcp_ai_clients_whitelist.client_app_id).

Important: agent is self-attested by the AI client. The trust root is the JWT transported in x-mcp-ads-client-token (см. § 6), not agent.client_app. Receivers SHOULD compare agent.client_app against the JWT’s sub claim and reject mismatches.

4.3 Example BidRequest (MCP impression)

{
  "id": "auction-01HXYZ123ABC",
  "imp": [
    {
      "id": "imp-1",
      "bidfloor": 1.50,
      "bidfloorcur": "USD",
      "ext": {
        "mcp": {
          "context_summary": "User is planning a 5-day trip to Tokyo in November, asking about JR Pass pricing and best neighborhoods to stay in for first-time visitors.",
          "conversation_id": "550e8400-e29b-41d4-a716-446655440000",
          "message_index": 7,
          "agent": {
            "kind": "mcp",
            "model": "claude-opus-4-7",
            "client_app": "claude-ai"
          },
          "locale": "en-US",
          "user_id_hash": "a3f5b7c9d1e2f4a6b8c0d2e4f6a8b0c2d4e6f8a0b2c4d6e8f0a2b4c6d8e0f2a4"
        }
      }
    }
  ],
  "site": null,
  "user": {
    "consent": "CPxxx.YAAAAAAAAA"
  },
  "regs": {
    "gdpr": 1,
    "gpp": "DBABL~BVQqAAAAAgA.QA",
    "gpp_sid": [7]
  },
  "source": {
    "schain": {
      "complete": 1,
      "nodes": [{ "asi": "mcp.g1.network", "sid": "g1-mcp-ads-pub", "hp": 1 }]
    }
  },
  "at": 1,
  "tmax": 100,
  "cur": ["USD"]
}

5. BidResponse contract

5.1 bid.ext.mcp (BidMcpPayload)

The response payload lives at Bid.ext.mcp. Bid.adm MAY be empty или contain a legacy-compat markdown fallback (matching bid.ext.mcp.markdown). When both are present, bid.ext.mcp wins.

FieldTypeRequiredDescription
markdownstring ≤4096yesMarkdown body. MAY reference image_url. NO inline base64 images.
image_urlstring (URL)optionalImage pointer (R2 signed URL, CDN, or absolute https://).
advertiserstringyesAdvertiser display name (matches dsp_advertisers.name).
ctastringoptionalCall-to-action text (e.g., "Get 20% off →"). MAY appear в markdown directly.
click_tokenstringyesHMAC-SHA256 signed click token (см. § 9). Required for click attribution.
sponsored_labelstringyes (defaults "Sponsored")Localized disclosure string. Rendered by AI client. См. § 9.
sponsored_label_localestring (BCP-47)optionalMatched against imp.mcp.locale.
integrity_hashstring (hex)optionalHash of canonical advertiser metadata. Used for tamper-detect post-render.

5.2 Markdown rules

5.3 Example BidResponse

{
  "id": "auction-01HXYZ123ABC",
  "cur": "USD",
  "seatbid": [
    {
      "seat": "dsp.g1.network",
      "bid": [
        {
          "id": "bid-9X",
          "impid": "imp-1",
          "price": 2.40,
          "adid": "ad-tokyo-jr-pass-2026",
          "adomain": ["jrpass.com"],
          "crid": "creative-jr-pass-v3-en",
          "lurl": "https://dsp.g1.network/lurl?bid=${AUCTION_LOSS}",
          "mtype": 1,
          "ext": {
            "mcp": {
              "markdown": "**Sponsored** · 🚆 **JR Pass — your unlimited bullet train ticket for Japan.** Pre-order online, save up to 25% vs. station prices. Valid 7/14/21 days. [Get yours →](https://adserver.g1.network/click?t=eyJ...signed...)",
              "image_url": "https://cdn.g1.network/r2/creative/jrpass-2026-banner.webp",
              "advertiser": "Japan Rail Pass Official",
              "cta": "Get yours →",
              "click_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpbXBfaWQiOiI...",
              "sponsored_label": "Sponsored",
              "sponsored_label_locale": "en-US",
              "integrity_hash": "3a7f9b2c1d8e4f5a6b9c2d8e1f4a7b3c"
            }
          }
        }
      ]
    }
  ]
}

5.4 No-bid

A no-bid response uses standard OpenRTB nbr codes. MCP-specific reasons MAY use vendor-specific codes ≥200 (e.g., MCP_SKIPPED = 250 for user_id_hash matching skip flag).


6. AI client authentication

Each MCP BidRequest from an AI client MUST include the header:

x-mcp-ads-client-token: <JWT>

The JWT is issued by auth.g1.network (g1-auth-oidc) via the OAuth 2.0 client_credentials flow. Properties:

6.1 Validation

Receivers (gateway + RTB runtime) MUST:

  1. Reject if JWT signature does not validate against current auth.g1.network JWKS.
  2. Reject if exp is in the past or > 5 min in the future.
  3. Reject if audmcp.g1.network or isshttps://auth.g1.network/.
  4. Reject if scopes does not include ads:serve-for-context.
  5. Reject if imp.mcp.agent.client_app ≠ JWT sub.
  6. Reject if same jti was seen in the last 5 minutes (replay).
  7. SHOULD enforce per-client_app QPS quota (см. mcp_ai_clients_whitelist.qps_quota + qps_burst).

6.2 Defense in depth

JWT is the trust root. Whitelist (mcp_ai_clients_whitelist.status = 'approved') and behavior heuristics (fingerprint anomalies, sudden QPS spikes, geographic inconsistencies) are defense-in-depth layers. None of them alone is sufficient.


7. Skip mechanism

7.1 g1-side flag

Users may opt out of MCP Ads. The flag lives server-side в mcp_ads_user_prefs table:

mcp_ads_user_prefs:
  user_id_hash TEXT PRIMARY KEY,    -- SHA-256 hex (64 chars)
  skip BOOL NOT NULL DEFAULT FALSE,
  updated_at TIMESTAMP NOT NULL

The flag is NOT tied to any AI client subscription. AI clients pass imp.mcp.user_id_hash in the BidRequest; the RTB backend looks up the flag и returns no-bid (nbr = 250 MCP_SKIPPED) if skip = TRUE.

7.2 Setting the flag

Users set the flag via:

7.3 Privacy

user_id_hash is a one-way SHA-256 of an internal stable identifier. The hash space is sufficient (2^256) to make rainbow-table attacks infeasible. The plaintext user_id is never sent to AI clients; only the hash.


8. Frequency capping + density

8.1 Rules

RuleDefault valueConfigurable
Min interval1 ad per conversation baselineyes (per ad-unit)
Density1 additional ad per 50 messages в long conversationsyes
Hard cap5 ads per conversation totalyes
Per-user cap10 ads per user per 24h across all conversationsyes
Vertical lock1 IAB v3 vertical per conversation (см. § 9)yes

8.2 Enforcement

Enforcement uses mcp_ads_impressions (Turso) + Durable Object freq-cap state keyed by conversation_id + user_id_hash (if present). Fallback to ip_hash если neither.

8.3 Density formula

ads_allowed_so_far(message_index) = 1 + floor((message_index - 1) / 50)
ads_served_so_far(conversation_id) = count(mcp_ads_impressions WHERE conversation_id = ?)
serve_eligible = ads_served_so_far < min(ads_allowed_so_far, hard_cap)

9. Brand safety

9.1 Per-conversation vertical lock

The first won impression in a conversation establishes the IAB v3 vertical (category lock). Subsequent impressions within that conversation MUST share or be a sibling of the locked vertical (competitive separation). Stored в mcp_ads_conversations.locked_iab_v3_cat.

9.2 Re-classification on every bid

imp.mcp.context_summary is sent through the own LLM context verifier (Claude Haiku) on EVERY bid request — no caching. Output: IAB v3 cat list + sensitive-cat flag.

9.3 Sensitive-cat cooldown

If the verifier marks the conversation context as sensitive (e.g., IAB v3 Sensitive Social Issues, Adult Content, Crime & Public Safety, …), the conversation enters a 24-hour cooldown during which no ads are served, regardless of advertiser bid.

9.4 Mandatory Sponsored label

Per FTC Endorsement Guides и EU DSA Article 26, every served ad MUST include a localized “Sponsored” label inline в the markdown body. The label MUST be visually distinguishable (bold or italic acceptable). Default English text "Sponsored"; per-locale overrides specified in bid.ext.mcp.sponsored_label field. Recommended locale values:

BCP-47Label
en-US / en-GBSponsored
de-DEWerbung
es-ESPatrocinado
fr-FR / fr-CASponsorisé
pt-BRPatrocinado
ja-JPスポンサー
zh-Hant贊助內容

9.5 Click token

bid.ext.mcp.click_token is a JWT-style signed token (HMAC-SHA256, see @theg1team/openrtb/ads-cert) containing:

ClaimDescription
imp_idImpression UUID
creative_iddsp_creatives.id
advertiser_iddsp_advertisers.id
dest_urlDestination URL after redirect
iatIssued at
expIssued at + 7 days

The click endpoint (adserver.g1.network/click?t=<token>) verifies signature, records the click in mcp_ads_clicks, и 302-redirects to dest_url.


10. Render confirmation

10.1 Endpoint

POST https://adserver.g1.network/api/v1/mcp-ads/render-confirm
Content-Type: application/json
x-mcp-ads-client-token: <JWT, same format as § 6>

10.2 Payload

{
  imp_id: string,          // UUID v4 of the served impression
  rendered_at: number,     // Unix milliseconds; must be ≤30s from now
  client_token: string,    // SDK's JWT (redundant w/ header; verified)
  viewability?: number     // [0..1], optional SDK-measured viewability
}

10.3 Semantics

10.4 Response

200 OK
{
  "recorded": true,
  "billed_weight": 1.0
}

4xx если invalid (no body charging):
400 → schema/JWT invalid
404 → imp_id not found
409 → already confirmed (deduplication)
422 → rendered_at outside window

11. Errors + NBR codes

Standard OpenRTB nbr reason codes apply (см. @theg1team/openrtb NBR constants). MCP-specific reasons (vendor-extension codes ≥200):

CodeSymbolReason
200BLOCKED_ADVERTISERBid blocked by bcat / badv
201BLOCKED_CATEGORYIAB v3 category blocked
202NO_CREATIVE_MATCHNo eligible creative
203NO_BID_BUDGETAdvertiser budget exhausted
204BELOW_FLOORBid below floor
250MCP_SKIPPEDUser has skip flag set (§ 7)
251MCP_SENSITIVE_COOLDOWNConversation в sensitive-cat cooldown (§ 9.3)
252MCP_VERTICAL_LOCKEDLocked vertical mismatch (§ 9.1)
253MCP_FREQ_CAP_HITConversation or user freq cap exhausted (§ 8)
254MCP_JWT_INVALIDClient JWT failed verification (см. § 6.1)
255MCP_CLIENT_NOT_WHITELISTEDclient_app not approved или suspended
256MCP_QPS_QUOTA_EXCEEDEDPer-client_app QPS quota hit

12. Compliance

12.1 FTC Endorsement Guides (US)

Every served ad MUST display a clear, unambiguous “Sponsored” label (§ 9.4). The label MUST appear inline within the rendered content, not in a hover-state or expandable section.

12.2 EU DSA Article 26

Same requirement; for European jurisdictions, also requires reasoning why the ad is shown to a particular user available на demand. This is provided via:

12.4 Children (COPPA)

If Regs.coppa = 1, MCP Ads MUST NOT serve.

12.5 Material adverse change notice

If the AI client’s terms или ad rendering behavior materially changes, the AI client MUST notify g1 ≥30 days в advance (re: mcp_ai_clients_whitelist.docusign_envelope_id).


13. Security considerations

  1. Prompt injection в context_summary — Adversarial users may craft conversation context to influence bidding (e.g., insert fake brand mentions). Counter: own LLM context verifier (§ 9.2) treats context as untrusted input; never executes / interprets it як instructions.
  2. JWT replayjti + 5-min window (§ 6.1.6).
  3. Click token forgery — HMAC-SHA256 секрет rotated 30d.
  4. Render confirmation forgery — RC requires valid JWT + matching imp_id (which was returned only to the JWT subject). Cross-client RC submission is rejected (§ 10.3).
  5. Beacon stripping — Acknowledged. RC is primary billing path; beacon is fallback. Persistent beacon-only patterns from a client_app SHOULD trigger billing dispute review.
  6. user_id_hash correlation — Hash is one-way; AI clients cannot recover user_id. Multiple user_id_hash-es from same user across AI clients are unlinked (different user_id per AI client identity binding, when applicable).
  7. MCP gateway abuse — Per-client_app QPS quotas + circuit breakers (§ 6.1.7). Outliers fed in real-time to anomaly detection (Axiom g1-trace-id correlation).

14. Localization registry

Initial 7 supported locales (Phase 5b launch = EN; Phase 6 GA adds remaining 6):

BCP-47Sponsored labelCooldown text keyActive phase
en-USSponsoredmcp.cooldown.en5b pilot
en-GBSponsoredmcp.cooldown.en6 GA
de-DEWerbungmcp.cooldown.de6 GA
es-ESPatrocinadomcp.cooldown.es6 GA
fr-FRSponsorisémcp.cooldown.fr6 GA
pt-BRPatrocinadomcp.cooldown.pt-BR6 GA
ja-JPスポンサーmcp.cooldown.ja6 GA
zh-Hant贊助內容mcp.cooldown.zh-Hant6 GA

Registry maintained at docs.g1.network/adtech/mcp-ads/spec/v1.0#locales. Additions require:

  1. Native speaker review (g1 team or partner-provided).
  2. Sponsored label confirmed to meet local regulatory disclosure norms.
  3. PR + 14-day comment period before merge.

15. Worked example end-to-end

Step 1 — AI client (Claude.ai) prepares MCP tool call:
  - User conversation in flight; message_index=7
  - Claude.ai SDK assembles context_summary, conversation_id, user_id_hash
  - SDK requests JWT from auth.g1.network/oauth/token (client_credentials)
  - SDK calls mcp.g1.network MCP tool ads_serve_for_context with JWT header

Step 2 — mcp.g1.network gateway:
  - Validates JWT (sig, exp ≤5min, aud, scopes includes ads:serve-for-context)
  - Looks up client_app="claude-ai" in mcp_ai_clients_whitelist → status=approved
  - QPS check (claude-ai: 500/sec quota, 50/sec burst)
  - Builds OpenRTB 2.6 BidRequest with imp.mcp from tool inputs
  - Forwards to rtb.g1.network

Step 3 — rtb.g1.network:
  - context_summary → Claude Haiku verifier → IAB v3 cats = [Travel, Asia]
  - locked_iab_v3_cat (from mcp_ads_conversations) is empty → no conflict
  - Sensitive flag: false
  - user_id_hash → mcp_ads_user_prefs lookup → skip=false
  - Freq cap: conversation has 0 prior impressions; 1+floor(6/50) = 1 allowed; OK
  - Auction: 3 advertisers bid; jrpass.com wins at $2.40
  - Creative pre-flight: DV/IAS green; creative-jr-pass-v3-en
  - Returns BidResponse with bid.ext.mcp payload

Step 4 — adserver.g1.network records impression:
  - imp_id generated (UUID v4); inserted into mcp_ads_impressions
  - mcp_ads_conversations.locked_iab_v3_cat set to "Travel" (first impression)
  - Click token generated (HMAC-SHA256, exp +7d)
  - BidResponse returned to gateway → AI client

Step 5 — AI client renders ad:
  - Markdown rendered inline в response stream:
    "**Sponsored** · 🚆 **JR Pass...** [Get yours →](https://adserver.g1.network/click?t=eyJ...)"
  - Image displayed from image_url
  - SDK fires render-confirm POST с imp_id + rendered_at + JWT

Step 6 — adserver records confirmation:
  - RC validated; mcp_ads_impressions.confirmed_at set
  - billed_weight = 1.0

Step 7 — user clicks:
  - GET adserver.g1.network/click?t=<token>
  - Token verified; mcp_ads_clicks row inserted; cross-funnel link checked
  - 302 redirect to jrpass.com/?utm_source=g1mcp&...&click_id=<imp_id>

Step 8 — advertiser postback (conversion later):
  - POST traffic.g1.network/conversions/postback with HMAC X-Signature
  - cross-funnel attribution applied (DSP > affiliate > organic precedence)
  - dsp_capi_events row inserted

16. Implementation references


17. Change log


18. References

  1. IAB Tech Lab OpenRTB 2.6 (Apr 2024) — https://iabtechlab.com/standards/openrtb/
  2. IAB Tech Lab Supply Chain Object 1.0
  3. IAB Tech Lab ads.cert 1.0
  4. IAB TCF v2.2 / Global Privacy Platform 1.0
  5. OAuth 2.0 RFC 6749 + Client Credentials Grant RFC 6749 §4.4
  6. JSON Web Token RFC 7519
  7. FTC Endorsement Guides (16 CFR 255)
  8. EU DSA (Regulation 2022/2065), Article 26
  9. CommonMark Spec 0.30
  10. BCP-47 Language Tags

19. Submitted-to-IAB checklist