@cliwant/mcp-sam-gov 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ja.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @cliwant/mcp-sam-gov
2
2
 
3
3
  > **最も包括的なキーレス連邦データ MCP サーバー。**
4
- > SAM.gov · USAspending · SEC EDGAR · OFAC · FDIC · Federal Register · Regulations.gov · eCFR · FAR/DFARS · BLS · Treasury · NIH · NSF · ClinicalTrials · CMS · NVD/CISA · USITC · Census · FRED · BEA · DOL · FEMA · openFDA · NHTSA · CPSC · EPA Envirofacts · CourtListener · IRS-990(ProPublica) ほか **48 の連邦データソース、143 ツール。** キーレス優先 — Census business-patterns · FRED · BEA · DOL データエンドポイントの 4 ソースのみ無料キーが必要で、残り 44 ソースはキー不要。
4
+ > SAM.gov · USAspending · SEC EDGAR · OFAC · FDIC · Federal Register · Regulations.gov · eCFR · FAR/DFARS · BLS · Treasury · NIH · NSF · ClinicalTrials · CMS · NVD/CISA · USITC · Census · FRED · BEA · DOL · FEMA · openFDA · NHTSA · CPSC · EPA Envirofacts · CourtListener · IRS-990(ProPublica) ほか **48 の連邦データソース、144 ツール。** キーレス優先 — Census business-patterns · FRED · BEA · DOL データエンドポイントの 4 ソースのみ無料キーが必要で、残り 44 ソースはキー不要。
5
5
  > API キー不要、登録不要、サインアップ不要。Claude Desktop, Claude Code, Codex CLI, Cursor, Continue, Gemini CLI、すべての MCP ホスト対応。
6
6
 
7
7
  [English README](./README.md) · [한국어 README](./README.ko.md)
@@ -30,7 +30,7 @@
30
30
  | 🌐 **貿易・地理・災害** | "この品目の HTS 関税、この住所の Census tract、この州の FEMA 宣言" | USITC HTS, Census, FEMA, Socrata, CKAN |
31
31
  | 🎓 **grant・データセット** | "過去 30 日のサイバーセキュリティ grant、連邦オープンデータセット発見" | Grants.gov, data.gov |
32
32
 
33
- **48 の連邦データソース、合計 143 ツール — キーレス優先: Census business-patterns · FRED · BEA · DOL データエンドポイントの 4 ソースのみ無料キーが必要で、残り 44 ソースはキー不要。** (初期の 52 ツール版でおおよそ p50 ~0.25s / p95 ~0.8s を計測 — ソースや上流負荷で変動する近似値であり保証値ではありません。)
33
+ **48 の連邦データソース、合計 144 ツール — キーレス優先: Census business-patterns · FRED · BEA · DOL データエンドポイントの 4 ソースのみ無料キーが必要で、残り 44 ソースはキー不要。** (初期の 52 ツール版でおおよそ p50 ~0.25s / p95 ~0.8s を計測 — ソースや上流負荷で変動する近似値であり保証値ではありません。)
34
34
 
35
35
  ---
36
36
 
@@ -57,7 +57,7 @@ Claude Code (CLI) を既に使用している場合:
57
57
  /plugin install cliwant/mcp-sam-gov
58
58
  ```
59
59
 
60
- MCP サーバー + Claude が 143 ツールをいつ・どう呼ぶかを教える [SKILL.md ワークフローガイド](./skills/sam-gov/SKILL.md) を同時登録。
60
+ MCP サーバー + Claude が 144 ツールをいつ・どう呼ぶかを教える [SKILL.md ワークフローガイド](./skills/sam-gov/SKILL.md) を同時登録。
61
61
 
62
62
  ### 🔵 パス 3 — Codex / Cursor / Continue / Gemini 等の手動インストール
63
63
 
@@ -188,9 +188,9 @@ npm はインストール済みユーザーに新バージョンを通知しな
188
188
 
189
189
  **自動投稿は一切ありません。** サーバーにトークンもアカウントもなく、リンクを作るだけで、開いて送信するのは**あなた**です。事前入力リンクにはツール名・エラー種別・サーバーバージョンのみが含まれ、クエリ値は含まれません。公開リポジトリなので、機微な内容は削除してから送信してください。直接開く: [**New issue**](https://github.com/cliwant/mcp-sam-gov/issues/new/choose)。
190
190
 
191
- ## ツールカタログ (143)
191
+ ## ツールカタログ (144)
192
192
 
193
- ワークフロー別グループ。キーレス優先 — 大半はキー不要、Census business-patterns · FRED · BEA · DOL データエンドポイントは無料キーが必要。全 per-tool 一覧と入力 schema・誠実性 caveat の原文は [英語 README のカタログセクション](./README.md#tool-catalog-143-tools) を正とします。
193
+ ワークフロー別グループ。キーレス優先 — 大半はキー不要、Census business-patterns · FRED · BEA · DOL データエンドポイントは無料キーが必要。全 per-tool 一覧と入力 schema・誠実性 caveat の原文は [英語 README のカタログセクション](./README.md#tool-catalog-144-tools) を正とします。
194
194
 
195
195
  - **案件 + ソリシテーション — SAM.gov + Grants.gov (10)**: `sam_search_opportunities` `sam_search_shaping` `sam_get_opportunity` `sam_fetch_description` `sam_fetch_attachment_text` `sam_attachment_url` `sam_lookup_organization` `sam_lookup_notice_fields` `grants_search` `grants_get_opportunity`
196
196
  - **spending・受注・競合 — USAspending + FPDS + GAO (31)**: `usas_search_awards` `usas_search_individual_awards` `usas_get_award_detail` `usas_search_awards_by_recipient` `usas_search_subawards` `usas_search_recompetes` `usas_search_expiring_contracts`(deprecated) `usas_analyze_incumbent` `usas_search_teaming_partners` `usas_spending_over_time` `usas_search_agency_spending` `usas_search_subagency_spending` `usas_search_psc_spending` `usas_search_cfda_spending` `usas_search_state_spending` `usas_search_federal_account_spending` `usas_search_recipients` `usas_get_recipient_profile` `usas_get_agency_profile` `usas_get_agency_awards_summary` `usas_get_agency_budget_function` `usas_list_toptier_agencies` `usas_lookup_agency` `usas_autocomplete_naics` `usas_autocomplete_recipient` `usas_naics_hierarchy` `usas_glossary` `usas_list_disaster_codes`(災害緊急基金コード(DEFC)一覧 — COVID-19·IIJA/インフラ等の緊急歳出タグ) `usas_disaster_spending`(指定 DEFC の災害/緊急基金支出の地域別内訳 — どの州/郡/選挙区が COVID/IIJA 救済金を受領) `fpds_search_awards` `gao_protest_lookup`
package/README.ko.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @cliwant/mcp-sam-gov
2
2
 
3
3
  > **가장 포괄적인 keyless 연방 데이터 MCP 서버.**
4
- > SAM.gov · USAspending · SEC EDGAR · OFAC · FDIC · Federal Register · Regulations.gov · eCFR · FAR/DFARS · BLS · Treasury · NIH · NSF · ClinicalTrials · CMS · NVD/CISA · USITC · Census · FRED · BEA · DOL · FEMA · openFDA · NHTSA · CPSC · EPA Envirofacts · CourtListener · IRS-990(ProPublica) 외 **48개 연방 데이터 소스, 143개 도구.** keyless 우선 — Census business-patterns · FRED · BEA · DOL 데이터 엔드포인트 4개 소스만 무료 키가 필요하고 나머지 44개 소스는 키가 필요 없습니다.
4
+ > SAM.gov · USAspending · SEC EDGAR · OFAC · FDIC · Federal Register · Regulations.gov · eCFR · FAR/DFARS · BLS · Treasury · NIH · NSF · ClinicalTrials · CMS · NVD/CISA · USITC · Census · FRED · BEA · DOL · FEMA · openFDA · NHTSA · CPSC · EPA Envirofacts · CourtListener · IRS-990(ProPublica) 외 **48개 연방 데이터 소스, 144개 도구.** keyless 우선 — Census business-patterns · FRED · BEA · DOL 데이터 엔드포인트 4개 소스만 무료 키가 필요하고 나머지 44개 소스는 키가 필요 없습니다.
5
5
  > API 키 / 등록 / 가입 불필요. Claude Desktop, Claude Code, Codex CLI, Cursor, Continue, Gemini CLI, 모든 MCP 호스트 호환.
6
6
 
7
7
  [English README](./README.md) · [日本語 README](./README.ja.md)
@@ -30,7 +30,7 @@
30
30
  | 🌐 **무역·지리·재난** | "이 품목 HTS 관세, 이 주소 Census tract, 이 주의 FEMA 선포" | USITC HTS, Census, FEMA, Socrata, CKAN |
31
31
  | 🎓 **grant·데이터셋** | "최근 30일 사이버보안 grant, 연방 오픈 데이터셋 발굴" | Grants.gov, data.gov |
32
32
 
33
- **48개 연방 데이터 소스, 총 143개 도구 — keyless 우선: Census business-patterns · FRED · BEA · DOL 데이터 엔드포인트 4개 소스만 무료 키가 필요하고 나머지 44개 소스는 키가 필요 없습니다.** (초기 52-도구 빌드 기준 대략 p50 ~0.25s / p95 ~0.8s 측정 — 소스·업스트림 부하에 따라 변동하는 근사치이며 보장값이 아님.)
33
+ **48개 연방 데이터 소스, 총 144개 도구 — keyless 우선: Census business-patterns · FRED · BEA · DOL 데이터 엔드포인트 4개 소스만 무료 키가 필요하고 나머지 44개 소스는 키가 필요 없습니다.** (초기 52-도구 빌드 기준 대략 p50 ~0.25s / p95 ~0.8s 측정 — 소스·업스트림 부하에 따라 변동하는 근사치이며 보장값이 아님.)
34
34
 
35
35
  ---
36
36
 
@@ -57,7 +57,7 @@ PowerShell, npm 등 필요 없음.
57
57
  /plugin install cliwant/mcp-sam-gov
58
58
  ```
59
59
 
60
- MCP 서버 + Claude 가 143개 도구를 언제 / 어떻게 호출할지 가르치는 [SKILL.md 워크플로 가이드](./skills/sam-gov/SKILL.md) 동시 등록.
60
+ MCP 서버 + Claude 가 144개 도구를 언제 / 어떻게 호출할지 가르치는 [SKILL.md 워크플로 가이드](./skills/sam-gov/SKILL.md) 동시 등록.
61
61
 
62
62
  ### 🔵 경로 3 — Codex / Cursor / Continue / Gemini 등 수동 설치
63
63
 
@@ -188,9 +188,9 @@ npm은 설치한 사용자에게 새 버전을 알려주지 않으므로, 서버
188
188
 
189
189
  **자동 제출은 절대 없습니다.** 서버엔 토큰·계정이 없고 링크만 만들며, 열어서 제출하는 건 **사용자**입니다. 프리필 링크에는 툴명·에러종류·서버버전만 담기고 쿼리값은 담기지 않습니다. 공개 레포이니 민감한 내용은 지우고 제출하세요. 직접 열기: [**New issue**](https://github.com/cliwant/mcp-sam-gov/issues/new/choose).
190
190
 
191
- ## 도구 카탈로그 (143개)
191
+ ## 도구 카탈로그 (144개)
192
192
 
193
- 워크플로별 그룹. keyless 우선 — 대부분 키가 필요 없고, Census business-patterns · FRED · BEA · DOL 데이터 엔드포인트는 무료 키가 필요합니다. 전체 per-tool 목록과 입력 schema·정직성 caveat 원문은 [영문 README 의 카탈로그 섹션](./README.md#tool-catalog-143-tools)을 기준으로 하세요.
193
+ 워크플로별 그룹. keyless 우선 — 대부분 키가 필요 없고, Census business-patterns · FRED · BEA · DOL 데이터 엔드포인트는 무료 키가 필요합니다. 전체 per-tool 목록과 입력 schema·정직성 caveat 원문은 [영문 README 의 카탈로그 섹션](./README.md#tool-catalog-144-tools)을 기준으로 하세요.
194
194
 
195
195
  - **입찰 + 솔리시테이션 — SAM.gov + Grants.gov (10)**: `sam_search_opportunities` `sam_search_shaping` `sam_get_opportunity` `sam_fetch_description` `sam_fetch_attachment_text` `sam_attachment_url` `sam_lookup_organization` `sam_lookup_notice_fields` `grants_search` `grants_get_opportunity`
196
196
  - **spending·수주·경쟁 — USAspending + FPDS + GAO (31)**: `usas_search_awards` `usas_search_individual_awards` `usas_get_award_detail` `usas_search_awards_by_recipient` `usas_search_subawards` `usas_search_recompetes` `usas_search_expiring_contracts`(deprecated) `usas_analyze_incumbent` `usas_search_teaming_partners` `usas_spending_over_time` `usas_search_agency_spending` `usas_search_subagency_spending` `usas_search_psc_spending` `usas_search_cfda_spending` `usas_search_state_spending` `usas_search_federal_account_spending` `usas_search_recipients` `usas_get_recipient_profile` `usas_get_agency_profile` `usas_get_agency_awards_summary` `usas_get_agency_budget_function` `usas_list_toptier_agencies` `usas_lookup_agency` `usas_autocomplete_naics` `usas_autocomplete_recipient` `usas_naics_hierarchy` `usas_glossary` `usas_list_disaster_codes`(재난긴급자금코드(DEFC) 목록 — COVID-19·IIJA/인프라 등 긴급세출 태그) `usas_disaster_spending`(지정 DEFC의 재난/긴급자금 지출 지역별 분해 — 어느 주/카운티/선거구가 COVID/IIJA 구호금 수령) `fpds_search_awards` `gao_protest_lookup`
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  ### **$4 trillion of public federal data, one `npm install` away.**
6
6
 
7
- The most comprehensive **keyless-first** MCP server for US federal contracting + spending + regulation + partner vetting. **143 tools across 48 federal data sources** — keyless-first: only 4 sources (Census business-patterns, FRED, BEA, and DOL's data endpoint) need a free key; the other 44 need none. Works today, in any AI agent.
7
+ The most comprehensive **keyless-first** MCP server for US federal contracting + spending + regulation + partner vetting. **144 tools across 48 federal data sources** — keyless-first: only 4 sources (Census business-patterns, FRED, BEA, and DOL's data endpoint) need a free key; the other 44 need none. Works today, in any AI agent.
8
8
 
9
9
  [![npm](https://img.shields.io/npm/v/@cliwant/mcp-sam-gov?color=cb3837&label=%40cliwant%2Fmcp-sam-gov&logo=npm)](https://www.npmjs.com/package/@cliwant/mcp-sam-gov)
10
10
  [![mcp-registry](https://img.shields.io/badge/MCP%20Registry-active-2ea44f?logo=anthropic)](https://registry.modelcontextprotocol.io/v0/servers?search=cliwant)
@@ -50,7 +50,7 @@ The most comprehensive **keyless-first** MCP server for US federal contracting +
50
50
  |---|---|
51
51
  | GovWin: $30K-$100K/yr per seat | Free, MIT license |
52
52
  | API key registration → wait 24h → quota tier shopping | `npm install` → working in 60s |
53
- | 5+ separate vendor APIs / scrapers | 1 unified surface, 143 tools across 48 sources |
53
+ | 5+ separate vendor APIs / scrapers | 1 unified surface, 144 tools across 48 sources |
54
54
  | LLMs hallucinate NAICS codes / agency names | Anti-hallucination autocomplete guards built-in |
55
55
  | Brittle scraping breaks weekly | Daily live smoke test ([badge above](#)) |
56
56
  | Procurement officer → IT ticket → 3-week wait | Claude Desktop double-click install |
@@ -79,7 +79,7 @@ The federal data this wraps is **public domain**. There is no good reason it sho
79
79
  | 🌐 **Trade, geo & disaster** | "HTS tariff for this product; Census tract for this address; FEMA declarations in this state" | USITC HTS, US Census, FEMA, Socrata, CKAN |
80
80
  | 🎓 **Grants & datasets** | "Cybersecurity grants posted in the last 30 days; discover federal open datasets" | Grants.gov, data.gov |
81
81
 
82
- **143 tools across 48 federal data sources — keyless-first: only 4 sources (Census business-patterns, FRED, BEA, and DOL's data endpoint) need a free key; the other 44 need none.** (An earlier 52-tool build measured roughly p50 ~0.25s / p95 ~0.8s against production federal APIs; latency varies by source and upstream load — treat it as fast, not a benchmarked guarantee.)
82
+ **144 tools across 48 federal data sources — keyless-first: only 4 sources (Census business-patterns, FRED, BEA, and DOL's data endpoint) need a free key; the other 44 need none.** (An earlier 52-tool build measured roughly p50 ~0.25s / p95 ~0.8s against production federal APIs; latency varies by source and upstream load — treat it as fast, not a benchmarked guarantee.)
83
83
 
84
84
  ---
85
85
 
@@ -106,7 +106,7 @@ If you already use Claude Code (the CLI):
106
106
  /plugin install cliwant/mcp-sam-gov
107
107
  ```
108
108
 
109
- This installs the MCP server **plus** a [SKILL.md](./skills/sam-gov/SKILL.md) workflow guide that teaches Claude when + how to use each of the 143 tools.
109
+ This installs the MCP server **plus** a [SKILL.md](./skills/sam-gov/SKILL.md) workflow guide that teaches Claude when + how to use each of the 144 tools.
110
110
 
111
111
  ### 🔵 Path 3 — Manual install for any MCP host (Codex, Cursor, Continue, Gemini)
112
112
 
@@ -174,7 +174,7 @@ Then point your host config at the absolute path:
174
174
 
175
175
  (Or skip this entirely — use Path 1's `.mcpb` and it auto-configures.)
176
176
 
177
- Restart Claude Desktop fully (system tray quit on Windows / Quit menu on macOS), then look for the 🔨 icon. You should see "sam-gov (143 tools)".
177
+ Restart Claude Desktop fully (system tray quit on Windows / Quit menu on macOS), then look for the 🔨 icon. You should see "sam-gov (144 tools)".
178
178
 
179
179
  ### Claude Code
180
180
 
@@ -399,7 +399,7 @@ This server is built to **improve from real usage**. Because an AI agent (not a
399
399
 
400
400
  You can also open one directly: [**New issue**](https://github.com/cliwant/mcp-sam-gov/issues/new/choose) — bug / feature / wrong-output templates.
401
401
 
402
- ## Tool catalog (143 tools)
402
+ ## Tool catalog (144 tools)
403
403
 
404
404
  Grouped by workflow. Keyless-first — most tools need no key; Census business-patterns, FRED, BEA, and DOL's data endpoint require a free key, and a handful of others gain higher limits from an optional free key (noted above). Descriptions are condensed — each tool's own `inputSchema` carries the full contract and honesty caveats.
405
405
 
@@ -522,7 +522,8 @@ Grouped by workflow. Keyless-first — most tools need no key; Census business-p
522
522
  - `regulations_search_documents` — search Regulations.gov rulemaking documents (rules, proposed rules, notices)
523
523
  - `regulations_search_comments` — search public comments on rulemakings
524
524
  - `regulations_get_docket` — fetch one Regulations.gov docket by id
525
- - `ecfr_search` — full-text search across the entire CFR (titleNumber=48 for FAR)
525
+ - `ecfr_search` — full-text search across the entire CFR (titleNumber=48 for FAR); returns ranked snippets + ecfrUrl
526
+ - `ecfr_get_section` — the FULL text of one CFR section by citation (any title; for FAR/DFARS prefer `far_clause_lookup`)
526
527
  - `ecfr_list_titles` — all 50 CFR titles + last-amended dates
527
528
  - `far_clause_lookup` — authoritative FAR/DFARS clause text + its prescription (exact clause number)
528
529
  - `far_search` — FAR/DFARS-scoped search (excludes GSAM, collapses to current in-force version)
package/dist/ecfr.d.ts CHANGED
@@ -22,6 +22,20 @@ export declare function listTitles(): Promise<import("./meta.js").MetaBundle<{
22
22
  reserved: boolean;
23
23
  }[];
24
24
  }>>;
25
+ export declare function getSection(args: {
26
+ titleNumber: number;
27
+ section: string;
28
+ date?: string;
29
+ }): Promise<import("./meta.js").MetaBundle<{
30
+ titleNumber: number;
31
+ section: string;
32
+ citation: string | null;
33
+ alternateReference: string | null;
34
+ heading: string | null;
35
+ fullText: string;
36
+ issueDate: string;
37
+ ecfrUrl: string;
38
+ }>>;
25
39
  export declare function search(args: {
26
40
  query: string;
27
41
  titleNumber?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"ecfr.d.ts","sourceRoot":"","sources":["../src/ecfr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA2BH,wBAAsB,UAAU;;;;;;;;;IA0C/B;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;;;;;;;;;;;;;;;IAgJA"}
1
+ {"version":3,"file":"ecfr.d.ts","sourceRoot":"","sources":["../src/ecfr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA2BH,wBAAsB,UAAU;;;;;;;;;IA0C/B;AA2CD,wBAAsB,UAAU,CAAC,IAAI,EAAE;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;;;;;;;;;IA0GA;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;;;;;;;;;;;;;;;IAgJA"}
package/dist/ecfr.js CHANGED
@@ -12,7 +12,7 @@
12
12
  *
13
13
  * Both keyless. Documented at https://www.ecfr.gov/developers/.
14
14
  */
15
- import { fetchWithRetry } from "./errors.js";
15
+ import { fetchWithRetry, ToolErrorCarrier } from "./errors.js";
16
16
  import { driftError } from "./datasource.js";
17
17
  import { memoize } from "./cache.js";
18
18
  import { withMeta } from "./meta.js";
@@ -59,6 +59,132 @@ export async function listTitles() {
59
59
  });
60
60
  });
61
61
  }
62
+ // ─── ecfr_get_section — full in-force text of one CFR section ──────────────
63
+ // The eval-found gap: ecfr_search returns ranked SNIPPETS; there was no way to pull
64
+ // a clause's COMPLETE text. This fetches one section from the versioner `full`
65
+ // endpoint (a per-section XML, ~5KB), de-XMLed to plain text. A bespoke individual
66
+ // source (not the search API) — mode-2 discovery.
67
+ const ECFR_SECTION_RE = /^[0-9]{1,3}\.[0-9]{1,4}(-[0-9]{1,4})?$/;
68
+ const ECFR_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
69
+ async function fetchXmlText(url) {
70
+ const r = await fetchWithRetry(url, { headers: { Accept: "application/xml" }, signal: AbortSignal.timeout(20_000) }, `ecfr:${url.split("/api/")[1] ?? url}`);
71
+ return await r.text();
72
+ }
73
+ function decodeXmlEntities(s) {
74
+ return s
75
+ .replace(/&quot;/g, '"')
76
+ .replace(/&lt;/g, "<")
77
+ .replace(/&gt;/g, ">")
78
+ .replace(/&#39;/g, "'")
79
+ .replace(/&#(\d+);/g, (_, n) => String.fromCharCode(Number(n)))
80
+ .replace(/&amp;/g, "&");
81
+ }
82
+ // De-XML a section body to readable plain text: block tags → newlines, strip the
83
+ // rest, decode entities, drop empty lines. No fabrication — the eCFR's own text.
84
+ function xmlToPlainText(xml) {
85
+ return decodeXmlEntities(xml
86
+ .replace(/<\/(P|HD1|HD2|HD3|HD4|HEAD|FP|GID|GPOTABLE|ROW)>/gi, "\n")
87
+ .replace(/<[^>]+>/g, ""))
88
+ .split("\n")
89
+ .map((l) => l.trim())
90
+ .filter((l) => l.length > 0)
91
+ .join("\n");
92
+ }
93
+ export async function getSection(args) {
94
+ // SSRF/injection: `section` (+ derived `part`) interpolate into the URL query, so
95
+ // the charclass is the load-bearing guard. `titleNumber` is numeric (schema).
96
+ // `\s` reject is load-bearing: JS `$` also matches BEFORE a trailing "\n", so the
97
+ // charclass alone would admit "52.204-21\n". No valid section carries whitespace.
98
+ if (!ECFR_SECTION_RE.test(args.section) || /\s/.test(args.section)) {
99
+ throw new ToolErrorCarrier({
100
+ kind: "invalid_input",
101
+ retryable: false,
102
+ message: `Invalid section ${JSON.stringify(args.section)} — expected a CFR section like "52.204-21" or "12.301" (^[0-9]{1,3}\\.[0-9]{1,4}(-[0-9]{1,4})?$, no whitespace).`,
103
+ upstreamEndpoint: "ecfr:versioner/full",
104
+ });
105
+ }
106
+ let issueDate = args.date;
107
+ if (issueDate !== undefined && !ECFR_DATE_RE.test(issueDate)) {
108
+ throw new ToolErrorCarrier({
109
+ kind: "invalid_input",
110
+ retryable: false,
111
+ message: `Invalid date ${JSON.stringify(args.date)} — expected an eCFR issue date YYYY-MM-DD (omit to use the title's latest).`,
112
+ upstreamEndpoint: "ecfr:versioner/full",
113
+ });
114
+ }
115
+ if (!issueDate) {
116
+ // Resolve the title's latest issue date (memoized titles list) — DISCLOSED below.
117
+ const t = (await listTitles()).data.titles.find((x) => x.number === args.titleNumber);
118
+ issueDate = t?.latestIssueDate;
119
+ if (!issueDate) {
120
+ throw new ToolErrorCarrier({
121
+ kind: "invalid_input",
122
+ retryable: false,
123
+ message: `Title ${args.titleNumber} is not a known CFR title (or has no issue date). Verify it via ecfr_list_titles.`,
124
+ upstreamEndpoint: "ecfr:versioner/full",
125
+ });
126
+ }
127
+ }
128
+ const part = args.section.split(".")[0];
129
+ const url = `${ECFR}/versioner/v1/full/${issueDate}/title-${args.titleNumber}.xml?part=${encodeURIComponent(part)}&section=${encodeURIComponent(args.section)}`;
130
+ const xml = await fetchXmlText(url);
131
+ // Locate the SECTION DIV8 for EXACTLY this section (the endpoint may return the
132
+ // enclosing part). Absent ⇒ honest not_found, NEVER a fabricated empty/wrong text.
133
+ const escaped = args.section.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
134
+ const div = xml.match(new RegExp(`<DIV8 N="${escaped}"[^>]*TYPE="SECTION"[^>]*>([\\s\\S]*?)</DIV8>`, "i"));
135
+ if (!div) {
136
+ throw new ToolErrorCarrier({
137
+ kind: "not_found",
138
+ retryable: false,
139
+ message: `Section ${args.section} not found in CFR title ${args.titleNumber} as of the ${issueDate} issue. Verify the citation (e.g. via ecfr_search); the part number (${part}) must actually contain the section.`,
140
+ upstreamEndpoint: "ecfr:versioner/full",
141
+ });
142
+ }
143
+ const body = div[1];
144
+ const headMatch = body.match(/<HEAD>([\s\S]*?)<\/HEAD>/i);
145
+ const heading = headMatch ? xmlToPlainText(headMatch[1]).replace(/\n+/g, " ").trim() : null;
146
+ let citation = null;
147
+ let alternateReference = null;
148
+ const meta = xml.match(/hierarchy_metadata="([^"]*)"/i);
149
+ if (meta) {
150
+ try {
151
+ const hm = JSON.parse(decodeXmlEntities(meta[1]));
152
+ citation = hm.citation ?? null;
153
+ alternateReference = hm.alternate_reference ?? null;
154
+ }
155
+ catch {
156
+ /* metadata is advisory — its absence never blocks the text */
157
+ }
158
+ }
159
+ const fullText = xmlToPlainText(body);
160
+ if (fullText.length === 0) {
161
+ // A 200 with a section shell but no readable text ⇒ schema drift, not a fake empty.
162
+ throw driftError("ecfr:versioner/full", `The section ${args.section} DIV8 carried no extractable text — eCFR XML shape drift, never a fabricated empty section.`);
163
+ }
164
+ const ecfrUrl = `https://www.ecfr.gov/current/title-${args.titleNumber}/section-${args.section}`;
165
+ return withMeta({
166
+ titleNumber: args.titleNumber,
167
+ section: args.section,
168
+ citation,
169
+ alternateReference,
170
+ heading,
171
+ fullText,
172
+ issueDate,
173
+ ecfrUrl,
174
+ }, {
175
+ source: "ecfr.gov/api (versioner/v1/full)",
176
+ keylessMode: true,
177
+ returned: 1,
178
+ totalAvailable: 1,
179
+ truncated: false,
180
+ filtersApplied: ["titleNumber", "section"],
181
+ filtersDropped: [],
182
+ fieldsUnavailable: [],
183
+ notes: [
184
+ `Full in-force text of ${citation ?? `${args.titleNumber} CFR ${args.section}`} as of the ${issueDate} eCFR issue (the title's LATEST unless a date was supplied — a moving target). De-XMLed to plain text; no content fabricated — open ecfrUrl for the authoritative rendering.`,
185
+ ],
186
+ });
187
+ }
62
188
  export async function search(args) {
63
189
  const url = new URL(`${ECFR}/search/v1/results`);
64
190
  url.searchParams.set("query", args.query);
package/dist/ecfr.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ecfr.js","sourceRoot":"","sources":["../src/ecfr.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ecfr.js","sourceRoot":"","sources":["../src/ecfr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,MAAM,IAAI,GAAG,0BAA0B,CAAC;AAExC,4EAA4E;AAC5E,6EAA6E;AAC7E,4EAA4E;AAC5E,mEAAmE;AACnE,MAAM,oBAAoB,GAAG,KAAK,CAAC;AAEnC,KAAK,UAAU,SAAS,CAAI,GAAW;IACrC,MAAM,CAAC,GAAG,MAAM,cAAc,CAC5B,GAAG,EACH;QACE,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;QACvC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;KACpC,EACD,QAAQ,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CACvC,CAAC;IACF,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAM,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,sEAAsE;IACtE,OAAO,OAAO,CAAC,aAAa,EAAE,KAAK,IAAI,EAAE;QAWvC,MAAM,IAAI,GAAG,MAAM,SAAS,CAAO,GAAG,IAAI,2BAA2B,CAAC,CAAC;QACvE,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC7C,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC;YACrB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE;YAClB,eAAe,EAAE,CAAC,CAAC,iBAAiB;YACpC,eAAe,EAAE,CAAC,CAAC,iBAAiB;YACpC,YAAY,EAAE,CAAC,CAAC,gBAAgB;YAChC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ;SACvB,CAAC,CAAC,CAAC;QACJ,+EAA+E;QAC/E,2EAA2E;QAC3E,6EAA6E;QAC7E,+EAA+E;QAC/E,OAAO,QAAQ,CACb,EAAE,MAAM,EAAE,EACV;YACE,MAAM,EAAE,oCAAoC;YAC5C,WAAW,EAAE,IAAI;YACjB,QAAQ,EAAE,MAAM,CAAC,MAAM;YACvB,cAAc,EAAE,MAAM,CAAC,MAAM;YAC7B,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,EAAE;YAClB,cAAc,EAAE,EAAE;YAClB,KAAK,EAAE;gBACL,iIAAiI;aAClI;SACF,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,oFAAoF;AACpF,+EAA+E;AAC/E,mFAAmF;AACnF,kDAAkD;AAClD,MAAM,eAAe,GAAG,wCAAwC,CAAC;AACjE,MAAM,YAAY,GAAG,qBAAqB,CAAC;AAE3C,KAAK,UAAU,YAAY,CAAC,GAAW;IACrC,MAAM,CAAC,GAAG,MAAM,cAAc,CAC5B,GAAG,EACH,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,iBAAiB,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAC/E,QAAQ,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CACvC,CAAC;IACF,OAAO,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;AACxB,CAAC;AAED,SAAS,iBAAiB,CAAC,CAAS;IAClC,OAAO,CAAC;SACL,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;SAC9D,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,iFAAiF;AACjF,iFAAiF;AACjF,SAAS,cAAc,CAAC,GAAW;IACjC,OAAO,iBAAiB,CACtB,GAAG;SACA,OAAO,CAAC,oDAAoD,EAAE,IAAI,CAAC;SACnE,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAC3B;SACE,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;SAC3B,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAIhC;IACC,kFAAkF;IAClF,8EAA8E;IAC9E,kFAAkF;IAClF,kFAAkF;IAClF,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,gBAAgB,CAAC;YACzB,IAAI,EAAE,eAAe;YACrB,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,mBAAmB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,kHAAkH;YAC1K,gBAAgB,EAAE,qBAAqB;SACxC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC;IAC1B,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,gBAAgB,CAAC;YACzB,IAAI,EAAE,eAAe;YACrB,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,gBAAgB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,6EAA6E;YAC/H,gBAAgB,EAAE,qBAAqB;SACxC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,kFAAkF;QAClF,MAAM,CAAC,GAAG,CAAC,MAAM,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAC7C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,WAAW,CACrC,CAAC;QACF,SAAS,GAAG,CAAC,EAAE,eAAe,CAAC;QAC/B,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,gBAAgB,CAAC;gBACzB,IAAI,EAAE,eAAe;gBACrB,SAAS,EAAE,KAAK;gBAChB,OAAO,EAAE,SAAS,IAAI,CAAC,WAAW,mFAAmF;gBACrH,gBAAgB,EAAE,qBAAqB;aACxC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;IACzC,MAAM,GAAG,GAAG,GAAG,IAAI,sBAAsB,SAAS,UAAU,IAAI,CAAC,WAAW,aAAa,kBAAkB,CAAC,IAAI,CAAC,YAAY,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;IAChK,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;IACpC,gFAAgF;IAChF,mFAAmF;IACnF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IACpE,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CACnB,IAAI,MAAM,CAAC,YAAY,OAAO,+CAA+C,EAAE,GAAG,CAAC,CACpF,CAAC;IACF,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,gBAAgB,CAAC;YACzB,IAAI,EAAE,WAAW;YACjB,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,WAAW,IAAI,CAAC,OAAO,2BAA2B,IAAI,CAAC,WAAW,cAAc,SAAS,wEAAwE,IAAI,sCAAsC;YACpN,gBAAgB,EAAE,qBAAqB;SACxC,CAAC,CAAC;IACL,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAE,CAAC;IACrB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7F,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,IAAI,kBAAkB,GAAkB,IAAI,CAAC;IAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACxD,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAGhD,CAAC;YACF,QAAQ,GAAG,EAAE,CAAC,QAAQ,IAAI,IAAI,CAAC;YAC/B,kBAAkB,GAAG,EAAE,CAAC,mBAAmB,IAAI,IAAI,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,8DAA8D;QAChE,CAAC;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,oFAAoF;QACpF,MAAM,UAAU,CACd,qBAAqB,EACrB,eAAe,IAAI,CAAC,OAAO,6FAA6F,CACzH,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,sCAAsC,IAAI,CAAC,WAAW,YAAY,IAAI,CAAC,OAAO,EAAE,CAAC;IACjG,OAAO,QAAQ,CACb;QACE,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,QAAQ;QACR,kBAAkB;QAClB,OAAO;QACP,QAAQ;QACR,SAAS;QACT,OAAO;KACR,EACD;QACE,MAAM,EAAE,kCAAkC;QAC1C,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE,CAAC;QACX,cAAc,EAAE,CAAC;QACjB,SAAS,EAAE,KAAK;QAChB,cAAc,EAAE,CAAC,aAAa,EAAE,SAAS,CAAC;QAC1C,cAAc,EAAE,EAAE;QAClB,iBAAiB,EAAE,EAAE;QACrB,KAAK,EAAE;YACL,yBAAyB,QAAQ,IAAI,GAAG,IAAI,CAAC,WAAW,QAAQ,IAAI,CAAC,OAAO,EAAE,cAAc,SAAS,8KAA8K;SACpR;KACF,CACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAK5B;IACC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,oBAAoB,CAAC,CAAC;IACjD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5D,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,oEAAoE;QACpE,uDAAuD;QACvD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,kBAAkB,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IACrE,CAAC;IACD,8EAA8E;IAC9E,8EAA8E;IAC9E,uEAAuE;IACvE,+EAA+E;IAC/E,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC/B,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACnE,CAAC;IA4BD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAO,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IACnD,+EAA+E;IAC/E,gFAAgF;IAChF,6EAA6E;IAC7E,kFAAkF;IAClF,8EAA8E;IAC9E,iFAAiF;IACjF,wEAAwE;IACxE,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/D,MAAM,UAAU,CACd,UAAU,EACV,qHAAqH,CACtH,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC1D,MAAM,UAAU,CACd,UAAU,EACV,+JAA+J,CAChK,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG;QACX,OAAO,EAAE,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACxC,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE;YAClB,KAAK,EAAE,CAAC,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;YAC/B,OAAO,EAAE,CAAC,CAAC,SAAS,EAAE,OAAO;YAC7B,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,IAAI;YACvB,OAAO,EAAE,CAAC,CAAC,SAAS,EAAE,OAAO;YAC7B,OAAO,EAAE,CAAC,CAAC,SAAS,EAAE,OAAO;YAC7B,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,IAAI,EAAE,CAAC;iBACnD,MAAM,CAAC,OAAO,CAAC;iBACf,IAAI,CAAC,KAAK,CAAC;YACd,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,iBAAiB,IAAI,EAAE,CAAC;YAC7C,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;YACnB,iDAAiD;YACjD,OAAO,EAAE,CAAC,CAAC,SAAS;gBAClB,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC3B,CAAC,CAAC,EAAE;YACN,WAAW,EAAE,CAAC,CAAC,SAAS,IAAI,EAAE;YAC9B,2EAA2E;YAC3E,0EAA0E;YAC1E,4EAA4E;YAC5E,2EAA2E;YAC3E,MAAM,EAAE,CAAC,CAAC,OAAO,IAAI,IAAI;SAC1B,CAAC,CAAC;KACJ,CAAC;IAEF,qEAAqE;IACrE,kEAAkE;IAClE,yEAAyE;IACzE,uEAAuE;IACvE,2EAA2E;IAC3E,2DAA2D;IAC3D,wEAAwE;IACxE,2EAA2E;IAC3E,6EAA6E;IAC7E,6EAA6E;IAC7E,iFAAiF;IACjF,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IACrC,MAAM,cAAc,GAClB,OAAO,IAAI,CAAC,IAAI,EAAE,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5E,6EAA6E;IAC7E,8EAA8E;IAC9E,6EAA6E;IAC7E,yEAAyE;IACzE,yBAAyB;IACzB,MAAM,iBAAiB,GACrB,cAAc,KAAK,IAAI,IAAI,cAAc,IAAI,oBAAoB,CAAC;IACpE,MAAM,SAAS,GACb,IAAI,CAAC,WAAW,KAAK,SAAS;QAC5B,CAAC,CAAC,sBAAsB,IAAI,CAAC,WAAW,GACpC,IAAI,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC,CAAC,yCAAyC,CAAC,CAAC,CAAC,EACxE,OAAO;QACT,CAAC,CAAC,mDAAmD,CAAC;IAC1D,MAAM,KAAK,GAAG,CAAC,SAAS,CAAC,CAAC;IAC1B,kFAAkF;IAClF,kFAAkF;IAClF,uEAAuE;IACvE,KAAK,CAAC,IAAI,CACR,2TAA2T,CAC5T,CAAC;IACF,IAAI,iBAAiB,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CACR,4BAA4B,oBAAoB,wMAAwM,CACzP,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,EAAE;QACpB,MAAM,EAAE,0BAA0B;QAClC,WAAW,EAAE,IAAI;QACjB,QAAQ;QACR,cAAc;QACd,wEAAwE;QACxE,0EAA0E;QAC1E,gEAAgE;QAChE,iBAAiB;QACjB,SAAS,EACP,cAAc,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,GAAG,cAAc,CAAC,CAAC,CAAC,SAAS;QACjE,cAAc,EAAE,IAAI,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE;QACrE,cAAc,EAAE,EAAE;QAClB,iBAAiB,EAAE,EAAE;QACrB,KAAK;KACN,CAAC,CAAC;AACL,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC;SACL,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,YAAY,CAAC,CAKrB;IACC,MAAM,IAAI,GAAG,sCAAsC,CAAC,CAAC,KAAK,EAAE,CAAC;IAC7D,IAAI,CAAC,CAAC,OAAO;QAAE,OAAO,GAAG,IAAI,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;IACrD,IAAI,CAAC,CAAC,IAAI;QAAE,OAAO,GAAG,IAAI,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,IAAI,CAAC,CAAC,OAAO;QAAE,OAAO,GAAG,IAAI,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;IACrD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;GAgBG;AAQH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,YAAY,EAKb,MAAM,oBAAoB,CAAC;AA66I5B,KAAK,OAAO,GAAG;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,CAAC,CAAC,UAAU,CAAC;IAO1B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE;QAAE,GAAG,EAAE,YAAY,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACxE,CAAC;AAoBF,eAAO,MAAM,KAAK,EAAE,OAAO,EA6vD1B,CAAC;AAkLF,wBAAsB,OAAO,CAC3B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,GAAG,EAAE,YAAY,GAChB,OAAO,CAAC,OAAO,CAAC,CAkClB"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;GAgBG;AAQH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,YAAY,EAKb,MAAM,oBAAoB,CAAC;AA67I5B,KAAK,OAAO,GAAG;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,CAAC,CAAC,UAAU,CAAC;IAO1B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE;QAAE,GAAG,EAAE,YAAY,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACxE,CAAC;AAoBF,eAAO,MAAM,KAAK,EAAE,OAAO,EAowD1B,CAAC;AAkLF,wBAAsB,OAAO,CAC3B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,GAAG,EAAE,YAAY,GAChB,OAAO,CAAC,OAAO,CAAC,CAkClB"}
package/dist/server.js CHANGED
@@ -86,7 +86,7 @@ import { realpathSync } from "node:fs";
86
86
  const SERVER_NAME = "mcp-sam-gov";
87
87
  // Kept in lockstep with package.json / manifest.json / server.json.
88
88
  // Keep in sync with package.json "version" (asserted at release; see CHANGELOG).
89
- const SERVER_VERSION = "1.8.0";
89
+ const SERVER_VERSION = "1.9.0";
90
90
  // ─── Tool input schemas (Zod) ────────────────────────────────────
91
91
  const SamSearchInput = z.object({
92
92
  query: z.string().optional().describe("Free-text title query"),
@@ -456,6 +456,21 @@ const EcfrSearchInput = z.object({
456
456
  perPage: z.number().min(1).max(20).optional(),
457
457
  });
458
458
  const EcfrListTitlesInput = z.object({});
459
+ const EcfrGetSectionInput = z.object({
460
+ titleNumber: z
461
+ .number()
462
+ .int()
463
+ .min(1)
464
+ .max(50)
465
+ .describe("CFR title (1–50). e.g. 2 = federal financial assistance (grants), 29 = Labor, 26 = IRS. For FAR/DFARS (title 48) prefer far_clause_lookup."),
466
+ section: z
467
+ .string()
468
+ .describe("The section citation, e.g. '200.1' (2 CFR 200.1) or '52.204-21' — the part number is the pre-dot integer. Charclass-validated (^[0-9]{1,3}\\.[0-9]{1,4}(-[0-9]{1,4})?$)."),
469
+ date: z
470
+ .string()
471
+ .optional()
472
+ .describe("Optional eCFR issue date YYYY-MM-DD; omit to use the title's LATEST issue (disclosed in _meta)."),
473
+ });
459
474
  // FAR / DFARS clause lookup (eCFR versioner full endpoint)
460
475
  const FarClauseLookupInput = z.object({
461
476
  clauseNumber: z
@@ -4507,13 +4522,19 @@ export const TOOLS = [
4507
4522
  inputSchema: FedRegPublicInspectionInput,
4508
4523
  handler: (input) => fedreg.publicInspection(input),
4509
4524
  }),
4510
- // ━━━ eCFR (5) ━━━
4525
+ // ━━━ eCFR (6) ━━━
4511
4526
  defineTool({
4512
4527
  name: "ecfr_search",
4513
- description: "Full-text search across the entire CFR (Code of Federal Regulations). Use for compliance questions — pass titleNumber=48 for FAR (Federal Acquisition Regulation), titleNumber=2 for federal financial assistance, etc. Returns excerpt + section path + ecfrUrl.",
4528
+ description: "Full-text search across the entire CFR (Code of Federal Regulations). Use for DISCOVERY — pass titleNumber=48 for FAR (Federal Acquisition Regulation), titleNumber=2 for federal financial assistance, etc. Returns a ranked EXCERPT (snippet, not full text) + section path + ecfrUrl per hit. To then read the COMPLETE text of a hit: for a FAR/DFARS clause (title 48) use far_clause_lookup (adds prescription + revision); for any other title's section use ecfr_get_section; or open the ecfrUrl.",
4514
4529
  inputSchema: EcfrSearchInput,
4515
4530
  handler: (input) => ecfr.search(input),
4516
4531
  }),
4532
+ defineTool({
4533
+ name: "ecfr_get_section",
4534
+ description: "Get the FULL in-force text of ONE CFR section by citation (the companion to ecfr_search, which returns only snippets). Input titleNumber (1–50) + section (e.g. '200.1' → 2 CFR 200.1, uniform grants guidance; '1601.1' → 29 CFR labor) + optional issue date (default = the title's latest). Returns { citation, alternateReference, heading, fullText, issueDate, ecfrUrl }. ★For a FAR/DFARS clause (title 48) prefer far_clause_lookup — it adds the prescription, revision, and FAR-overhaul-risk this generic tool does not; use ecfr_get_section for the OTHER 49 titles (grants/labor/IRS/SBA/…). HONESTY: text is the eCFR's own, de-XMLed (no fabrication); a nonexistent section ⇒ not_found (never a fake/wrong section); the resolved issue date is disclosed (the title's latest is a moving target); a bad section format ⇒ invalid_input (SSRF charclass); an outage ⇒ throws. Keyless.",
4535
+ inputSchema: EcfrGetSectionInput,
4536
+ handler: (input) => ecfr.getSection(input),
4537
+ }),
4517
4538
  defineTool({
4518
4539
  name: "ecfr_list_titles",
4519
4540
  description: "List all 50 CFR titles with name + last_amended_on date. Use to discover what's in each title (Title 48 = FAR, Title 32 = National Defense, Title 14 = Aeronautics, etc.).",