@mailwoman/mcp 9.4.0 → 10.1.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/out/tools.js CHANGED
@@ -2,38 +2,6 @@
2
2
  * @copyright Sister Software
3
3
  * @license AGPL-3.0
4
4
  * @author Teffen Ellis, et al.
5
- *
6
- * The MCP tool table — pure, transport-free. `server.ts` adapts this to the `@modelcontextprotocol/sdk`'s
7
- * registration API; `cli.ts` builds the real `MCPToolDeps` from the mailwoman library. Kept separate so this
8
- * file (the actual product surface) is testable without any MCP plumbing — `tools.test.ts` calls
9
- * `buildToolTable` directly with stub deps.
10
- *
11
- * One tool per capability the exotic-POI/BDC arcs' other packages expose to a human/CLI caller — see
12
- * `buildToolTable`'s return value for the authoritative, current list (this comment intentionally states no count,
13
- * so it can't go stale as tools are added):
14
- *
15
- * - `mailwoman_parse` — the runtime pipeline's parse (optionally POI-aware).
16
- * - `mailwoman_geocode` — the street-level geocode cascade (`mailwoman/geocode-core`).
17
- * - `mailwoman_poi_search` — POI-intent extraction + (when a poi.db is wired) execution.
18
- * - `mailwoman_overpass_export` — OverpassQL EXPORT emitter (`mailwoman/poi-overpass`) — "we print the query;
19
- * we never run it".
20
- * - `mailwoman_layer_manifest` — read a spatial-layer database's provenance manifest + coverage summary
21
- * (`@mailwoman/core/layers`).
22
- * - `mailwoman_bdc_filing_landscape` — read a bdc.db layer's provider/technology/speed-bucket filing census over a
23
- * set of census blocks or H3 cells (`@mailwoman/bdc`'s `filingLandscape`).
24
- * - `mailwoman_plausibility_check` — score one claimed broadband-service assertion against BDC filing evidence and
25
- * nearby telecom infrastructure (`@mailwoman/bdc`'s `plausibilityCheck`), returning a positive-evidence-only bundle
26
- * with an always-present `coverage_confidence`. A missing/absent `bdc_database_path`/`poi_database_path` degrades
27
- * to a typed abstain entry in the bundle, never a throw (decision 6).
28
- * - `mailwoman_filer_lookup` — read the FCC filer identity crosswalk (`@mailwoman/filer`'s
29
- * `filerLookup`) for one identifier (FRN, Form 499 ID, or BDC provider ID): every OTHER identifier it shares an
30
- * authoritative edge with, its current attributes, its authoritative entity cluster, and any inferred links —
31
- * reported separately, never merged into the cluster. `as_of` is always present (defaults to today).
32
- * - `mailwoman_filer_family` — read a corporate family's membership (`@mailwoman/filer/sdk`'s
33
- * `familyRollup`) from a filer.db layer database, given a `family_id` or a `node_id`. Distinct from an entity
34
- * cluster (same filer, different identifiers) — a corporate family spans several DIFFERENT filers under a
35
- * holding/parent/subsidiary/management relationship. The handler passes `familyRollup`'s result through
36
- * unchanged: no reshaping, filtering, or summarizing of who-owns-whom data.
37
5
  */
38
6
  import { z } from "zod";
39
7
  const ParseInputSchema = z.object({
@@ -166,7 +134,8 @@ const FilerFamilyInputSchema = z.object({
166
134
  "actually used."),
167
135
  });
168
136
  /**
169
- * Build the tool table for a concrete `MCPToolDeps` implementation. Pure — no transport, no I/O of its own.
137
+ * Builds the MCP tool table over the given dependencies, without opening a transport
138
+ * or performing I/O itself.
170
139
  */
171
140
  export function buildToolTable(deps) {
172
141
  return [
package/out/tools.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tools.js","sourceRoot":"","sources":["../lib/tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../lib/tools.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mailwoman/mcp",
3
- "version": "9.4.0",
4
- "description": "MCP server — mailwoman's spatial toolset for agents (parse, geocode, poi_search, overpass_export, layer_manifest).",
3
+ "version": "10.1.0",
4
+ "description": "MCP server — mailwoman's toolset for agents: address parsing and geocoding, POI search and Overpass export, layer manifests, plausibility checks, and FCC broadband and filer lookups.",
5
5
  "license": "AGPL-3.0-only OR LicenseRef-Commercial",
6
6
  "repository": {
7
7
  "type": "git",
@@ -9,7 +9,7 @@
9
9
  "directory": "packages/mcp"
10
10
  },
11
11
  "bin": {
12
- "mailwoman-mcp": "./out/cli.js"
12
+ "mailwoman-mcp": "./out/cli/main.js"
13
13
  },
14
14
  "files": [
15
15
  "out/**/*.js",
@@ -17,18 +17,19 @@
17
17
  "out/**/*.d.ts",
18
18
  "out/**/*.d.ts.map",
19
19
  "README.md",
20
- "*.ts",
21
- "*.tsx",
22
- "**/*.ts",
23
- "**/*.tsx",
24
- "!*.test.ts",
25
- "!*.test.tsx",
20
+ "lib/**/*.ts",
21
+ "lib/**/*.tsx",
22
+ "cli/**/*.ts",
26
23
  "!**/*.test.ts",
27
- "!**/*.test.tsx",
28
- "!test/**"
24
+ "!**/*.test.tsx"
29
25
  ],
30
26
  "type": "module",
31
27
  "imports": {
28
+ "#cli/*": {
29
+ "types": "./out/cli/*.d.ts",
30
+ "node": "./out/cli/*.js",
31
+ "default": "./out/cli/*.js"
32
+ },
32
33
  "#*": {
33
34
  "types": "./out/*.d.ts",
34
35
  "node": "./out/*.js",
@@ -42,15 +43,15 @@
42
43
  "node": "./out/index.js",
43
44
  "default": "./out/index.js"
44
45
  },
45
- "./layer-guards": {
46
- "types": "./out/layer-guards.d.ts",
47
- "node": "./out/layer-guards.js",
48
- "default": "./out/layer-guards.js"
46
+ "./cli/*": {
47
+ "types": "./out/cli/*.d.ts",
48
+ "node": "./out/cli/*.js",
49
+ "default": "./out/cli/*.js"
49
50
  },
50
- "./tools": {
51
- "types": "./out/tools.d.ts",
52
- "node": "./out/tools.js",
53
- "default": "./out/tools.js"
51
+ "./*": {
52
+ "types": "./out/*.d.ts",
53
+ "node": "./out/*.js",
54
+ "default": "./out/*.js"
54
55
  }
55
56
  },
56
57
  "publishConfig": {
@@ -62,18 +63,23 @@
62
63
  "node": "./out/index.js",
63
64
  "default": "./out/index.js"
64
65
  },
65
- "./layer-guards": {
66
- "types": "./out/layer-guards.d.ts",
67
- "node": "./out/layer-guards.js",
68
- "default": "./out/layer-guards.js"
66
+ "./cli/*": {
67
+ "types": "./out/cli/*.d.ts",
68
+ "node": "./out/cli/*.js",
69
+ "default": "./out/cli/*.js"
69
70
  },
70
- "./tools": {
71
- "types": "./out/tools.d.ts",
72
- "node": "./out/tools.js",
73
- "default": "./out/tools.js"
71
+ "./*": {
72
+ "types": "./out/*.d.ts",
73
+ "node": "./out/*.js",
74
+ "default": "./out/*.js"
74
75
  }
75
76
  },
76
77
  "imports": {
78
+ "#cli/*": {
79
+ "types": "./out/cli/*.d.ts",
80
+ "node": "./out/cli/*.js",
81
+ "default": "./out/cli/*.js"
82
+ },
77
83
  "#*": {
78
84
  "types": "./out/*.d.ts",
79
85
  "node": "./out/*.js",
@@ -82,25 +88,18 @@
82
88
  }
83
89
  },
84
90
  "dependencies": {
85
- "@mailwoman/bdc": "9.4.0",
86
- "@mailwoman/core": "9.4.0",
87
- "@mailwoman/filer": "9.4.0",
88
- "@mailwoman/neural": "9.4.0",
89
- "@mailwoman/neural-weights-en-us": "9.4.0",
90
- "@mailwoman/poi-taxonomy": "9.4.0",
91
- "@mailwoman/resolver": "9.4.0",
92
- "@mailwoman/resolver-wof-sqlite": "9.4.0",
93
- "@mailwoman/sqlite": "9.4.0",
91
+ "@mailwoman/bdc": "10.1.0",
92
+ "@mailwoman/core": "10.1.0",
93
+ "@mailwoman/filer": "10.1.0",
94
+ "@mailwoman/neural": "10.1.0",
95
+ "@mailwoman/neural-weights-en-us": "10.1.0",
96
+ "@mailwoman/poi-taxonomy": "10.1.0",
97
+ "@mailwoman/resolver": "10.1.0",
98
+ "@mailwoman/resolver-wof-sqlite": "10.1.0",
99
+ "@mailwoman/sqlite": "10.1.0",
94
100
  "@modelcontextprotocol/sdk": "^1.30.0",
95
- "mailwoman": "9.4.0",
101
+ "mailwoman": "10.1.0",
102
+ "path-ts": "^2.5.0",
96
103
  "zod": "^4.5.4"
97
- },
98
- "peerDependencies": {
99
- "@mailwoman/resolver-wof-sqlite": "9.4.0"
100
- },
101
- "peerDependenciesMeta": {
102
- "@mailwoman/resolver-wof-sqlite": {
103
- "optional": true
104
- }
105
104
  }
106
105
  }
package/lib/cli.ts DELETED
@@ -1,373 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * @copyright Sister Software
4
- * @license AGPL-3.0
5
- * @author Teffen Ellis, et al.
6
- *
7
- * `mailwoman-mcp` — boot the MCP server over stdio. Wires the real `MCPToolDeps` (`tools.ts`) from the mailwoman
8
- * library: `createRuntimePipeline` for parse/POI-intent, `geocode-core`'s `geocodeAddress` for geocode,
9
- * `mailwoman/poi-overpass`'s `emitOverpassQL` for the export tool, `@mailwoman/core/layers` for the layer
10
- * manifest tool, and `@mailwoman/bdc`'s `filingLandscape`/`plausibilityCheck` for the two BDC tools.
11
- *
12
- * Deps are LAZY: nothing here loads the neural weights or opens a gazetteer db at startup — an MCP client
13
- * connects, lists tools, and may never call one (or may call only the layer-database tools, none of which touch the
14
- * classifier). The shared classifier+resolver are built once, on the FIRST call to any tool that needs them, and
15
- * cached for the process lifetime. `mailwoman_overpass_export` DOES need them despite never executing a query — it
16
- * parses the input to find the subject and anchor before it can emit OverpassQL.
17
- *
18
- * **Laziness moves the first failure into a tool call, so `loadCore` owns the friendly-failure messages** that
19
- * `photon`/`nominatim`/`mailwoman serve` print at boot. Both are thrown, not printed: `server.ts` catches a handler
20
- * throw and returns it as an `isError` tool result, so a thrown message reaches the agent where a `console.error` +
21
- * `process.exit(1)` would just kill the transport mid-conversation. See `loadCore` for the two.
22
- *
23
- * **Graceful layer-absent guards (decision 6).** Both BDC-backed tools treat a missing/unreadable
24
- * database file as absence, never a raw `node:sqlite` throw ("unable to open database file"): `bdcFilingLandscape`
25
- * requires bdc.db unconditionally, so a missing file becomes one friendly thrown `Error` naming the layer;
26
- * `plausibilityCheck`'s `bdcDB`/`poi` deps are each OPTIONAL, so a missing/absent `bdc_database_path`/
27
- * `poi_database_path` degrades to the SAME typed-abstain evidence entry (`{type:"abstain",
28
- * reason:"requires_bdc_layer"|"requires_build_local_layer"}`) the scorer already produces for an omitted dep. The
29
- * guards themselves (`assertBDCDatabaseExists`, `openBDCDatabaseIfPresent`, `openPlausibilityPOIDeps`) live in
30
- * `./layer-guards.ts`, NOT here — they're pure, transport-independent logic with no need for the stdio connection
31
- * this file opens at import time (which is exactly why THIS file can't be unit-tested directly; see
32
- * `layer-guards.test.ts` for their branch coverage).
33
- *
34
- * `mailwoman_filer_lookup` follows the SAME "requires the layer unconditionally" discipline as
35
- * `mailwoman_bdc_filing_landscape` (`assertFilerDatabaseExists` + `openFilerDatabaseIfPresent`, mirroring
36
- * `assertBDCDatabaseExists` + the BDC open) — `filerLookup` itself has no optional-dep abstain shape (criterion 4 makes
37
- * it throw rather than answer unstamped), so a missing filer.db becomes one friendly thrown Error naming the layer.
38
- *
39
- * `mailwoman_filer_family` follows the IDENTICAL discipline, reusing the same two guards — `familyRollup`
40
- * has no optional-dep abstain shape either (it throws on a bad `familyID`/`nodeID` XOR or a pre-`filer_family`
41
- * schema), so filer.db is required unconditionally here too. Its result — always `FamilyRollup[]`, never `null` or
42
- * a bare object — is passed through untouched: this data is who-owns-whom, and a silent reshape here would be a
43
- * fabricated relationship claim.
44
- *
45
- * ```sh
46
- * mailwoman-mcp # geocode/poi_search degrade gracefully with no poi.db wired
47
- * mailwoman-mcp --poi-db poi.db # mailwoman_poi_search additionally executes against poi.db
48
- * ```
49
- */
50
-
51
- import { filingLandscape, plausibilityCheck, type BDCDatabase } from "@mailwoman/bdc"
52
- import type { PipelineResult } from "@mailwoman/core"
53
- import { pathExists } from "@mailwoman/core/fs/readers"
54
- import { readLayerManifest, type LayerContractDatabase } from "@mailwoman/core/layers"
55
- import type { Resolver } from "@mailwoman/core/resolver"
56
- import { parseArguments } from "@mailwoman/core/scripting/arguments"
57
- import { mailwomanDataRoot, wofExtractPaths } from "@mailwoman/core/utils"
58
- import { familyRollup } from "@mailwoman/filer/family-rollup"
59
- import { filerLookup } from "@mailwoman/filer/filer-lookup"
60
- import { toFRN, type FRN } from "@mailwoman/filer/frn"
61
- import { NeuralAddressClassifier, type ScriptRoutedClassifier } from "@mailwoman/neural"
62
- import { getPOICategory } from "@mailwoman/poi-taxonomy"
63
- import { emitOverpassQL } from "@mailwoman/poi-taxonomy/overpass"
64
- import { createWOFResolver } from "@mailwoman/resolver"
65
- import { DatabaseClient } from "@mailwoman/sqlite/client"
66
- import { createRuntimePipeline } from "mailwoman"
67
- import { geocodeAddress, RegionDatabaseProvider } from "mailwoman/geocode"
68
- import { buildNoGazetteerMessage, createResolverBackend, resolveCandidateDBPath } from "mailwoman/resolver-backend"
69
-
70
- import {
71
- assertBDCDatabaseExists,
72
- assertFilerDatabaseExists,
73
- openBDCDatabaseIfPresent,
74
- openFilerDatabaseIfPresent,
75
- openPlausibilityPOIDeps,
76
- } from "#layer-guards"
77
- import { createMCPServer } from "#server"
78
- import type { MCPToolDeps } from "#tools"
79
-
80
- const { values } = parseArguments({
81
- options: {
82
- "poi-db": { type: "string" },
83
- },
84
- allowPositionals: true,
85
- })
86
-
87
- /**
88
- * `--poi-db` wires `mailwoman_poi_search` (and, via the same pipeline, `mailwoman_parse`'s `poi: true` path) to a real
89
- * `poi.db`. Absent → intent-only (parses the query, extracts the subject/anchor, never executes a lookup).
90
- */
91
- const poiDatabasePath = values["poi-db"]
92
-
93
- /**
94
- * The shared classifier + resolver, built exactly once on the first call that needs them (see the module header).
95
- * `NeuralAddressClassifier.loadFromWeights` auto-resolves the bundled `en-US` weights; the resolver backend prefers a
96
- * configured candidate gazetteer (`$MAILWOMAN_CANDIDATE_DB`) and otherwise falls back to the admin-only WOF extracts
97
- * already on the data root — same selection `nominatim`/`photon`'s CLIs make.
98
- */
99
- let corePromise:
100
- | Promise<{
101
- classifier: ScriptRoutedClassifier<NeuralAddressClassifier>
102
- resolver: Resolver
103
- databases: RegionDatabaseProvider
104
- }>
105
- | undefined
106
-
107
- /**
108
- * The four tools that need {@link loadCore} — every path through `getPlainPipeline`/`getPoiPipeline`/`resolveGeocode`.
109
- * `mailwoman_layer_manifest`, `mailwoman_bdc_filing_landscape`, `mailwoman_filer_lookup` and `mailwoman_filer_family`
110
- * never call it, so they keep working when this fails; `mailwoman_plausibility_check` only reaches it when it geocodes.
111
- * Named in both guard messages below because an agent that just got one needs to know what it can still do.
112
- */
113
- const CORE_BACKED_TOOLS = "mailwoman_parse, mailwoman_geocode, mailwoman_poi_search, mailwoman_overpass_export"
114
-
115
- const CORE_FREE_TOOLS =
116
- "mailwoman_layer_manifest, mailwoman_bdc_filing_landscape, mailwoman_filer_lookup, mailwoman_filer_family"
117
-
118
- function loadCore(): Promise<{
119
- classifier: ScriptRoutedClassifier
120
- resolver: Resolver
121
- databases: RegionDatabaseProvider
122
- }> {
123
- corePromise ??= (async () => {
124
- const resolverMod = await import("@mailwoman/resolver-wof-sqlite")
125
- const wofPaths: string[] = []
126
-
127
- for (const extractPath of wofExtractPaths()) {
128
- if (await pathExists(extractPath)) {
129
- wofPaths.push(extractPath)
130
- }
131
- }
132
-
133
- const candidateDB = await resolveCandidateDBPath()
134
-
135
- // #1009 friendly-failure discipline, the MCP shape of it. `server.ts` turns a thrown Error into an
136
- // `isError` tool result carrying `error.message`, so the message an agent reads IS whatever is thrown
137
- // here — which made the raw internal `resolveExtracts: at least one extract is required` the first thing a
138
- // stranger saw from `mailwoman_parse` on a fresh install (measured 2026-08-03 against a standalone
139
- // `npm install @mailwoman/mcp`). Same preflight as `photon`/`nominatim`/`mailwoman serve`, and the same
140
- // discovery: #1444 moved the `<data-root>/wof/candidate.db` convention fallback INTO
141
- // `resolveCandidateDBPath`, so this bare call picks a pulled gazetteer up with nothing exported. The
142
- // `MAILWOMAN_DATA_ROOT` in the client's `env` block is enough on its own.
143
- if (!candidateDB && !wofPaths.length) {
144
- throw new Error(
145
- `${buildNoGazetteerMessage({
146
- dataRoot: mailwomanDataRoot(),
147
- docsPath: "/docs/developers/how-to/use-the-mcp-server",
148
- })}\n\n Needs it: ${CORE_BACKED_TOOLS}\n Works without it: ${CORE_FREE_TOOLS}`
149
- )
150
- }
151
-
152
- const backend = await createResolverBackend(resolverMod, { wofPaths, candidateDB })
153
- const resolver = createWOFResolver(backend)
154
-
155
- // Same discipline for the model weights. `@mailwoman/neural-weights-en-us` is a declared dependency of
156
- // this package as of 2026-08-03 — before that a standalone `npm install @mailwoman/mcp` resolved
157
- // nothing and every core-backed tool answered with `resolveWeights`' raw not-found text. The guard keeps
158
- // that text (it already names the exact fix command) and adds what an agent mid-conversation needs next:
159
- // which tools are down and which are not.
160
- let classifier: ScriptRoutedClassifier<NeuralAddressClassifier>
161
-
162
- try {
163
- classifier = await NeuralAddressClassifier.loadRoutedFromWeights({ locale: "en-US" })
164
- } catch (error) {
165
- throw new Error(
166
- `✗ ${error instanceof Error ? error.message : String(error)}\n\n` +
167
- ` Needs it: ${CORE_BACKED_TOOLS}\n Works without it: ${CORE_FREE_TOOLS}`
168
- )
169
- }
170
-
171
- const databases = await RegionDatabaseProvider.create(resolverMod, mailwomanDataRoot())
172
-
173
- return { classifier, resolver, databases }
174
- })()
175
-
176
- return corePromise
177
- }
178
-
179
- type Pipeline = (raw: string) => Promise<PipelineResult>
180
-
181
- let plainPipeline: Pipeline | undefined
182
- /**
183
- * Keyed by the poi.db path used to build it (`""` = intent-only, no db) — `mailwoman_poi_search` can be called with a
184
- * `poiDatabasePath` that differs from the server's `--poi-db`, in which case a fresh one-off pipeline is built and
185
- * cached under that path instead of reusing the default.
186
- */
187
- const poiPipelines = new Map<string, Pipeline>()
188
-
189
- async function getPlainPipeline(): Promise<Pipeline> {
190
- if (!plainPipeline) {
191
- const { classifier, resolver } = await loadCore()
192
-
193
- plainPipeline = createRuntimePipeline({ classifier, resolver })
194
- }
195
-
196
- return plainPipeline
197
- }
198
-
199
- async function getPoiPipeline(dbPath: string | undefined): Promise<Pipeline> {
200
- const key = dbPath ?? ""
201
- const cached = poiPipelines.get(key)
202
-
203
- if (cached) return cached
204
- const { classifier, resolver } = await loadCore()
205
-
206
- const pipeline = createRuntimePipeline({
207
- classifier,
208
- resolver,
209
- poiQueryKind: dbPath ? { poiDatabasePath: dbPath } : true,
210
- })
211
-
212
- poiPipelines.set(key, pipeline)
213
-
214
- return pipeline
215
- }
216
-
217
- /**
218
- * `plausibilityCheck`'s geocode dep — reuses the SAME shared classifier+resolver `deps.geocode` builds from (see the
219
- * module header's laziness note). `deriveGeocodeRegister`/the formatted register is the geocode dep's concern, so it is
220
- * wired at this CLI/MCP layer rather than inside `plausibility.ts`. The real return type (`GeocodeResult`) is
221
- * structurally assignable to `plausibility.ts`'s minimal `GeocodeLike` — no adapter needed.
222
- */
223
- async function resolveGeocode(address: string) {
224
- const { classifier, resolver, databases } = await loadCore()
225
-
226
- return geocodeAddress(address, { classifier, resolver, databases: databases.for })
227
- }
228
-
229
- const deps: MCPToolDeps = {
230
- async parse(text, opts) {
231
- const pipeline = opts?.poi ? await getPoiPipeline(poiDatabasePath) : await getPlainPipeline()
232
-
233
- return pipeline(text)
234
- },
235
-
236
- async geocode(text) {
237
- return resolveGeocode(text)
238
- },
239
-
240
- async poiSearch(q) {
241
- const pipeline = await getPoiPipeline(q.poiDatabasePath ?? poiDatabasePath)
242
- const result = await pipeline(q.query)
243
-
244
- return result.poiIntent ?? { type: "abstain", reason: "not_poi_shaped" }
245
- },
246
-
247
- async overpassExport(query) {
248
- // Intent-only is enough here — the export just needs the parsed subject/anchor, never executed results
249
- // ("we print the query; we never run it", poi-overpass.ts). Reuses the server's wired poi pipeline (a
250
- // real poi.db doesn't change the emitted OverpassQL) instead of forcing a second one-off pipeline.
251
- const pipeline = await getPoiPipeline(poiDatabasePath)
252
- const result = await pipeline(query)
253
- const outcome = result.poiIntent
254
-
255
- if (!outcome || outcome.type !== "intent") {
256
- const reason = outcome?.type === "abstain" ? `: ${outcome.reason}` : ""
257
-
258
- throw new Error(
259
- `mailwoman_overpass_export: query is not POI-shaped (${outcome?.type ?? "no poi intent"}${reason})`
260
- )
261
- }
262
-
263
- const { subject } = outcome.intent
264
-
265
- // One tag per category the subject reaches, and only when EVERY member carries one: a union emitted from the
266
- // subset that happens to have an `osmTag` is a narrower query than the POI branch ran.
267
- const osmTags =
268
- subject.kind === "category"
269
- ? subject.categoryIDs.map((id) => getPOICategory(id)?.osmTag).filter((tag) => tag !== undefined)
270
- : []
271
-
272
- return emitOverpassQL(
273
- outcome.intent,
274
- subject.kind === "category" && osmTags.length === subject.categoryIDs.length ? { osmTags } : {}
275
- )
276
- },
277
-
278
- async layerManifest(databasePath) {
279
- using db = new DatabaseClient<LayerContractDatabase>(databasePath, { readOnly: true })
280
-
281
- const manifest = await readLayerManifest(db)
282
-
283
- const coverage = await db
284
- .selectFrom("layer_coverage")
285
- .select((eb) => [
286
- eb.fn.count<number>("h3_cell").as("surveyedCellCount"),
287
- eb.fn.avg<number>("completeness").as("averageCompleteness"),
288
- eb.fn.sum<number>("observed_rows").as("totalObservedRows"),
289
- ])
290
- .executeTakeFirst()
291
-
292
- return { manifest, coverage }
293
- },
294
-
295
- async bdcFilingLandscape(q) {
296
- // Decision 6: `mailwoman_bdc_filing_landscape` requires bdc.db unconditionally (no optional-dep
297
- // abstain shape exists for this tool), so a missing file becomes a friendly thrown Error naming the layer —
298
- // never the raw `node:sqlite` "unable to open database file" message.
299
- await assertBDCDatabaseExists("mailwoman_bdc_filing_landscape", q.databasePath)
300
-
301
- using db = new DatabaseClient<BDCDatabase>(q.databasePath, { readOnly: true })
302
-
303
- return filingLandscape(db, { geoids: q.geoids, h3Cells: q.h3Cells })
304
- },
305
-
306
- async plausibilityCheck(q) {
307
- const bdcDB = await openBDCDatabaseIfPresent(q.bdcDatabasePath)
308
- const poi = await openPlausibilityPOIDeps(q.poiDatabasePath)
309
-
310
- try {
311
- return await plausibilityCheck(
312
- {
313
- address: q.address,
314
- point: q.point,
315
- geoid: q.geoid,
316
- technologyCode: q.technologyCode,
317
- claimedDownloadMbps: q.claimedDownloadMbps,
318
- },
319
- { bdcDB, poi, geocode: resolveGeocode }
320
- )
321
- } finally {
322
- bdcDB?.destroy()
323
- poi?.contractDB.destroy()
324
- }
325
- },
326
-
327
- async filerLookup(q) {
328
- // Decision 6 / criterion 4: filerLookup has no optional-dep abstain shape — it throws rather than
329
- // answer unstamped — so filer.db is required unconditionally, same discipline as bdc.db is for
330
- // mailwoman_bdc_filing_landscape.
331
- await assertFilerDatabaseExists("mailwoman_filer_lookup", q.databasePath)
332
-
333
- using db = (await openFilerDatabaseIfPresent(q.databasePath))!
334
-
335
- let frn: FRN | undefined
336
-
337
- if (q.frn !== undefined) {
338
- const parsed = toFRN(q.frn)
339
-
340
- if (!parsed) {
341
- throw new Error(`mailwoman_filer_lookup: "${q.frn}" is not a valid FRN`)
342
- }
343
-
344
- frn = parsed
345
- }
346
-
347
- return await filerLookup(db, {
348
- frn,
349
- form499ID: q.form499ID,
350
- bdcProviderID: q.bdcProviderID,
351
- asOf: q.asOf,
352
- })
353
- },
354
-
355
- async filerFamily(q) {
356
- // Same discipline as mailwoman_filer_lookup — familyRollup has no optional-dep abstain shape
357
- // either, so filer.db is required unconditionally.
358
- await assertFilerDatabaseExists("mailwoman_filer_family", q.databasePath)
359
-
360
- using db = (await openFilerDatabaseIfPresent(q.databasePath))!
361
-
362
- return familyRollup(db, {
363
- familyID: q.familyID,
364
- nodeID: q.nodeID,
365
- asOf: q.asOf,
366
- })
367
- },
368
- }
369
-
370
- const server = createMCPServer(deps)
371
- const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js")
372
-
373
- await server.connect(new StdioServerTransport())
package/out/cli.d.ts DELETED
@@ -1,51 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * @copyright Sister Software
4
- * @license AGPL-3.0
5
- * @author Teffen Ellis, et al.
6
- *
7
- * `mailwoman-mcp` — boot the MCP server over stdio. Wires the real `MCPToolDeps` (`tools.ts`) from the mailwoman
8
- * library: `createRuntimePipeline` for parse/POI-intent, `geocode-core`'s `geocodeAddress` for geocode,
9
- * `mailwoman/poi-overpass`'s `emitOverpassQL` for the export tool, `@mailwoman/core/layers` for the layer
10
- * manifest tool, and `@mailwoman/bdc`'s `filingLandscape`/`plausibilityCheck` for the two BDC tools.
11
- *
12
- * Deps are LAZY: nothing here loads the neural weights or opens a gazetteer db at startup — an MCP client
13
- * connects, lists tools, and may never call one (or may call only the layer-database tools, none of which touch the
14
- * classifier). The shared classifier+resolver are built once, on the FIRST call to any tool that needs them, and
15
- * cached for the process lifetime. `mailwoman_overpass_export` DOES need them despite never executing a query — it
16
- * parses the input to find the subject and anchor before it can emit OverpassQL.
17
- *
18
- * **Laziness moves the first failure into a tool call, so `loadCore` owns the friendly-failure messages** that
19
- * `photon`/`nominatim`/`mailwoman serve` print at boot. Both are thrown, not printed: `server.ts` catches a handler
20
- * throw and returns it as an `isError` tool result, so a thrown message reaches the agent where a `console.error` +
21
- * `process.exit(1)` would just kill the transport mid-conversation. See `loadCore` for the two.
22
- *
23
- * **Graceful layer-absent guards (decision 6).** Both BDC-backed tools treat a missing/unreadable
24
- * database file as absence, never a raw `node:sqlite` throw ("unable to open database file"): `bdcFilingLandscape`
25
- * requires bdc.db unconditionally, so a missing file becomes one friendly thrown `Error` naming the layer;
26
- * `plausibilityCheck`'s `bdcDB`/`poi` deps are each OPTIONAL, so a missing/absent `bdc_database_path`/
27
- * `poi_database_path` degrades to the SAME typed-abstain evidence entry (`{type:"abstain",
28
- * reason:"requires_bdc_layer"|"requires_build_local_layer"}`) the scorer already produces for an omitted dep. The
29
- * guards themselves (`assertBDCDatabaseExists`, `openBDCDatabaseIfPresent`, `openPlausibilityPOIDeps`) live in
30
- * `./layer-guards.ts`, NOT here — they're pure, transport-independent logic with no need for the stdio connection
31
- * this file opens at import time (which is exactly why THIS file can't be unit-tested directly; see
32
- * `layer-guards.test.ts` for their branch coverage).
33
- *
34
- * `mailwoman_filer_lookup` follows the SAME "requires the layer unconditionally" discipline as
35
- * `mailwoman_bdc_filing_landscape` (`assertFilerDatabaseExists` + `openFilerDatabaseIfPresent`, mirroring
36
- * `assertBDCDatabaseExists` + the BDC open) — `filerLookup` itself has no optional-dep abstain shape (criterion 4 makes
37
- * it throw rather than answer unstamped), so a missing filer.db becomes one friendly thrown Error naming the layer.
38
- *
39
- * `mailwoman_filer_family` follows the IDENTICAL discipline, reusing the same two guards — `familyRollup`
40
- * has no optional-dep abstain shape either (it throws on a bad `familyID`/`nodeID` XOR or a pre-`filer_family`
41
- * schema), so filer.db is required unconditionally here too. Its result — always `FamilyRollup[]`, never `null` or
42
- * a bare object — is passed through untouched: this data is who-owns-whom, and a silent reshape here would be a
43
- * fabricated relationship claim.
44
- *
45
- * ```sh
46
- * mailwoman-mcp # geocode/poi_search degrade gracefully with no poi.db wired
47
- * mailwoman-mcp --poi-db poi.db # mailwoman_poi_search additionally executes against poi.db
48
- * ```
49
- */
50
- export {};
51
- //# sourceMappingURL=cli.d.ts.map
package/out/cli.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../lib/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG"}