@pipeworx/usitc-edis
Connect: https://gateway.pipeworx.io/usitc-edis/mcp · Install: one-click buttons
No MCP client? Skip the connection: POST https://gateway.pipeworx.io/v1/tools/search_packs {"query":"..."} to find a tool below, GET /v1/tools/<name> for its schema, POST the same URL with arguments for the data — see For AI agents.
Tools: 6
The docket for US International Trade Commission investigations: Section 337 (unfair import / patent) cases and Title VII (antidumping/countervailing-duty, “Import Injury”) cases. Two USITC services, one pack, both keyless:
- IDS (Investigations Database System,
ids.usitc.gov) — the case record itself: search/list across all ~4,400 investigations, full detail for one. - EDIS (Electronic Document Information System,
edis.usitc.gov) — the documents FILED in an investigation and their attachments.
A login.gov-issued token (PLATFORM_EDIS_TOKEN) exists as a FALLBACK for
edis_* if EDIS’s keyless route ever closes — see “Auth” below — but it is
not needed for a normal call, and the pack never blocks on it.
Tools
| Tool | Auth | Answers |
|---|---|---|
itc_investigation_search | none | Paginated list of investigations, most-recent-first, with a same-page type/active filter |
itc_investigation_detail | none | Full status record for one investigation (by internal investigation_id) |
itc_investigation_types | none | The 4 top-level investigation type categories |
edis_document_list | none (token fallback) | Documents filed in one investigation (motions, orders, certified lists, complaints…) |
edis_document_detail | none (token fallback) | Full detail for one document id |
edis_attachment_list | none (token fallback) | Attachment metadata (title, size, page count, download URI) for one document |
Auth
Everything in this pack is keyless for a normal call, verified live 2026-09-24:
- IDS (
itc_*).advanced-searchandinvestigation/{id}both answer real data with no credential at all. The only header requirement is a browser-shapedOrigin/Referer(not a credential, just what a same-origin page sends); a plain User-Agent alone was rejected. - EDIS (
edis_*). Every GET resource (document,document/{id},document/{id}/detail,attachment/{documentId}) answers real data with no Authorization header at all, as long asAccept: application/xmlis sent (application/json406s on these three resources) — and as long as the User-Agent matches what EDIS’s WAF allows (see “Traps” below; this is the actual gate, not auth).
edis_* tries the keyless route FIRST, and only falls back to
PLATFORM_EDIS_TOKEN if that fails — a non-200, an HTTP 401/403, or a body
that turns out to be USITC’s generic “under maintenance” HTML page rather
than data (edisGetKeylessFirst in src/index.ts). The token is a JWT
(sub: "MOJIBAKE") Bruce obtained through EDIS’s login.gov-gated
registration, sent as Authorization: Basic <token> on the fallback attempt
only. Stored in the encrypted platform_keys table (no Worker secret binding
— the gateway is at its text-binding cap), injected as _apiKey when a
caller supplies none.
The token expires 2026-10-08T04:00:00Z. Because it is fallback-only, this
is NOT the operational cliff it would be for an always-token design: the pack
keeps answering real data with no credential at all unless and until EDIS’s
keyless route itself closes. If it ever does close and a fallback is needed,
the pack checks the token’s own exp claim (base64url, no signature check
needed — reading our own token) before sending it, and refuses explicitly —
auth_required: USITC EDIS requires an API key: the keyless route failed and the Pipeworx EDIS token expired on <date>... — rather than returning an
empty result. token_expires_at (and a token_warning under 3 days) appears
ONLY on a response that actually needed the fallback; an ordinary keyless
success carries neither, since nothing about the token was consulted.
Renewal is only needed if the keyless route closes. Procedure, as far as EDIS’s own docs establish it (unverified end to end — nobody has run it, and there is no reason to until the keyless route actually needs backup):
- Sign in at https://edis.usitc.gov/external/ via Login.gov — EDIS
accounts are login.gov-verified identities, not self-service API keys.
/external/registrationredirects tohttps://edis.usitc.gov/external/oauth2/authorization/logingov. - Once authenticated, the WADL (
https://edis.usitc.gov/data/, fetched keylessly) listsPOST secretKey/{username}(form parampassword) as the token-mint endpoint. - This pack, and whoever renews the key by hand, must NOT call that
endpoint speculatively or more than once per renewal — minting a new
secretKey may revoke whichever one is currently live. Mint it only when
actually renewing, immediately before updating
PLATFORM_EDIS_TOKEN. - Update the value in the
platform_keystable (seedocs/gateway-text-binding-limit.mdfor how platform-key-store entries without a Worker binding are set).
A platform-key-probes.json entry (usitc-edis → edis_document_list) is
pinned via PROBE_OVERRIDES in scripts/sync-platform-key-probes.mjs,
verified live 2026-09-24. Since edis_document_list is keyless-first, a pass
on this probe proves the keyless route this pack actually depends on
day-to-day is up — it does NOT specifically prove PLATFORM_EDIS_TOKEN is
alive, because a healthy keyless route means the fallback is never reached.
That is an intentional shift from what a platform-key probe usually means
here, noted explicitly so nobody re-derives the wrong assumption from the
filename.
Data sources
https://ids.usitc.gov/idata/api/v1/advanced-search(POST) — investigation search/list, paginated.https://ids.usitc.gov/idata/api/v1/investigation/{id}(GET) — full investigation detail.https://ids.usitc.gov/idata/api/v1/lookup/investigation-types(GET) — the 4 top-level type categories.https://edis.usitc.gov/data/document/document/{id}/detail/attachment/{documentId}(GET) — filed documents and attachment metadata, keyless. WADL athttps://edis.usitc.gov/data/.
Traps for the next builder
- edis.usitc.gov’s WAF 403s almost any User-Agent string, disguised as
“the site is down”. Verified live 2026-09-24, repeatedly: bare
curl(curl/8.7.1,curl/7.64.1) andpython-requests/2.31.0all get a clean 200; a blank UA,Wget/1.21, a full browser UA string, and this pack’s own plain identifying UA (pipeworx-usitc-edis/1.0 (+https://pipeworx.io)) all get HTTP 403 with USITC’s generic “under maintenance” HTML page — which reads exactly like an outage, not a UA filter. The match is a PREFIX, not an exact string:curl/8.7.1 pipeworx-usitc-edis/1.0 (+https://pipeworx.io)passes.EDIS_UAinsrc/index.tsis built that way on purpose — it is an honest identification (the pack names itself) composed to also clear whatever allowlist rule this is, not a literal impersonation of curl. If EDIS ever tightens this further, this is the first thing to re-check before assuming the whole route died. - A bad/malformed EDIS
Authorizationheader does not 401 — it also 503s the same generic “under maintenance” HTML page, so a rejected credential, genuine intermittent downtime, a UA-filter block, and (on IDS) a malformed request body are ALL indistinguishable from the response alone.edisGetKeylessFirstonly treats a response as a credential rejection when the STATUS is specifically 401/403 on the fallback attempt with a token attached; everything else (including a maintenance-page body) reads asupstream_down— retriable, not “rotate the key”. investigationNumbernormalization (EDIS only). Pass"337-TA-1400"in and every value EDIS itself returns (documentListUri, theinvestigationNumberfield on documents) comes back"337-1400"— EDIS drops"-TA-"internally.edis_document_listaccepts either spelling and normalizes before querying.- URL-encoding trap on IDS-adjacent EDIS endpoints (historical, not
currently exercised by this pack):
investigationType=Sec%20337(percent-encoded space) 400s;investigationType=Sec+337(plus-encoded) works.URLSearchParamsencodes spaces as+by construction, so a hand-built query string is the only way to hit this. - IDS’s
advanced-searchcriteriafilter DSL is unknown. The live Angular app (ids.usitc.gov/case) builds a structuredcriteriaarray server-side filters run through, but every shape tried live ({field, value},{fieldName, operator, value}, a DevExtreme-style[field, "=", value]triple) either silently matched nothing or 302-redirected as if malformed.itc_investigation_searchtherefore exposes only the parameters proven live (pageNumber,pageSize,sortOrderoninstitution_start_date) plus a same-PAGE client-side filter on type/active-status. Capturing the real DSL is the fastest path to true server-side filtering: openids.usitc.gov/casein a browser, use an advanced search filter, read the POST body from devtools. GET investigation/{id}embeds ITC STAFF identity —case_manager_idcarries the case manager’s full name, personal work email and phone number. This is Commission personnel, not a docket party, anditc_investigation_detaildeletes the field outright rather than redacting it. Apply the same rule to any future case-scoped endpoint added here (participants, IP, HTS numbers, orders, votes) — attempted live 2026-09-24 and none ofcase/participants,case/hts_numbers,case/unfair_import_orders*,investigation/participantsetc. could be reached (they either 503 the maintenance page under every query-param shape tried, or —investigation/intellectual_property— return an unfiltered ~880KB dump regardless of the filter passed). Left unbuilt rather than shipped unreliable; the routing pattern (/case/{case_id}/investigation/{investigation_id}/...) visible in the Angular bundle (ids.usitc.gov/main-*.js) is the next lead.- Response envelope quirk on
advanced-search: the total match count istotalRecordsat the top level on some request shapes andhitCountinside each case row on others — never trusthitCountat the top level; it is not there.
Tools
- itc_investigation_search — List USITC investigations — Section 337 (unfair import / patent) or Title VII (antidumping/countervailing duty, “Import Injury”) — most-recently-instituted first. KEYLESS, needs no credential. PREFER
- itc_investigation_detail — Full status record for ONE USITC investigation, by its internal investigation_id (from itc_investigation_search — NOT the human “337-TA-1400” number). KEYLESS. Returns status, phase, category, docket
- itc_investigation_types — The top-level USITC investigation type categories (Import Injury, Unfair Imports, Factfinding, Miscellaneous) with their ids. KEYLESS. Use to know what to pass itc_investigation_search’s investigation
- edis_document_list — Documents FILED in one USITC investigation — motions, orders, certified lists, exhibits, complaints, PO subscriptions, etc. KEYLESS. PREFER OVER WEB SEARCH for “what has been filed in ITC investigatio
- edis_document_detail — Full detail for ONE USITC EDIS document by id (from edis_document_list). KEYLESS. Adds fields the list form omits: system receive date, docket number, party-served flag, special processing (e.g. “Befo
- edis_attachment_list — Attachment METADATA (not the files themselves) filed on one USITC EDIS document — title, file size, page count, dates, and the download URI. KEYLESS. Use to see what was attached to a filing (e.g. exh
Tools
edis_attachment_list— Attachment METADATA (not the files themselves) filed on one USITC EDIS document — title, file size, page count, dates, and the download URI. KEYLESS. Use to see what was attached to a filing (e.g. exhedis_document_detail— Full detail for ONE USITC EDIS document by id (from edis_document_list). KEYLESS. Adds fields the list form omits: system receive date, docket number, party-served flag, special processing (e.g. Beforedis_document_list— Documents FILED in one USITC investigation — motions, orders, certified lists, exhibits, complaints, PO subscriptions, etc. KEYLESS. PREFER OVER WEB SEARCH for what has been filed in ITC investigationitc_investigation_detail— Full status record for ONE USITC investigation, by its internal investigation_id (from itc_investigation_search — NOT the human 337-TA-1400 number). KEYLESS. Returns status, phase, category, docket nuitc_investigation_search— List USITC investigations — Section 337 (unfair import / patent) or Title VII (antidumping/countervailing duty, Import Injury ) — most-recently-instituted first. KEYLESS, needs no credential. PREFER Oitc_investigation_types— The top-level USITC investigation type categories (Import Injury, Unfair Imports, Factfinding, Miscellaneous) with their ids. KEYLESS. Use to know what to pass itc_investigation_search's investigation