@cliwant/mcp-sam-gov 1.14.0 → 1.16.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 +3 -2
- package/README.ko.md +3 -2
- package/README.md +7 -5
- package/dist/arcgis-feature.d.ts.map +1 -1
- package/dist/arcgis-feature.js +8 -0
- package/dist/arcgis-feature.js.map +1 -1
- package/dist/bonfire.d.ts +1 -1
- package/dist/bonfire.d.ts.map +1 -1
- package/dist/bonfire.js +19 -17
- package/dist/bonfire.js.map +1 -1
- package/dist/ckan.d.ts +6 -4
- package/dist/ckan.d.ts.map +1 -1
- package/dist/ckan.js +17 -4
- package/dist/ckan.js.map +1 -1
- package/dist/data-map.d.ts +43 -0
- package/dist/data-map.d.ts.map +1 -0
- package/dist/data-map.js +344 -0
- package/dist/data-map.js.map +1 -0
- package/dist/fpds.d.ts.map +1 -1
- package/dist/fpds.js +3 -2
- package/dist/fpds.js.map +1 -1
- package/dist/gao.d.ts.map +1 -1
- package/dist/gao.js +17 -6
- package/dist/gao.js.map +1 -1
- package/dist/gsa-perdiem.d.ts +5 -0
- package/dist/gsa-perdiem.d.ts.map +1 -1
- package/dist/gsa-perdiem.js +6 -1
- package/dist/gsa-perdiem.js.map +1 -1
- package/dist/open-checkbook.d.ts +8 -0
- package/dist/open-checkbook.d.ts.map +1 -1
- package/dist/open-checkbook.js +9 -1
- package/dist/open-checkbook.js.map +1 -1
- package/dist/pricing.d.ts +1 -0
- package/dist/pricing.d.ts.map +1 -1
- package/dist/pricing.js +135 -50
- package/dist/pricing.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +76 -24
- package/dist/server.js.map +1 -1
- package/dist/socrata.d.ts +16 -1
- package/dist/socrata.d.ts.map +1 -1
- package/dist/socrata.js +76 -1
- package/dist/socrata.js.map +1 -1
- package/package.json +1 -1
- package/src/arcgis-feature.ts +8 -0
- package/src/bonfire.ts +19 -17
- package/src/ckan.ts +17 -4
- package/src/data-map.ts +386 -0
- package/src/fpds.ts +3 -2
- package/src/gao.ts +20 -6
- package/src/gsa-perdiem.ts +12 -1
- package/src/open-checkbook.ts +26 -3
- package/src/pricing.ts +142 -48
- package/src/server.ts +88 -23
- package/src/socrata.ts +83 -1
package/src/data-map.ts
ADDED
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State & local data map — single source of truth.
|
|
3
|
+
*
|
|
4
|
+
* These entries are exported for:
|
|
5
|
+
* (a) the MCP resource samgov://data-map/state-local (resources/read)
|
|
6
|
+
* (b) consistency tests (SKILL.md table must agree on domain/id/rows)
|
|
7
|
+
*
|
|
8
|
+
* Keep verified row counts and notes current here only; SKILL.md table and
|
|
9
|
+
* the resource content are generated from this array.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export type DataMapTool =
|
|
13
|
+
| "socrata_query"
|
|
14
|
+
| "ckan_query"
|
|
15
|
+
| "tableau_view_csv"
|
|
16
|
+
| "open_checkbook_search";
|
|
17
|
+
|
|
18
|
+
export interface DataMapEntry {
|
|
19
|
+
/** Two-letter state abbreviation for grouping */
|
|
20
|
+
state: string;
|
|
21
|
+
/** Human-readable jurisdiction name */
|
|
22
|
+
jurisdiction: string;
|
|
23
|
+
/** Short description of what the dataset contains */
|
|
24
|
+
dataLabel: string;
|
|
25
|
+
/** Tool to call */
|
|
26
|
+
tool: DataMapTool;
|
|
27
|
+
/** Key args to pass — human-readable form for doc */
|
|
28
|
+
keyArgs: string;
|
|
29
|
+
/** Verified approximate row count (null = not precisely known) */
|
|
30
|
+
rows: number | null;
|
|
31
|
+
/** Approximate flag — when true prefix rows with '~' */
|
|
32
|
+
approximate: boolean;
|
|
33
|
+
/** What this dataset is NOT (common agent error) */
|
|
34
|
+
notNote: string;
|
|
35
|
+
/** Extra notes (optional) */
|
|
36
|
+
extra?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Verified 2026-09-21 — all keyless.
|
|
41
|
+
*/
|
|
42
|
+
export const DATA_MAP_ENTRIES: DataMapEntry[] = [
|
|
43
|
+
// ── State-level ──────────────────────────────────────────────────────────
|
|
44
|
+
{
|
|
45
|
+
state: "CA",
|
|
46
|
+
jurisdiction: "California",
|
|
47
|
+
dataLabel: "DGS Purchase Order Data 2012–2015",
|
|
48
|
+
tool: "ckan_query",
|
|
49
|
+
keyArgs: "host=data.ca.gov, resourceId=bb82edc5-9c78-44e2-8947-68ece26197c5",
|
|
50
|
+
rows: 344504,
|
|
51
|
+
approximate: false,
|
|
52
|
+
notNote: "live Cal eProcure portal (WAF-403); FY2012–2015 only — no post-2015 rows",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
state: "CA",
|
|
56
|
+
jurisdiction: "California",
|
|
57
|
+
dataLabel: "DGS-Approved Non-Competitive Bids",
|
|
58
|
+
tool: "ckan_query",
|
|
59
|
+
keyArgs: "host=data.ca.gov, resourceId=14932789-485b-481b-910a-dafb40d3471c",
|
|
60
|
+
rows: 480,
|
|
61
|
+
approximate: false,
|
|
62
|
+
notNote: "open competitive solicitations; sole-source/non-competitive award register",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
state: "OK",
|
|
66
|
+
jurisdiction: "Oklahoma",
|
|
67
|
+
dataLabel: "Vendor Payments FY2019 Q1 (OMES)",
|
|
68
|
+
tool: "ckan_query",
|
|
69
|
+
keyArgs: "host=data.ok.gov, resourceId=cc443616-15eb-4a1f-8d87-93e5711ac43c",
|
|
70
|
+
rows: 286185,
|
|
71
|
+
approximate: false,
|
|
72
|
+
notNote: "bids or awards; vendor PAYMENTS — per-quarter resources, one fiscal year = 4 calls",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
state: "VA",
|
|
76
|
+
jurisdiction: "Virginia",
|
|
77
|
+
dataLabel: "eVA PO line items 2023",
|
|
78
|
+
tool: "ckan_query",
|
|
79
|
+
keyArgs: "host=data.virginia.gov, resourceId=3c7f1bde-35b0-4fbf-b89c-978a19124d53",
|
|
80
|
+
rows: 1693227,
|
|
81
|
+
approximate: false,
|
|
82
|
+
notNote: "the live eVA portal (login-gated)",
|
|
83
|
+
extra:
|
|
84
|
+
"Years 2016–2026 have separate resourceIds; ckan_discover_datasets host=data.virginia.gov q=eVA procurement lists them (2024=25a59527, 2025=b8dc22a8, 2026=76f6831d)",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
state: "MA",
|
|
88
|
+
jurisdiction: "Massachusetts",
|
|
89
|
+
dataLabel: "Comptroller vendor payments (CTHRU)",
|
|
90
|
+
tool: "socrata_query",
|
|
91
|
+
keyArgs: "domain=cthru.data.socrata.com, datasetId=pegc-naaa",
|
|
92
|
+
rows: 49000000,
|
|
93
|
+
approximate: true,
|
|
94
|
+
notNote: "an award or bid register; these are payment transactions",
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
state: "NJ",
|
|
98
|
+
jurisdiction: "New Jersey",
|
|
99
|
+
dataLabel: "YourMoney agency purchasing by vendor",
|
|
100
|
+
tool: "socrata_query",
|
|
101
|
+
keyArgs: "domain=data.nj.gov, datasetId=ubnu-tqu7",
|
|
102
|
+
rows: 660425,
|
|
103
|
+
approximate: false,
|
|
104
|
+
notNote: "a solicitation or bid register; agency expenditure rows",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
state: "NY",
|
|
108
|
+
jurisdiction: "New York",
|
|
109
|
+
dataLabel: "State authority procurement contracts",
|
|
110
|
+
tool: "socrata_query",
|
|
111
|
+
keyArgs: "domain=data.ny.gov, datasetId=ehig-g5x3",
|
|
112
|
+
rows: 275763,
|
|
113
|
+
approximate: false,
|
|
114
|
+
notNote: "all NYS agencies (authorities only) and NOT active solicitations",
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
state: "NY",
|
|
118
|
+
jurisdiction: "New York",
|
|
119
|
+
dataLabel: "MTA procurement contracts",
|
|
120
|
+
tool: "socrata_query",
|
|
121
|
+
keyArgs: "domain=data.ny.gov, datasetId=twsw-2mqa",
|
|
122
|
+
rows: 107503,
|
|
123
|
+
approximate: false,
|
|
124
|
+
notNote: "a live MTA bid portal; MTA historical contract records",
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
state: "WA",
|
|
128
|
+
jurisdiction: "Washington",
|
|
129
|
+
dataLabel: "Agency contract register",
|
|
130
|
+
tool: "socrata_query",
|
|
131
|
+
keyArgs: "domain=data.wa.gov, datasetId=s8d5-pj78",
|
|
132
|
+
rows: 79329,
|
|
133
|
+
approximate: false,
|
|
134
|
+
notNote: "a solicitation or bid feed; awarded contract records",
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
state: "WA",
|
|
138
|
+
jurisdiction: "Washington",
|
|
139
|
+
dataLabel: "Master-contract sales by vendor/customer",
|
|
140
|
+
tool: "socrata_query",
|
|
141
|
+
keyArgs: "domain=data.wa.gov, datasetId=n8q6-4twj",
|
|
142
|
+
rows: 245831,
|
|
143
|
+
approximate: false,
|
|
144
|
+
notNote: "open bids; sales reported off statewide master contracts",
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
state: "MT",
|
|
148
|
+
jurisdiction: "Montana",
|
|
149
|
+
dataLabel: "DOA contracts awarded",
|
|
150
|
+
tool: "tableau_view_csv",
|
|
151
|
+
keyArgs: "view=mt_contracts_awarded",
|
|
152
|
+
rows: 4554,
|
|
153
|
+
approximate: true,
|
|
154
|
+
notNote: "a bid portal; awarded records only, freshness set by publisher",
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
state: "SD",
|
|
158
|
+
jurisdiction: "South Dakota",
|
|
159
|
+
dataLabel: "Open Checkbook vendor payments",
|
|
160
|
+
tool: "open_checkbook_search",
|
|
161
|
+
keyArgs: "portal=sd",
|
|
162
|
+
rows: 741000,
|
|
163
|
+
approximate: true,
|
|
164
|
+
notNote: "an award register; only ~3 most-recent FYs, exact-match filters",
|
|
165
|
+
},
|
|
166
|
+
// ── Alaska — verified 2026-09-21 ─────────────────────────────────────────
|
|
167
|
+
{
|
|
168
|
+
state: "AK",
|
|
169
|
+
jurisdiction: "Alaska",
|
|
170
|
+
dataLabel: "Open Checkbook vendor payments (FY2026 ONLY)",
|
|
171
|
+
tool: "open_checkbook_search",
|
|
172
|
+
keyArgs: "portal=ak, year=2026",
|
|
173
|
+
rows: 41751,
|
|
174
|
+
approximate: false,
|
|
175
|
+
notNote:
|
|
176
|
+
"historical FY coverage — ONLY FY2026 is published by this portal. FY2019–FY2025 return count:0, meaning 'not published', NOT 'no spending'. Probed years 2019–2026 and no-year on 2026-09-21: 2019–2025 = 0 rows each; 2026 = 41,751 rows ($1,179,091,896.12); no-year = 0 rows. Always pass year='2026' to get results.",
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
state: "IL",
|
|
180
|
+
jurisdiction: "Illinois",
|
|
181
|
+
dataLabel: "CDB capital project future bids",
|
|
182
|
+
tool: "socrata_query",
|
|
183
|
+
keyArgs: "domain=data.illinois.gov, datasetId=6rb8-ntpm",
|
|
184
|
+
rows: 48,
|
|
185
|
+
approximate: false,
|
|
186
|
+
notNote: "a comprehensive solicitation feed, and NOT currently open bids — these are ~48 CDB capital solicitations the publisher describes as \"anticipated for a future date, but have not been posted yet\" (estimated_bid_date field)",
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
state: "IL",
|
|
190
|
+
jurisdiction: "Illinois",
|
|
191
|
+
dataLabel: "IDHR certified eligible bidders",
|
|
192
|
+
tool: "socrata_query",
|
|
193
|
+
keyArgs: "domain=data.illinois.gov, datasetId=w8h2-q8hu",
|
|
194
|
+
rows: 7848,
|
|
195
|
+
approximate: false,
|
|
196
|
+
notNote: "a bid or award register; vendor-eligibility directory only",
|
|
197
|
+
},
|
|
198
|
+
// ── Texas — verified 2026-09-21 ──────────────────────────────────────────
|
|
199
|
+
{
|
|
200
|
+
state: "TX",
|
|
201
|
+
jurisdiction: "Texas",
|
|
202
|
+
dataLabel: "TxDOT current lettings (★live bid-line items)",
|
|
203
|
+
tool: "socrata_query",
|
|
204
|
+
keyArgs: "domain=data.texas.gov, datasetId=qh8x-rm8r",
|
|
205
|
+
rows: 8861,
|
|
206
|
+
approximate: false,
|
|
207
|
+
notNote:
|
|
208
|
+
"rows are bid LINE ITEMS not projects (8,861 rows = 412 distinct project_ids — report project count not row count); TxDOT highway lettings ONLY, not all Texas procurement; rolling window only (past lettings dropped, cannot answer historical questions); ESBD/TxSmartBuy non-TxDOT solicitations are absent",
|
|
209
|
+
extra:
|
|
210
|
+
"★First live state solicitation feed in this map. Use $select=count(distinct project_id) for open-bid count.",
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
state: "TX",
|
|
214
|
+
jurisdiction: "Texas",
|
|
215
|
+
dataLabel: "DIR Cooperative Contract Sales FY2010–FY2025 (archive)",
|
|
216
|
+
tool: "socrata_query",
|
|
217
|
+
keyArgs: "domain=data.texas.gov, datasetId=w64c-ndf7",
|
|
218
|
+
rows: 10749743,
|
|
219
|
+
approximate: false,
|
|
220
|
+
notNote: "bids or awards; purchase line items off DIR cooperative contracts (historical)",
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
state: "TX",
|
|
224
|
+
jurisdiction: "Texas",
|
|
225
|
+
dataLabel: "DIR Cooperative & Tele Contract Sales FY2026",
|
|
226
|
+
tool: "socrata_query",
|
|
227
|
+
keyArgs: "domain=data.texas.gov, datasetId=a743-wj72",
|
|
228
|
+
rows: 2077855,
|
|
229
|
+
approximate: false,
|
|
230
|
+
notNote: "historical FY2026 purchase lines (same shape as w64c-ndf7); not bids",
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
state: "TX",
|
|
234
|
+
jurisdiction: "Texas",
|
|
235
|
+
dataLabel: "DIR Current Active Cooperative Contracts",
|
|
236
|
+
tool: "socrata_query",
|
|
237
|
+
keyArgs: "domain=data.texas.gov, datasetId=vipt-h4ye",
|
|
238
|
+
rows: 5167,
|
|
239
|
+
approximate: false,
|
|
240
|
+
notNote: "a solicitation feed; active cooperative contract register (not TxDOT lettings)",
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
state: "TX",
|
|
244
|
+
jurisdiction: "Texas",
|
|
245
|
+
dataLabel: "TCEQ Current Contracts & Purchase Orders",
|
|
246
|
+
tool: "socrata_query",
|
|
247
|
+
keyArgs: "domain=data.texas.gov, datasetId=svjm-sdfz",
|
|
248
|
+
rows: 2067,
|
|
249
|
+
approximate: false,
|
|
250
|
+
notNote: "statewide; one agency (TCEQ) only",
|
|
251
|
+
},
|
|
252
|
+
// ── Maryland — verified 2026-09-21 ───────────────────────────────────────
|
|
253
|
+
{
|
|
254
|
+
state: "MD",
|
|
255
|
+
jurisdiction: "Maryland",
|
|
256
|
+
dataLabel: "eMaryland Marketplace (eMMA) bids — FY2018 exemplar",
|
|
257
|
+
tool: "socrata_query",
|
|
258
|
+
keyArgs: "domain=opendata.maryland.gov, datasetId=pgna-cxjh",
|
|
259
|
+
rows: 107303,
|
|
260
|
+
approximate: false,
|
|
261
|
+
notNote:
|
|
262
|
+
"rows are bid LINE ITEMS not bids — FY2018 is 107,303 rows for only 3,067 bids (35× overcount); always use $select=count(distinct bid_number) for actual bid count. Coverage stops at FY2019 — eMMA migrated to Periscope mid-FY2019; there is no FY2020+ mirror and this dataset cannot answer questions about current Maryland bids",
|
|
263
|
+
extra:
|
|
264
|
+
"All six FY datasetIds: FY2018=pgna-cxjh (107,303 rows/3,067 bids), FY2017=qkjf-rv4t (64,331/4,943), FY2016=7ang-84wj (45,204/4,818), FY2015=3hzs-sazv (46,895/4,898), FY2014=itax-4ccz (45,551/4,884), FY2019=ttg5-zfzj (4,623/388 — small because eMMA migrated to Periscope mid-year; first row is a sparse placeholder, subsequent rows are complete).",
|
|
265
|
+
},
|
|
266
|
+
// ── Oregon — verified 2026-09-21 ─────────────────────────────────────────
|
|
267
|
+
{
|
|
268
|
+
state: "OR",
|
|
269
|
+
jurisdiction: "Oregon",
|
|
270
|
+
dataLabel: "OregonBuys Purchases and Contracts FY2022–FY2025",
|
|
271
|
+
tool: "socrata_query",
|
|
272
|
+
keyArgs: "domain=data.oregon.gov, datasetId=qyug-f2km",
|
|
273
|
+
rows: 109119,
|
|
274
|
+
approximate: false,
|
|
275
|
+
notNote:
|
|
276
|
+
"open solicitations — these are issued purchase orders and contracts (not bids). ORPIN was the retired system; OregonBuys is its replacement. qyug-f2km covers sent_date 2021-07-01 → 2025-07-01 (FY2022–FY2025); 92,224 distinct po_nbr",
|
|
277
|
+
extra:
|
|
278
|
+
"Historical ORPIN datasets (retired system, same domain): Contracts Issued=6e9e-sfc4 (93,846 rows), Contracts Expired=8izy-bwhd (92,755 rows), Statewide Price Agreement Spend=gart-52me (5,224 rows). All keyless.",
|
|
279
|
+
},
|
|
280
|
+
// ── Vermont — verified 2026-09-21 ────────────────────────────────────────
|
|
281
|
+
{
|
|
282
|
+
state: "VT",
|
|
283
|
+
jurisdiction: "Vermont",
|
|
284
|
+
dataLabel: "Purchase Orders with Vendor Information (current FY, live-ish)",
|
|
285
|
+
tool: "socrata_query",
|
|
286
|
+
keyArgs: "domain=data.vermont.gov, datasetId=8ewu-igdm",
|
|
287
|
+
rows: 111271,
|
|
288
|
+
approximate: false,
|
|
289
|
+
notNote:
|
|
290
|
+
"a bid or award register — issued purchase orders. 39,882 distinct po_id (~2.8 line items per PO). po_date 2025-07-02 → 2026-06-19 (current fiscal year, so this is live-ish state spend, not an archive)",
|
|
291
|
+
},
|
|
292
|
+
// ── Colorado (City of Denver on state portal) — verified 2026-09-21 ──────
|
|
293
|
+
{
|
|
294
|
+
state: "CO",
|
|
295
|
+
jurisdiction: "City of Denver",
|
|
296
|
+
dataLabel: "City of Denver Procurement Transactions (on CO state portal)",
|
|
297
|
+
tool: "socrata_query",
|
|
298
|
+
keyArgs: "domain=data.colorado.gov, datasetId=66zf-qjdd",
|
|
299
|
+
rows: 76357,
|
|
300
|
+
approximate: false,
|
|
301
|
+
notNote:
|
|
302
|
+
"Colorado STATE procurement — this is City of Denver spend hosted on the Colorado state portal (data.colorado.gov). An agent that reads the domain as the jurisdiction gets this wrong. Updated 2026-09-20.",
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
state: "CO",
|
|
306
|
+
jurisdiction: "City of Denver",
|
|
307
|
+
dataLabel: "City of Denver Checkbook (on CO state portal)",
|
|
308
|
+
tool: "socrata_query",
|
|
309
|
+
keyArgs: "domain=data.colorado.gov, datasetId=wnau-xrqi",
|
|
310
|
+
rows: 154595,
|
|
311
|
+
approximate: false,
|
|
312
|
+
notNote:
|
|
313
|
+
"Colorado STATE procurement — this is City of Denver checkbook data hosted on the Colorado state portal (data.colorado.gov). An agent that reads the domain as the jurisdiction gets this wrong. Updated 2026-09-20.",
|
|
314
|
+
},
|
|
315
|
+
// ── Fulton County GA (second portal) — verified 2026-09-21 ───────────────
|
|
316
|
+
{
|
|
317
|
+
state: "GA",
|
|
318
|
+
jurisdiction: "Fulton County GA",
|
|
319
|
+
dataLabel: "Vendor Payments 2014–present (sharefulton portal)",
|
|
320
|
+
tool: "socrata_query",
|
|
321
|
+
keyArgs: "domain=sharefulton.fultoncountyga.gov, datasetId=kp4p-scak",
|
|
322
|
+
rows: 226797,
|
|
323
|
+
approximate: false,
|
|
324
|
+
notNote:
|
|
325
|
+
"data.fultoncountyga.gov (a DIFFERENT host that is also allowlisted — both are official Fulton County portals). Fields: fiscal_year, fy_period, disb_date, dept, department_name, unit, unit_name, object, object_name, fund, fund_name, amount, vendor_code, vendor_legal_name. Updated 2026-09-14, attribution: 'Fulton County Government (GA)', 226,797 rows spanning 2014-01-01 to present.",
|
|
326
|
+
},
|
|
327
|
+
];
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Format a row count for display.
|
|
331
|
+
*
|
|
332
|
+
* HONESTY: an EXACT count (approximate:false) is printed in full with thousands
|
|
333
|
+
* separators — never rounded. The table header promises a "verified row count",
|
|
334
|
+
* so rounding a measured 1,693,227 to "2M" would overstate it by 18% while still
|
|
335
|
+
* reading as exact. Only an entry explicitly marked `approximate` is rounded, and
|
|
336
|
+
* that form always carries a leading `~` so the reader can tell the two apart.
|
|
337
|
+
*/
|
|
338
|
+
function fmtRows(e: DataMapEntry): string {
|
|
339
|
+
if (e.rows === null) return "?";
|
|
340
|
+
if (!e.approximate) return e.rows.toLocaleString("en-US");
|
|
341
|
+
// Keep 2 significant figures below 10 units so "~5k" never stands in for a
|
|
342
|
+
// measured 4,554 (a 10% overstatement); 49,000,000 still renders "~49M".
|
|
343
|
+
const scale = (v: number, suffix: string) =>
|
|
344
|
+
`${v < 10 ? v.toFixed(1).replace(/\.0$/, "") : String(Math.round(v))}${suffix}`;
|
|
345
|
+
const n = e.rows >= 1000000 ? scale(e.rows / 1000000, "M") :
|
|
346
|
+
e.rows >= 1000 ? scale(e.rows / 1000, "k") :
|
|
347
|
+
String(e.rows);
|
|
348
|
+
return `~${n}`;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Render the state-level entries as a Markdown table.
|
|
353
|
+
* Matches the format in SKILL.md §State & local data map.
|
|
354
|
+
*/
|
|
355
|
+
export function renderStateTableMarkdown(): string {
|
|
356
|
+
const header =
|
|
357
|
+
"| Jurisdiction | Data | Tool · key args | Rows | NOT |\n" +
|
|
358
|
+
"|---|---|---|---|---|\n";
|
|
359
|
+
const rows = DATA_MAP_ENTRIES.map((e) => {
|
|
360
|
+
const extra = e.extra ? ` ${e.extra}` : "";
|
|
361
|
+
return `| **${e.jurisdiction}** | ${e.dataLabel} | \`${e.tool}\` ${e.keyArgs} | ${fmtRows(e)} | ${e.notNote}${extra} |`;
|
|
362
|
+
});
|
|
363
|
+
return header + rows.join("\n");
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/** Full resource content: header + state table */
|
|
367
|
+
export function renderDataMapMarkdown(): string {
|
|
368
|
+
return `# State & local data map
|
|
369
|
+
|
|
370
|
+
Agent-readable lookup: jurisdiction → data type → exact tool call → verified row count → what it is NOT (the most common source of agent error).
|
|
371
|
+
|
|
372
|
+
**State-level open-data sources (verified 2026-09-21, all keyless):**
|
|
373
|
+
|
|
374
|
+
${renderStateTableMarkdown()}
|
|
375
|
+
|
|
376
|
+
**County & city** — use \`socrata_discover_datasets\` to find dataset IDs for: NYC (data.cityofnewyork.us), Chicago (data.cityofchicago.org), Austin TX (data.austintexas.gov), Dallas TX (www.dallasopendata.com), LA (controllerdata.lacity.org), King County WA (data.kingcounty.gov), Cook County IL (datacatalog.cookcountyil.gov), Montgomery County MD (data.montgomerycountymd.gov). For Hennepin County MN and Charlotte-Mecklenburg NC capital project pipelines, use \`arcgis_feature_query\` (hennepin_transportation_cip / charlotte_mecklenburg_cip) — these are CIP pipelines, NOT solicitation or award registers.
|
|
377
|
+
|
|
378
|
+
**State portals with no keyless procurement content (measured absence, not unexplored):**
|
|
379
|
+
- Login-gated or WAF-blocked live-bid portals: CA (Cal eProcure), TX ESBD/TxSmartBuy non-TxDOT (TxDOT lettings ARE available via qh8x-rm8r above), OH, NC, MI, and Periscope-based portals for IL/MA/NJ live bids.
|
|
380
|
+
- Portal exists but carries no procurement datasets: PA (data.pa.gov is live; scoped catalog has 0 bid/vendor/procurement datasets matching). Michigan (data.michigan.gov) was checked 2026-09-21 and carries only NIGP commodity code reference tables (w3u3-uptp 9,333 rows; jv5q-yp8x 235 rows) — not procurement transactions.
|
|
381
|
+
- No state-level open-data portal: FL (data.fl.gov NXDOMAIN), GA (data.georgia.gov NXDOMAIN). These states have no keyless state procurement data source — this is a measured absence, not a connectivity block.
|
|
382
|
+
|
|
383
|
+
**City-level measured absences (portals exist but carry no procurement data):**
|
|
384
|
+
- New Orleans LA (rank 46, 383,997 people): data.nola.gov exists but has NO procurement dataset. Full scan across 9 terms (procurement, solicitation, bid opportunities, vendor payments, purchase orders, contracts awarded, checkbook, supplier diversity, expenditure) on 2026-09-21 found only a 626-row DBE directory last updated 2019-11-11. Largest datasets are permits (347,839) and traffic citations (4M+) — not procurement. Use opengov_search_solicitations or bonfire_search_opportunities for New Orleans live bids.
|
|
385
|
+
`;
|
|
386
|
+
}
|
package/src/fpds.ts
CHANGED
|
@@ -48,9 +48,10 @@ const FPDS_HOST = "www.fpds.gov";
|
|
|
48
48
|
const FPDS_PATH = "/ezsearch/FEEDS/ATOM";
|
|
49
49
|
const FPDS_ORIGIN_PATH = `https://${FPDS_HOST}${FPDS_PATH}`;
|
|
50
50
|
const FPDS_LABEL = "www.fpds.gov";
|
|
51
|
-
//
|
|
51
|
+
// Identify this client honestly — same string used by every other module in the
|
|
52
|
+
// project. Live-verified 2026-09-22: FPDS returns 200 to this UA and with no UA.
|
|
52
53
|
const FPDS_UA =
|
|
53
|
-
"Mozilla/5.0 (
|
|
54
|
+
"Mozilla/5.0 (compatible; @cliwant/mcp-sam-gov; +https://github.com/cliwant/mcp-sam-gov)";
|
|
54
55
|
|
|
55
56
|
const PAGE_SIZE = 10;
|
|
56
57
|
/** Hard cap on entries sliced per feed (page size is 10; anything past a small
|
package/src/gao.ts
CHANGED
|
@@ -42,11 +42,12 @@ import { withMeta } from "./meta.js";
|
|
|
42
42
|
|
|
43
43
|
// ─── Shared HTTP ─────────────────────────────────────────────────
|
|
44
44
|
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
//
|
|
45
|
+
// Identify this client honestly — same string used by every other module in the
|
|
46
|
+
// project. Live-verified 2026-09-22: GAO's RSS feed returns 200 to this UA, to
|
|
47
|
+
// the formerly-used fake Chrome UA, and even with no UA at all. GAO per-decision
|
|
48
|
+
// pages 403 from Akamai regardless of UA, so spoofing a browser gains nothing.
|
|
48
49
|
const GAO_UA =
|
|
49
|
-
"Mozilla/5.0 (
|
|
50
|
+
"Mozilla/5.0 (compatible; @cliwant/mcp-sam-gov; +https://github.com/cliwant/mcp-sam-gov)";
|
|
50
51
|
|
|
51
52
|
const RSS_URL = "https://www.gao.gov/rss/reportslegal.xml";
|
|
52
53
|
const PRODUCT_BASE = "https://www.gao.gov/products/";
|
|
@@ -58,9 +59,9 @@ const SOURCE = "gao.gov Legal Products RSS + decision pages (keyless)";
|
|
|
58
59
|
* in `data` and inside `_meta.notes` so no consumer can miss the scope boundary.
|
|
59
60
|
*/
|
|
60
61
|
const ACCESS_NOTE =
|
|
61
|
-
"Keyless GAO access covers only RECENT decisions from the public Legal-Products RSS feed (a rolling ~25-item window). GAO's faceted historical protest search (by protester/agency/outcome/date across all years) is WAF-blocked to automated clients
|
|
62
|
+
"Keyless GAO access covers only RECENT decisions from the public Legal-Products RSS feed (a rolling ~25-item window). GAO's faceted historical protest search (by protester/agency/outcome/date across all years) is WAF-blocked to automated clients — keyless programmatic access is unavailable (a human can search at https://www.gao.gov/search). Do NOT treat these results as the complete protest history.";
|
|
62
63
|
|
|
63
|
-
// Thin LOCAL wrapper (ADR-0013) that injects
|
|
64
|
+
// Thin LOCAL wrapper (ADR-0013) that injects the project's honest UA + RSS Accept
|
|
64
65
|
// for the tool's two call sites, then delegates to the shared `getText` port
|
|
65
66
|
// (retry defaults true → fetchWithRetry, byte-identical to the former
|
|
66
67
|
// hand-rolled fetcher). `timeoutMs` is preserved as a param default (never
|
|
@@ -710,6 +711,19 @@ export async function gaoProtestLookup(args: {
|
|
|
710
711
|
);
|
|
711
712
|
}
|
|
712
713
|
|
|
714
|
+
// When a protester/agency/solicitationNumber filter was given and the window
|
|
715
|
+
// contains no matching decisions, give the caller a precise next step: GAO's
|
|
716
|
+
// own search pre-filtered to bid-protest decisions with the term filled in.
|
|
717
|
+
// (This is NOT a reading list — it is a single direct link to the full
|
|
718
|
+
// historical database that a human can open immediately.)
|
|
719
|
+
const searchTerm = (args.protester ?? args.agency ?? args.solicitationNumber)?.trim();
|
|
720
|
+
if (decisions.length === 0 && filtersApplied.length > 0 && searchTerm) {
|
|
721
|
+
const encoded = encodeURIComponent(searchTerm);
|
|
722
|
+
notes.push(
|
|
723
|
+
`"${searchTerm}" does not appear in the current ~25-decision window. GAO's full protest database is searchable at https://www.gao.gov/search?f%5B0%5D=ctype_search%3ABid%20Protest%20Decision&keyword=${encoded} — each result shows parties, agency, date and outcome. Keyless programmatic access to the historical archive is unavailable; the link above goes directly to the relevant results.`,
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
|
|
713
727
|
return withMeta(
|
|
714
728
|
{ accessNote: ACCESS_NOTE, decisions },
|
|
715
729
|
{
|
package/src/gsa-perdiem.ts
CHANGED
|
@@ -93,6 +93,10 @@ const STANDARD_RATE_NOTE =
|
|
|
93
93
|
"standardRate:true means this location falls under the CONUS STANDARD rate (not an individually-set non-standard rate). standardRate/isOconus are booleans coerced from the API's string 'true'/'false'.";
|
|
94
94
|
const NO_PAGINATION_NOTE =
|
|
95
95
|
"The per-diem API returns the COMPLETE rate set for the lookup (no pagination); totalAvailable equals the number of rows returned.";
|
|
96
|
+
const FISCAL_YEAR_NOTE =
|
|
97
|
+
"fiscalYear (= year) is the U.S. FEDERAL FISCAL YEAR (Oct 1–Sep 30). " +
|
|
98
|
+
"Example: October 2026 falls in FY2027 (FY runs Oct 2026–Sep 2027); September 2026 falls in FY2026. " +
|
|
99
|
+
"To look up October 2026 rates, pass year='2027'. To look up September 2026 rates, pass year='2026'.";
|
|
96
100
|
|
|
97
101
|
// ─── STRING-boolean coercion (null-never-fabricate) ───────────────
|
|
98
102
|
/** Coerce the API's string 'true'/'false' → a real boolean; anything else ⇒ null. */
|
|
@@ -119,6 +123,11 @@ export type PerdiemRate = {
|
|
|
119
123
|
state: string | null;
|
|
120
124
|
zip: string | null;
|
|
121
125
|
year: number | null;
|
|
126
|
+
/** Explicit U.S. federal fiscal year label (Oct 1–Sep 30). Same numeric value as
|
|
127
|
+
* `year` (the GSA API's year field IS the FY number). Surfaced as a separate named
|
|
128
|
+
* field so callers never confuse it with a calendar year. E.g. fiscalYear:2027 means
|
|
129
|
+
* rates run Oct 2026–Sep 2027; October 2026 travel uses FY2027 rates. */
|
|
130
|
+
fiscalYear: number | null;
|
|
122
131
|
isOconus: boolean | null; // OCONUS (outside-CONUS) flag — coerced from string boolean
|
|
123
132
|
standardRate: boolean | null; // CONUS standard-rate flag — coerced from string boolean
|
|
124
133
|
mealsUsd: number | null; // M&IE ceiling ($) — null-never-0
|
|
@@ -350,6 +359,8 @@ export async function perdiemRates(
|
|
|
350
359
|
state: gState,
|
|
351
360
|
zip: str(r.zip),
|
|
352
361
|
year: gYear,
|
|
362
|
+
fiscalYear: gYear, // same numeric value as year; surfaced separately so callers
|
|
363
|
+
// never confuse it with a calendar year (GSA year IS the FY)
|
|
353
364
|
isOconus: gOconus,
|
|
354
365
|
standardRate: strBool(r.standardRate),
|
|
355
366
|
mealsUsd: num(r.meals),
|
|
@@ -359,7 +370,7 @@ export async function perdiemRates(
|
|
|
359
370
|
}
|
|
360
371
|
|
|
361
372
|
const returned = rows.length;
|
|
362
|
-
const notes: string[] = [RATE_MEANING_NOTE, STANDARD_RATE_NOTE, NO_PAGINATION_NOTE];
|
|
373
|
+
const notes: string[] = [RATE_MEANING_NOTE, STANDARD_RATE_NOTE, NO_PAGINATION_NOTE, FISCAL_YEAR_NOTE];
|
|
363
374
|
if (yearWasDefaulted) {
|
|
364
375
|
notes.push(
|
|
365
376
|
`No \`year\` was supplied, so it defaulted to the CURRENT U.S. federal fiscal year (FY${year}). GSA per-diem ceilings are set per fiscal year (Oct 1–Sep 30); pass an explicit \`year\` for a prior or upcoming FY.`,
|
package/src/open-checkbook.ts
CHANGED
|
@@ -41,14 +41,37 @@ import { withMeta, type MetaBundle, type ResponseMeta } from "./meta.js";
|
|
|
41
41
|
|
|
42
42
|
export { num };
|
|
43
43
|
|
|
44
|
-
// ─── Curated portal allowlist (SSRF core) — LIVE-VERIFIED 2026-07-24 ──
|
|
45
|
-
export type OpenCheckbookPortal = {
|
|
44
|
+
// ─── Curated portal allowlist (SSRF core) — LIVE-VERIFIED 2026-07-24/2026-09-21 ──
|
|
45
|
+
export type OpenCheckbookPortal = {
|
|
46
|
+
key: string;
|
|
47
|
+
host: string;
|
|
48
|
+
label: string;
|
|
49
|
+
note: string;
|
|
50
|
+
/**
|
|
51
|
+
* What fiscal-year span this portal actually publishes, as MEASURED (not assumed).
|
|
52
|
+
* Portals differ: SD exposes roughly the three most recent FYs, AK exposes exactly
|
|
53
|
+
* one. Emitting a single hardcoded coverage sentence for both made the envelope
|
|
54
|
+
* contradict itself — the generic line claimed "~3 most-recent fiscal years" while
|
|
55
|
+
* the AK portal note in the same response said FY2026 only.
|
|
56
|
+
*/
|
|
57
|
+
coverageNote: string;
|
|
58
|
+
};
|
|
46
59
|
export const OPEN_CHECKBOOK_PORTALS: readonly OpenCheckbookPortal[] = [
|
|
47
60
|
{
|
|
48
61
|
key: "sd",
|
|
49
62
|
host: "southdakota.spending.socrata.com",
|
|
50
63
|
label: "South Dakota — Open Checkbook",
|
|
51
64
|
note: "State of South Dakota vendor-payment checkbook (row fields: expense_category, description, fund, payment_date, vendor, org1=department, amount, custom_checkbook_field7=invoice ref, payment_id). ~740,980 rows / ~$8.41B across the ~3 most-recent fiscal years (NOT full history). The underlying Socrata SODA dataset is login-gated; this public app-proxy is the keyless door.",
|
|
65
|
+
coverageNote:
|
|
66
|
+
"COVERAGE: this portal exposes only the ~3 most-recent fiscal years — NOT South Dakota's full payment history.",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
key: "ak",
|
|
70
|
+
host: "checkbook.alaska.gov",
|
|
71
|
+
label: "Alaska — Open Checkbook",
|
|
72
|
+
note: "State of Alaska vendor-payment checkbook (official .gov CNAME to alaska-state.spending.socrata.com). Verified live 2026-09-21: 41,751 rows / $1,179,091,896.12 for FY2026. ★ FY COVERAGE CAVEAT: ONLY FY2026 is published by this portal — years 2019–2025 and no-year all return count:0 / empty data. A count:0 result for a non-2026 year means 'this portal does not publish that year', NOT 'Alaska spent nothing'. Do NOT interpret zero results for FY2019–FY2025 as an absence of spending.",
|
|
73
|
+
coverageNote:
|
|
74
|
+
"COVERAGE: this portal publishes ONLY FY2026 (measured 2026-09-21: FY2019-FY2025 and an omitted year each return count:0). A count:0 for any other year means the portal does not publish that year — it does NOT mean Alaska made no payments.",
|
|
52
75
|
},
|
|
53
76
|
] as const;
|
|
54
77
|
|
|
@@ -160,7 +183,7 @@ export async function openCheckbookSearch(args: OpenCheckbookSearchArgs): Promis
|
|
|
160
183
|
`Source: ${portal.label} (Socrata Open Expenditures app-proxy /api/checkbook_data.json, keyless). ${portal.note}`,
|
|
161
184
|
"totalAvailable = the API's exact match count (matches the product's totals.json), NOT the page length.",
|
|
162
185
|
"Filters (year/vendor/org/expenseCategory) are EXACT-match — a partial/misspelled value returns an honest count:0, not an error. amount is number|null (a real $0 is 0, an absent value is null, never a fabricated 0).",
|
|
163
|
-
|
|
186
|
+
portal.coverageNote,
|
|
164
187
|
"FRESHNESS is set by the publisher: the portal says it refreshes each payment cycle, but refreshes can lag by weeks. To check recency, sort by payment_date (sortBy='payment_date', sortOrder='desc') and read the newest date.",
|
|
165
188
|
];
|
|
166
189
|
if (servedOffset !== offset)
|