GAM Seller MCP Node
The GAM Seller MCP Node is a governed, read-only MCP server that exposes sell-side ad inventory discovery to buyer-side AI agents, with built-in security, privacy, and audit controls.
What you can do:
Verify server identity & capabilities (
well_known_capabilities): Retrieve a signed RS256 capability document confirming node identity, privacy posture, and allowed surfaces. Acts as a trust anchor; no input required.Discover ad product families (
discover_products): List coarse product categories (e.g., "Pre-Roll Video") that a specific buyer is entitled to see. Requires abuyer_id. Never exposes deal IDs, internal IDs, raw inventory, or exact pricing.Get coarse availability forecasts (
get_forecast): Obtain a Low/Mid/High availability bucket for a specific product family and time period (e.g., Q4-2026), with a firm list price if configured. Requiresbuyer_id,family_id, andperiod. Never returns exact impression counts, CPM curves, or floor prices.
What you cannot do:
No write operations – no orders, line items, or bids can be created or modified.
No sensitive data access – exact pricing, deal IDs, and raw availability numbers are blocked at the policy layer.
No unauthenticated bulk access – every request is subject to Default-Deny policy, rate limiting (1 req/30s per buyer), replay detection (via
client_request_id), and RS256 token validation.
Additional capabilities:
Hash-chained audit ledger: Every allow/deny decision is recorded with buyer identities pseudonymized via HMAC.
GDPR toolkit: Export, restrict, or erase a buyer's audit data (pseudonymized only).
Configuration-driven: Product families, entitlements, and pricing managed via JSON config files.
Exposes read-only ad inventory discovery from Google Ad Manager, providing tools for well-known capabilities, product families, and bucketized availability forecasts.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@GAM Seller MCP Nodeshow me available product families"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Governed MCP seller control-plane prototype for future GAM integration.
A Model Context Protocol server that exposes sell-side ad inventory to buyer-side AI agents: discovery, firm pricing, and a buyer-scoped soft commitment primitive. No writes to an ad server exist. The Google Ad Manager adapter is not yet connected; catalog and forecast data are synthetic.
What problem does this solve?
Sell-side ad inventory (availability, pricing, product structure) lives inside ad servers that hold commercially sensitive and sometimes personal data. Giving an AI buyer agent direct API access to GAM or a similar system creates three risks:
Risk | Without this project | With this project |
Data over-exposure | Agent can read raw avails, deal IDs, exact floor prices | Only coarse buckets and pre-declared families |
Accidental writes | Agent SDK can create orders, modify line items | No ad-server writes exist; the only write is a buyer's own soft commitment, which can never become a GAM order or an inventory hold |
No accountability | API calls are logged but not auditable | Hash-chained audit ledger; every allow/deny recorded |
Related MCP server: google-ads-mcp
How it works
A buyer agent connects via MCP and gets five tools — three read-only, plus a buyer-scoped commitment primitive (create/revoke) that is the sole write surface:
Buyer agent
│
├── well_known_capabilities ← Signed trust anchor. Check this first.
│ Returns: RS256-signed capability document, node identity, privacy posture.
│
├── discover_products ← What can I buy here, and at what firm price?
│ Returns: product families the buyer is entitled to see (e.g. "Pre-Roll Video"),
│ each with its firm list price when the publisher has configured one.
│ Never returns: deal IDs, internal IDs, raw inventory, exact per-impression pricing.
│
├── get_forecast ← How available is this family next quarter?
│ Returns: Low / Mid / High availability bucket.
│ Never returns: exact impression counts, CPM curves, floor prices.
│
├── create_intent ← Commit to a product at its current firm price (with TTL).
│ Records a firm, time-boxed buying intent — rejected if the price is stale or
│ mismatched. NOT a GAM order and NOT an inventory hold; it is the handoff artifact
│ the classic sales rails pick up. Buyer-scoped: you can only ever commit as yourself.
│
└── revoke_intent ← Withdraw one of your own active intents by id.Every call flows through the same pipeline before any domain logic runs:
Buyer request
│
▼
[SEC-GATE-3] Replay detection — deduplicate client_request_id
│
▼
[Auth] RS256 token validation → identity confirmed or AUTH_FAILED
│
▼
[Policy] Surface denylist → entitlement check → scope check (Default-Deny)
│
▼
[Rate limit] N=1 / T=30s per buyer_id
│
▼
[Domain] Catalog / ForecastEngine — synthetic today, real GAM adapter in progress
│
▼
[Audit] Append-only hash-chained ledger, buyer pseudonymized (HMAC)
│
▼
Response to buyerEach request-path gate rejects on failure. Exception: on startup, a corrupted on-disk audit
ledger resets to an empty chain rather than blocking service (audit/ledger.ts:153).
Also, client_request_id (the replay-guard deduplication key) is optional; requests
that omit it bypass SEC-GATE-3.
create_intent runs the same gates and adds one more before it records anything: the buyer's
price_ref must match the family's current firm price, or the request is rejected.
Quick start
Install in an MCP client (via npx)
Add the server to your MCP client (Claude Desktop, Claude Code, Cursor, …):
{
"mcpServers": {
"gam-seller": {
"command": "npx",
"args": ["-y", "gam-seller-mcp-node"]
}
}
}Or run it directly (stdio transport — the default for MCP clients):
npx -y gam-seller-mcp-nodeDemo mode. With no config of your own, the node boots on a bundled
pilot-publisherexample (illustrative catalog, prices and forecasts) and says so on stderr — it starts instead of failing, so you can try the tools immediately. Because buyer surfaces always require a token (there is no anonymous path, even in demo), the node prints a ready-to-use demo buyer token on startup: copy it and pass it as thetokenargument todiscover_products/get_forecastto see the example families, prices and forecasts.For a real deployment, point
MCP_CONFIG_DIRat a directory holding your owndeployment.json,catalog.json,entitlements.jsonandpricing.json:MCP_CONFIG_DIR=/etc/gam-seller/config npx -y gam-seller-mcp-node
From source
git clone https://github.com/juan-sibbo/gam-seller-mcp-node.git
cd gam-seller-mcp-node
npm install
npm run build
npm run start:http # HTTP transport on 127.0.0.1:3900Run the full buyer-agent walkthrough (scripted demo):
npx tsx demo/run-demo.tsWith Docker
docker compose upThe node starts on 127.0.0.1:3900. The well-known document is at
/.well-known/seller-mcp-capabilities. Persistent volumes for keys and audit data are
pre-configured in docker-compose.yml.
Configure for your publisher
Four JSON files drive all publisher-specific behaviour — no code changes needed. Place them
in config/ (from-source) or in the directory named by MCP_CONFIG_DIR (npx/containerised):
deployment.json # DSR contact, controller model, data retention window
catalog.json # product families + per-buyer access grants
entitlements.json # which buyers are entitled to which MCP surfaces
pricing.json # firm list prices per family (fail-closed on expiry)Invalid config always fails closed: a malformed file stops the node rather than running
with a silently different access policy. Absent config (no config/ and no MCP_CONFIG_DIR)
drops to the bundled config/examples/pilot-publisher/
example — demo mode, announced on stderr — so the node is never a broken install, only ever a
real deployment or a clearly-labelled demo.
Why not just use the GAM API directly?
Approach | Data exposure | Writability | Auditability | AI-agent friendly |
Raw GAM API | Everything in the account | Full CRUD | Logging only | Poor (SOAP/REST, no MCP) |
OpenRTB bid requests | User-level data, floor prices | Bid-only | None | Poor |
This server | Coarse families + bucket forecasts | Buyer's own soft commitment only (no GAM writes) | Hash-chained ledger | Native MCP |
Current status
Working prototype. The full request pipeline (auth → policy → rate-limit → domain → audit),
the buyer-scoped commitment primitive (create_intent / revoke_intent, with TTL expiry),
the audit ledger, GDPR data-subject-rights toolkit, Docker packaging, HTTP transport,
and a live interop probe (Python buyer agent simulation) are all implemented and tested.
Not yet wired: a live Google Ad Manager connection. The catalog and forecast data are
synthetic, loaded from local config. The GAM ForecastService SOAP adapter interface exists
(src/forecast/source.ts) as a stub — it throws on any call until a
service account is provisioned (DP-AB-01 §5.2). See the
open issues for the roadmap.
Known limitations:
The audit ledger chain does not include
buyer_idorrequest_idin its canonical hash input (audit/event.ts:43-51); those fields are stored in the entry but are not covered by the chain's tamper-evidence guarantee.Chain integrity is not verified on startup before the node begins serving requests (
audit/anchor.ts:93-121implementsverifyAfterRestore(), which is not called inmain()).The head-hash anchor is written to a local file using a rewritable
writeFileSynccall (audit/anchor.ts:68-78). The code comment acknowledges this is not production-safe; cloud Object Lock storage is the intended target and is not yet implemented.client_request_id(replay guard) is optional (src/server.ts:202); requests that omit it bypass the SEC-GATE-3 deduplication step.The GDPR DSR CLI scripts (
scripts/dsr.ts,scripts/issue-buyer-token.ts,scripts/revoke-token.ts) are available in the source repository but are not included in the npm package distribution.
Architecture
See docs/ARCHITECTURE.md for the module map and data-flow diagrams.
Key modules:
Module | Role |
| MCP tool definitions + request pipeline |
| Default-Deny engine, entitlement store, surface allowlist/denylist |
| RS256 key management, token issuance/validation, revocation denylist |
| Hash-chained ledger, HMAC pseudonymization, local-file head-hash anchoring |
| Firm list price store, expiry-aware (fail-closed on stale prices) |
| Bucket engine + GAM adapter seam (synthetic today) |
| GDPR Art. 15/17/18/20 data-subject-rights toolkit (source only) |
| Product family store, per-buyer access grants |
Security model
Default-Deny. Every request is denied unless an explicit entitlement says otherwise — there is no "allow by default" path in the code.
Structural allow/denylist (SEC-GATE-*). Response surfaces are governed by a fixed list enforced
at the policy layer, independent of which tool was called. Exact pricing, deal IDs, raw availability
numbers, cross-buyer state, real inventory holds (soft-lock), and any ad-server write are permanently
denied. The one permitted write is a buyer's own commitment (create_intent / revoke_intent),
which required an explicit amendment to the surface allowlist and stays buyer-scoped. Adding a new
tool in the future cannot bypass this.
Opaque errors. A denied request, a failed authentication, and a revoked token all return the
same generic AUTH_FAILED code. Internal reasons never reach the buyer.
Audit-first. Every allow/deny is written to the ledger before the response is sent.
Buyer buyer_id values are pseudonymized (HMAC-SHA256) before entering the chain. Note that
buyer_id and request_id, while stored in each audit entry, are not included in the
hash-chain's canonical input (audit/event.ts:50); those fields are not covered by the
chain's tamper-evidence guarantee.
Privacy by construction. Responses carry only inventory-level data (product family, coarse bucket). User-level attributes don't exist in any response path.
See docs/DESIGN-PRINCIPLES.md for the full reasoning.
Regulatory posture
The AEPD (Spain's data protection authority) published guidelines on agentic AI systems in February 2026. The four recommendations most relevant to an ad-inventory node map directly to existing design decisions:
AEPD recommendation | This node |
Protection by design and by default | Default-Deny: every surface denied unless an explicit entitlement grants access |
Record and document agent actions | Append-only hash-chained audit ledger; every allow/deny recorded before the response is sent |
Control what leaves toward third parties, and with what traceability | Structural egress allowlist (SEC-GATE-*); exact pricing, deal IDs and raw availability permanently blocked |
Govern agent memory with purpose and retention rules | DSR toolkit (Arts. 15/17/18/20); configurable retention window enforced on the audit ledger |
This alignment is declared machine-readably in the signed well-known document
(/.well-known/seller-mcp-capabilities) under privacy_posture.regulatory_alignment_declared:
["GDPR", "AEPD-orientaciones-IA-agentica-2026"]. A buyer agent or auditor can verify it
cryptographically without trusting this README.
The node does not make legal determinations — whether a given processing has a legitimate basis, whether consent is valid, whether a particular treatment is permitted. Those judgements belong to the controller (the broadcaster). The node provides the mechanisms; the controller applies the criteria. This boundary is what keeps the node's design stable regardless of how the EU Data Act negotiations resolve.
Machine-readable trust anchor
The /.well-known/seller-mcp-capabilities endpoint returns an RS256-signed JWT. A buyer agent
reads and verifies this document before the first authenticated request. The privacy_posture
block inside it is machine-readable and cryptographically bound to the node's keypair:
Property | Current value | Meaning |
|
| No end-user personal data in any response path |
|
| No audience targeting surfaces |
|
| Node does not consume TC strings (server-to-server, PATH A) |
|
| No device storage access (ePrivacy N/A) |
|
| Declared operating jurisdiction |
|
| Declared alignment |
| from | Contact for data-subject requests |
| from | Publisher's declared controller role |
| from | Hot/archive retention windows in days/months |
Not yet in the well-known document (properties that remain implicit):
Whether the catalog and forecast data are synthetic or live (
data_source)Whether head-hash anchoring uses a local file or cloud Object Lock (
anchor_store)Whether the node is in demo mode or serving a real publisher config (
deployment_mode)
These properties would allow a buyer agent to programmatically distinguish a demo deployment from a production one, and a locally-anchored node from one with external tamper-evidence. They are not present in the current version.
Testing
npm test # full suite (vitest)
python3 sandbox/buyer-agent-probe.py # external Python interop probe (no shared code with server)The test suite includes:
Unit tests for each module (policy, pricing, identity, audit, catalog, forecast, DSR)
Integration tests over real in-memory MCP transports (
tests/server.test.ts)HTTP transport tests over a real ephemeral-port HTTP server (
tests/http.test.ts)End-to-end session tests simulating a full buyer-agent session (
tests/buyer-agent-session.test.ts)External Python probe that exercises the HTTP transport without any shared Node.js code
CI runs on every push via GitHub Actions.
Data protection
Raw buyer_id values never enter the audit ledger — only an HMAC pseudonym. The
src/dsr/toolkit.ts implements export, restriction, and erasure of a
buyer's audit data (GDPR Art. 15/17/18/20). The node stores nothing about end users; the DSR
scope is exactly what it records — B2B buyer organization pseudonyms and their request events.
Distribution note. The DSR CLI scripts (scripts/dsr.ts, scripts/issue-buyer-token.ts,
scripts/revoke-token.ts) are present in the source repository but are not included in the
npm package distribution. Publishers deploying via npx or Docker must clone the repository
to access the DSR CLI.
Roadmap
See the open issues for the full roadmap. Highlights:
Real GAM adapter — wire
getAvailabilityForecastvia the ForecastService SOAP APIBuyer agent SDKs — Python and TypeScript client libraries for the MCP buyer flow
OpenRTB 3.0 taxonomy — align
family_idscheme with IAB standardsPrometheus metrics — observability endpoint for production deployments
Contributing
See CONTRIBUTING.md. Issues tagged
good first issue
are a good starting point.
License
MIT — see LICENSE.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Flicense-qualityCmaintenanceA Multi-Agent Conversation Protocol Server that provides programmatic access to the Google Authorized Buyers Marketplace API, allowing agents to interact with the digital advertising marketplace through natural language.

google-ads-mcpofficial
Alicense-qualityAmaintenanceMCP server that provides tools and resources for interacting with Google Ads API, enabling search, metadata retrieval, and account management through natural language.843Apache 2.0- AlicenseAqualityBmaintenanceA read-only MCP server for querying Google Ads data using GAQL, enabling AI assistants to safely read campaign performance, ad groups, and keywords.12MIT
- Alicense-qualityCmaintenanceA read-only MCP server that enables AI agents to act as GCP platform engineers, allowing them to investigate incidents, take inventory, and find cost-optimization opportunities in Google Cloud projects without mutating any infrastructure.2MIT
Related MCP Connectors
Hosted Amazon Seller Central and Amazon Ads MCP server for Claude, ChatGPT, Cursor, and agents.
MCP server exposing the Backtest360 engine API as tools for AI agents.
Hosted Amazon Seller and Vendor MCP server for Claude, ChatGPT, Cursor, Codex, Gemini, Copilot.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/juan-sibbo/gam-seller-mcp-node'
If you have feedback or need assistance with the MCP directory API, please join our Discord server