RTBlint

io.github.aleksUIX由 GitHub 帳號 aleksUIX 發布v0.14.4更新於 Nov 4, 2026

Validate OpenRTB bid requests and responses against IAB specs. ARTF, Rust core.

已驗證Streamable HTTP可網頁執行開發者工具商業與電商

概覽

AI 產生的概覽

RTBlint 依版本化的 IAB 規範快照驗證 OpenRTB 2.x 競價請求與回應,以及 ARTF 信封與變更集。

可以做什麼
  • 依指定 OpenRTB 版本驗證競價請求與競價回應,回傳含規則 ID、嚴重程度與 JSON 路徑的結構化問題
  • 將回應與原始請求交叉比對(impid、mtype、adm 標記、dealid、seat、幣別)
  • 驗證 ARTF RTBRequest 信封與 RTBResponse 變更集,可選擇套用變更後重新驗證
  • 列出此建置支援的 OpenRTB 版本,並回報 AdCP 協定能力與一致性指標
適用情境
適合在建置或除錯程式化廣告整合時使用:檢查擷取的競價請求與回應、核對交易所設定檔的符合度,或在協調器收到之前,為代理的 ARTF 變更提案提供驗證防護。
執行需求
遠端 Streamable HTTP 端點 rtblint.org/mcp,未宣告驗證、環境變數或標頭。另有本機 stdio 版本,但此處未提供對應套件。託管工具不會連網抓取 sellers.json 或 ads.txt。
安裝前請注意
README 說明送到託管端點的酬載可能去識別化後儲存以改善規則,因此不要傳送敏感或專有競價資料;本機 stdio 伺服器不會外送酬載。驗證結果僅描述文件本身,不構成法律結論。ARTF 的 apply 選項會把變更寫入副本並重新驗證。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 RTBlint,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

交給代理程式安裝

把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。

閱讀 https://sourceweft.com/mcp/io.github.aleksUIX%2Frtblint/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。

檢視代理程式所依據的安裝指南

其他 MCP 客戶端

把它新增到你客戶端的 mcpServers 設定中。

{
  "mcpServers": {
    "rtblint": {
      "type": "http",
      "url": "https://rtblint.org/mcp"
    }
  }
}

README

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] [CI] [smithery badge] [OpenSSF Scorecard]

Website and playground: 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 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, 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 carriesrtblint validate --type artf-request rtb-request.json
# The mutation set against the auction it targetsrtblint validate --type artf-response --request rtb-request.json rtb-response.json
# Apply the mutations, revalidate, and report only what the mutations brokertblint 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

SurfacePackageStatus
Rust CLIrtblintWorking
Rust libraryrtblint-coreWorking
MCP serverrtblint-mcpWorking
Node (WASM)rtblint-core on npmWorking
GitHub ActionaleksUIX/rtblintWorking
Pythonrtblint on PyPINot implemented yet
Gogithub.com/aleksUIX/rtblint/goNot 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 for what's next and CHANGELOG.md for release history.

CLI

bash
cargo install rtblint
rtblint validate request.jsonrtblint validate --type response response.jsonrtblint validate --type response --request request.json response.jsonrtblint validate --version 2.5 --format json request.jsonrtblint validate --dialect proto-json grpc-bid-request.jsonrtblint validate --profile google-ab google-bid-request.jsonrtblint validate --profile prebid-server pbs-auction.jsonrtblint validate --profile xandr xandr-bid-request.jsonrtblint validate --profile magnite magnite-bid-request.jsonrtblint validate --resolve --cache ./supply-cache request.jsonrtblint validate --summary bids.ndjsonrtblint validate --batch --summary bids.ndjsoncat 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

Protobuf JSON also supports the IAB schema's native object alternatives: imp.native.request_native (requestNative) and bid.adm_native (admNative). Their native flags use booleans. The string alternatives request and adm keep their JSON-encoded Native Ads markup. Supply one alternative per oneof. Native assets remain validated and paired against required request assets. See the IAB protobuf schema.

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 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/[email protected]  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 producedconst { 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. Smithery listing: aleksander/rtblint (same account as vastlint). Payloads sent to the hosted endpoint may be stored (identifiers stripped) so the rules can be improved; see rtblint.org/privacy. Local rtblint-mcp over stdio does not send payloads.

rtblint-mcp also speaks MCP over stdio. Tools: validate_bid_request, validate_bid_response (optional bid_request for cross-validation), validate_artf_request, validate_artf_response (apply writes the mutations and revalidates), list_openrtb_versions, get_adcp_capabilities. Validation tools take optional dialect and profile arguments.

The ARTF tools are the guardrail an agent calls around its own work: check the envelope it was handed, then check the mutation set it is about to propose, before the orchestrator sees it.

json
{  "mcpServers": {    "rtblint": { "url": "https://rtblint.org/mcp" }  }}

Local stdio instead of the hosted endpoint:

json
{  "mcpServers": {    "rtblint": { "command": "rtblint-mcp" }  }}

Rust library

rust
use rtblint_core::{validate_bid_request_for_version, OpenRtbVersion};
let result = validate_bid_request_for_version(OpenRtbVersion::V2_6_202505, payload);for issue in &result.issues {    println!("{} {} {:?}", issue.severity, issue.id, issue.path);}

validate_bid_request_with_profile applies an exchange profile (Profile::GoogleAuthorizedBuyers, Profile::PrebidServer) on top of the spec. validate_bid_request_with_dialect selects spec JSON vs protobuf JSON.

Published profile IDs: spec, google-ab, prebid-server, xandr, magnite, dv360, index-exchange, index-exchange-seller, unity, vungle, bidswitch, bidswitch-supplier, inmobi, inmobi-supplier, mobilefuse, mobilefuse-sdk, applovin-alx, commerce-grid, digital-turbine, sovrn, equativ, equativ-supplier, triplelift-supplier, adform-handler, yandex-sdk-bidding, pubmatic-openwrap, pubmatic-openwrap-ctv. Select the matching direction, such as bidswitch for buyer 5.7 and bidswitch-supplier for supplier 1.1.

See the profile scope and source evidence for checked fields, supported directions and explicit gaps. Paired response validation uses the request as reference context; run request validation separately for its complete report.

JSON Schemas

schemas/ holds a JSON Schema (draft 2020-12) per tracked version, for both payload types, generated from the same catalogs the validator uses. IAB Tech Lab publishes no JSON Schema for 2.6 or 3.0, so these are the machine-readable contract for each monthly snapshot:

https://rtblint.org/schemas/openrtb-2.6-202606-bid-request.schema.jsonhttps://rtblint.org/schemas/openrtb-2.6-202606-bid-response.schema.json

They cover structure, types, required fields, documented value sets, and AdCOM enum lists. What they cannot express is what the linter adds: deprecated and moved paths, version-specific removals, and the semantic rules. Validating against a schema is not the same as linting.

Regenerate after any catalog change (CI fails if they drift):

bash
cargo run -p rtblint-core --example export_json_schemas

Documentation

Beyond this README, rtblint.org hosts the reference material:

Spec data and provenance

The validator runs on structured catalogs extracted from the IAB Tech Lab OpenRTB specifications: object names, field names, type notations, enumerated value sets, and section citations. The catalogs carry no spec prose. The dialect table is derived the same way, by comparing those catalogs against the field types the IAB OpenRTB protobuf schema declares. RTBlint is not affiliated with or endorsed by IAB Tech Lab. See NOTICE for attribution.

Supply chain

OpenSSF Scorecard runs weekly and publishes a public score. Dependabot covers Cargo, npm, and GitHub Actions. CodeQL scans Rust and JavaScript on every push and PR.

Three cargo-fuzz targets (validate, validate_response, validate_artf) run for 30 seconds each on every CI push. The validator must not panic on arbitrary input.

bash
cargo +nightly fuzz run validate -- -max_total_time=60

License

Apache-2.0. See LICENSE and NOTICE.

Research

Sekowski, A. (2026). How Machine-Checkable Is OpenRTB? Classifying the Normative Content of the Protocol That Clears Real-Time Advertising. Preprint. DOI: 10.13140/RG.2.2.27937.57448

Sekowski, A. (2026). Measuring OpenRTB Dialects in Client-Side Header Bidding. Preprint. DOI: 10.13140/RG.2.2.26572.78720

Sekowski, A. (2026). Why CTV Ad Fraud Keeps Working: A Verifiability Analysis of the Connected TV Supply Chain. Preprint. ResearchGate. Field inventory extracted from this catalog. Artifacts: github.com/aleksUIX/ctv-verification-gap.

來源:README.md,提交 d7fd6a1

工具

6

validate_bid_request

Validate an OpenRTB 2.x bid request JSON payload against a tracked spec version. Returns structured issues with rule ids, severities, and JSON paths.

輸入參數dialectpayload必填profileversionsample_kind

validate_bid_response

Validate an OpenRTB 2.x bid response JSON payload against a tracked spec version. Optionally cross-validate it against the originating bid request (impid, mtype, adm markup, dealid, seat, and currency coherence). Returns structured issues with rule ids, severities, and JSON paths.

輸入參數dialectpayload必填profileversionbid_requestsample_kind

validate_artf_request

Validate an ARTF (IAB Tech Lab Agentic Real Time Framework) RTBRequest envelope: required members, lifecycle and payload coherence, tmax plausibility, originator and applicable_intents enums, plus full OpenRTB validation of the bid request and bid response it carries. The carried payloads are protobuf JSON, so they are validated in that dialect.

輸入參數payload必填versionsample_kind

validate_artf_response

Validate an ARTF RTBResponse mutation set against the RTBRequest it answers: envelope id echo, declared intent against applicable_intents, operation and payload coherence, and whether each semantic path (/imp/{id}, /imp/{id}/pmp/deals/{id}, /user/data/segment, /seatbid/{seat}/bid/{id}) resolves to something the auction actually carries. With apply=true the mutations are written into the payloads and revalidated, reporting the OpenRTB findings the mutations introduced. Call this before proposing mutations to an orchestrator.

輸入參數applypayload必填versionrtb_request必填sample_kind

list_openrtb_versions

List every OpenRTB version id this build can validate against, from 2.0 through the monthly 2.6 snapshots. Call this before pinning version on a validate_* tool.

無需輸入參數。

get_adcp_capabilities

AdCP protocol discovery. Returns the AdCP releases this agent speaks and the bid-stream conformance metrics it computes. Call this first when wiring rtblint into an agentic buying pipeline: it declares the experimental measurement protocol and the metric ids (openrtb_error_count, openrtb_warning_count, openrtb_conformance_rate) that validate_bid_request and validate_bid_response produce. Part of the Ad Context Protocol (AdCP 3.1) specification.

輸入參數extcontextprotocolsadcp_versionidempotency_keyadcp_major_version

版本歷史

5
  1. v0.14.4最新Oct 21, 2026
  2. v0.14.3Oct 21, 2026
  3. v0.14.0Oct 10, 2026
  4. v0.13.4Oct 4, 2026
  5. v0.8.0Sep 16, 2026

評分

已滿足適用檢查項的 100%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通必需25 分
  • 已宣告認證方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分