Skip to main content
ClaudeWave

OpenRTB linter: validates OpenRTB 2.x bid requests and bid responses against versioned IAB spec snapshots. Rust core, CLI, npm/WASM, MCP server.

MCP ServersOfficial Registry2 stars0 forks● RustApache-2.0Updated today
ClaudeWave Trust Score
95/100
✓ Verified
Passed
  • ✓Open-source license (Apache-2.0)
  • ✓Actively maintained (<30d)
  • ✓Clear description
  • ✓Topics declared
  • ✓Documented (README)
Last scanned: 10/10/2026
Install in Claude Code / Claude Desktop
Method: Manual · rtblint
Claude Code CLI
git clone https://github.com/aleksUIX/rtblint
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "rtblint": {
      "command": "rtblint"
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
💡 Install the binary first: cargo install rtblint (or build from https://github.com/aleksUIX/rtblint).
Use cases

MCP Servers overview

# RTBlint

**OpenRTB linter.** Validates OpenRTB 2.x bid requests and bid responses against versioned IAB Tech Lab spec snapshots, from 2.0 through the monthly 2.6 releases (currently up to 2.6-202606).

[![Crates.io](https://img.shields.io/crates/v/rtblint.svg)](https://crates.io/crates/rtblint)
[![CI](https://github.com/aleksUIX/rtblint/actions/workflows/rust.yml/badge.svg)](https://github.com/aleksUIX/rtblint/actions)
[![smithery badge](https://smithery.ai/badge/aleksander/rtblint)](https://smithery.ai/servers/aleksander/rtblint)
[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/aleksUIX/rtblint/badge)](https://scorecard.dev/viewer/?uri=github.com/aleksUIX/rtblint)

Website and playground: [rtblint.org](https://rtblint.org)

## What it checks

- Malformed JSON and wrong top-level shape
- Required fields, including required non-empty arrays
- Unknown objects and fields per version catalog (`ext` subtrees stay open)
- Type mismatches (string, integer, float, boolean, object, and array forms)
- Documented enum values, including AdCOM lists and vendor ranges (500+)
- Deprecated, moved, removed, and not-yet-available fields across versions
- Semantic rules: site/app/dooh exclusivity, imp media type presence, skippable video dependencies, duration exclusivity, seatbid/nbr presence on responses, and more
- Response markup coherence: `bid.adm` content vs the declared `bid.mtype` (native JSON encoding, VAST/DAAST roots, double-encoded payloads)
- Request/response cross-validation: with the originating request supplied, every bid's `impid`, `mtype`, `adm` markup, `dealid`, seat, and currency are checked against what the request actually offered
- JSON dialect: spec JSON types flag fields such as `imp.secure` and `regs.coppa` as integers, while the IAB OpenRTB protobuf schema declares 28 of them `bool`. Either encoding is correct on its own transport and wrong on the other, so the caller declares which one it meant
- Exchange profiles apply published request, response and paired constraints for the selected vendor and traffic direction. Optional extensions stay optional unless the source explicitly requires them. Profiles include Google Authorized Buyers, Prebid Server, Microsoft Monetize, Magnite DV+ xAPI and separate buyer, supplier and SDK contracts. See [exchange profile evidence](docs/exchange-profiles/) for sources, fixtures and limits
- Nested specs OpenRTB carries as strings or opaque `ext`: Native Ads 1.2 markup (`imp.native.request` and native `bid.adm`, including required-asset pairing), GPP header vs `gpp_sid` and TCF 2 shape, `${AUCTION_*}` macros on billing and loss URLs, EID/SUA structure, SKAdNetwork `ext.skadn`
- Privacy signal contradictions: `regs.coppa` / `device.lmt` / `device.dnt` / `regs.gdpr` versus identifiers on the same payload, TCF Purpose 1 versus device-storage IDs, US Privacy Opt-Out Sale versus hashed EIDs, email-shaped `user.id` / `site.page`, DSA Transparency field presence. Findings describe the document. They do not state a legal conclusion.
- ARTF envelopes and mutation sets, including applying the mutations and revalidating what comes out

Every finding carries a stable rule id, a severity, a message, and a JSON path.

## ARTF

[ARTF](https://iabtechlab.com/standards/artf/), the IAB Tech Lab Agentic Real Time Framework, hands an agent an OpenRTB payload inside an `RTBRequest` envelope and takes back *mutations*: proposed changes the orchestrator may accept or reject one at a time. Nothing in the framework checks that the auction still validates once they are applied, and a mutation is only meaningful relative to the request it targets.

```bash
# The envelope, plus full OpenRTB validation of what it carries
rtblint validate --type artf-request rtb-request.json

# The mutation set against the auction it targets
rtblint validate --type artf-response --request rtb-request.json rtb-response.json

# Apply the mutations, revalidate, and report only what the mutations broke
rtblint validate --type artf-response --apply --request rtb-request.json rtb-response.json
```

Three passes:

- **Envelope.** Required members, `lifecycle` against the payloads actually carried, `tmax` plausibility for an in-auction call, `originator` and `applicable_intents` enum values, and the carried bid request and bid response validated as protobuf JSON.
- **Mutations.** The response id echoes the extension point request id (not the bid request id), each declared intent is in `applicable_intents`, the operation and payload oneof member match the intent, and every semantic path (`/imp/{id}`, `/imp/{id}/pmp/deals/{id}`, `/user/data/segment`, `/seatbid/{seat}/bid/{id}`) resolves to something the auction carries. `ADJUST_DEAL_MARGIN` is reported as having no OpenRTB field to write to, because it does not.
- **Applied.** The mutations are written in and the result revalidated, reporting the OpenRTB findings the mutations introduced with pre-existing findings filtered out. What the agent broke, not what arrived broken.

The ARTF v1.0 document and its `.proto` use different vocabularies for the same mutation (`activateSegments` and a `value: {IDsPayload: ...}` wrapper against `ACTIVATE_SEGMENTS` and top-level oneof members). Payloads written from the document are mapped and reported as `artf.mutation.legacy_spec_encoding` rather than dismissed as unknown.

## Surfaces

| Surface | Package | Status |
|---------|---------|--------|
| Rust CLI | [`rtblint`](https://crates.io/crates/rtblint) | Working |
| Rust library | [`rtblint-core`](https://crates.io/crates/rtblint-core) | Working |
| MCP server | [`rtblint-mcp`](https://crates.io/crates/rtblint-mcp) | Working |
| Node (WASM) | `rtblint-core` on npm | Working |
| GitHub Action | [`aleksUIX/rtblint`](https://github.com/aleksUIX/rtblint) | Working |
| Python | `rtblint` on PyPI | Not implemented yet |
| Go | `github.com/aleksUIX/rtblint/go` | Not implemented yet |

OpenRTB 3.0 validates through its layered envelope: the transport objects (Openrtb, Request, Item, Deal, Source, Response, Seatbid, Bid) and the AdCOM 1.0 domain objects under `item.spec` (Placement), `bid.media` (Ad), and `request.context`. A 2.x payload sent to a 3.0 validator gets a migration diagnostic rather than a bare parse error. The 2.6-202204 snapshot has no extracted catalog and reports itself as unsupported instead of passing payloads silently. See [ROADMAP.md](ROADMAP.md) for what's next and [CHANGELOG.md](CHANGELOG.md) for release history.

## CLI

```bash
cargo install rtblint

rtblint validate request.json
rtblint validate --type response response.json
rtblint validate --type response --request request.json response.json
rtblint validate --version 2.5 --format json request.json
rtblint validate --dialect proto-json grpc-bid-request.json
rtblint validate --profile google-ab google-bid-request.json
rtblint validate --profile prebid-server pbs-auction.json
rtblint validate --profile xandr xandr-bid-request.json
rtblint validate --profile magnite magnite-bid-request.json
rtblint validate --resolve --cache ./supply-cache request.json
rtblint validate --summary bids.ndjson
rtblint validate --batch --summary bids.ndjson
cat request.json | rtblint validate --stdin
```

`--request` supplies the originating bid request for paired checks, including batch validation. `--dialect proto-json` selects the protobuf JSON encoding. `--profile` selects the vendor contract and traffic direction. Xandr checks bidder-facing Microsoft Monetize traffic; Magnite checks the DV+ xAPI extension model. Their optional seller, context and inventory identity fields are checked when supplied. Account-specific and runtime acceptance remain outside the payload. `--resolve --cache <dir>` checks SupplyChain hops against sellers.json and ads.txt / app-ads.txt from a local directory:

```text
<dir>/sellers/<asi>/sellers.json
<dir>/ads/<site.domain>/ads.txt
<dir>/app-ads/<app.bundle>/app-ads.txt
```

Nothing is fetched; populate the cache yourself. `--batch` lints one JSON object per line from a file or stdin. `--summary` adds rule-frequency totals for a captured stream (`--summary bids.ndjson` for the histogram alone). See [ARTF](#artf) for `--type artf-request` and `--type artf-response`.

Exit codes: 0 valid, 1 validation errors, 2 usage or I/O error.

## GitHub Action

The Action lives in this repo. Pin a release tag so CI downloads that CLI tarball:

```yaml
- uses: aleksUIX/rtblint@v0.13.0
  with:
    path: fixtures/bid-request.json
    spec-version: 2.6-202505
```

`version` selects the CLI release (`auto` follows the action's own `v*` tag). `spec-version` is the OpenRTB snapshot. Linux and macOS runners, x86_64 and aarch64.

## Node

```js
import { validate, validateResponse, validateResponseAgainstRequest } from "rtblint-core";

const report = validate(JSON.stringify(bidRequest), "2.6-202505");
if (!report.valid) {
  for (const issue of report.issues) {
    console.log(`[${issue.severity}] ${issue.path}: ${issue.message} (${issue.id})`);
  }
}

// Cross-validate a response against the request it answers.
const paired = validateResponseAgainstRequest(
  JSON.stringify(bidResponse),
  JSON.stringify(bidRequest)
);
```

For gRPC bidstream payloads and ARTF:

```js
import {
  validateDialect,
  validateProfile,
  validateArtfRequest,
  validateArtfResponseApplied,
  protoBoolDivergences,
} from "rtblint-core";

validateDialect(JSON.stringify(bidRequest), "proto-json");
validateProfile(JSON.stringify(bidRequest), "google-ab");
validateProfile(JSON.stringify(bidRequest), "prebid-server");
validateArtfRequest(JSON.stringify(rtbRequest));

// { result, application }: what the mutations broke, and the payloads they produced
const { result, application } = validateArtfResponseApplied(
  JSON.stringify(rtbResponse),
  JSON.stringify(rtbRequest)
);

protoBoolDivergences(); // the 28 fields the two schemas type differently
```

## MCP server

Hosted Streamable HTTP (no install): [https://rtblint.org/mcp](https://rtblin
ad-techadtechlintermcpmcp-serveropenrtbopenrtb-validatorprogrammatic-advertisingrtbrustvalidator

What people ask about rtblint

What is aleksUIX/rtblint?

+

aleksUIX/rtblint is mcp servers for the Claude AI ecosystem. OpenRTB linter: validates OpenRTB 2.x bid requests and bid responses against versioned IAB spec snapshots. Rust core, CLI, npm/WASM, MCP server. It has 2 GitHub stars and its last recorded update is dated 2026-10-10.

How do I install rtblint?

+

You can install rtblint by cloning the repository (https://github.com/aleksUIX/rtblint) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is aleksUIX/rtblint safe to use?

+

Our security agent has analyzed aleksUIX/rtblint and assigned a Trust Score of 95/100 (tier: Verified). See the full breakdown of passed checks and flags on this page.

Who maintains aleksUIX/rtblint?

+

aleksUIX/rtblint is maintained by aleksUIX. The last recorded GitHub activity is dated 2026-10-10, with 0 open issues.

Are there alternatives to rtblint?

+

Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.

Deploy rtblint to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: aleksUIX/rtblint
[![Featured on ClaudeWave](https://claudewave.com/api/badge/aleksuix-rtblint)](https://claudewave.com/repo/aleksuix-rtblint)
<a href="https://claudewave.com/repo/aleksuix-rtblint"><img src="https://claudewave.com/api/badge/aleksuix-rtblint" alt="Featured on ClaudeWave: aleksUIX/rtblint" width="320" height="64" /></a>

More MCP Servers

rtblint alternatives