@mailwoman/mcp 8.5.0 → 9.0.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.md CHANGED
@@ -4,13 +4,21 @@ An **MCP server** exposing [Mailwoman](https://mailwoman.sister.software)'s pars
4
4
 
5
5
  ## Tools
6
6
 
7
- | Tool | What it does |
8
- | --------------------------- | ----------------------------------------------------------------------- |
9
- | `mailwoman_parse` | Runtime-pipeline parse (optionally POI-aware) |
10
- | `mailwoman_geocode` | Street-level geocode cascade |
11
- | `mailwoman_poi_search` | POI-intent extraction, executed against a wired `poi.db` |
12
- | `mailwoman_overpass_export` | Renders a POI query as OverpassQL (prints the query, never runs it) |
13
- | `mailwoman_layer_manifest` | Reads a spatial-layer database's provenance manifest + coverage summary |
7
+ | Tool | What it does | Needs the model + a gazetteer |
8
+ | -------------------------------- | ---------------------------------------------------------------------------- | ----------------------------- |
9
+ | `mailwoman_parse` | Runtime-pipeline parse (optionally POI-aware) | Yes |
10
+ | `mailwoman_geocode` | Street-level geocode cascade | Yes |
11
+ | `mailwoman_poi_search` | POI-intent extraction, executed against a wired `poi.db` | Yes |
12
+ | `mailwoman_overpass_export` | Renders a POI query as OverpassQL (prints the query, never runs it) | Yes |
13
+ | `mailwoman_layer_manifest` | Reads a spatial-layer database's provenance manifest + coverage summary | No |
14
+ | `mailwoman_bdc_filing_landscape` | Reads a `bdc.db` layer's filing census over census blocks or H3 cells | No |
15
+ | `mailwoman_plausibility_check` | Scores one claimed broadband-service assertion against filing + POI evidence | Only when it geocodes |
16
+ | `mailwoman_filer_lookup` | Reads the FCC filer identity crosswalk from a `filer.db` layer | No |
17
+ | `mailwoman_filer_family` | Reads a corporate family's membership from a `filer.db` layer | No |
18
+
19
+ The four model-backed tools load the `en-US` weights and open a resolver on the first call that needs them, not at
20
+ startup. With neither `$MAILWOMAN_CANDIDATE_DB` nor a WOF distribution on the data root, that first call answers with
21
+ the `mailwoman data pull candidate` fix instead of an internal resolver error.
14
22
 
15
23
  ## Config
16
24
 
package/cli.ts CHANGED
@@ -10,11 +10,17 @@
10
10
  * manifest tool, and `@mailwoman/bdc`'s `filingLandscape`/`plausibilityCheck` for the two BDC tools.
11
11
  *
12
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 `mailwoman_overpass_export`/`mailwoman_layer_manifest`,
14
- * neither of which needs the classifier at all). The shared classifier+resolver are built once, on the FIRST call
15
- * to any tool that needs them, and cached for the process lifetime.
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.
16
17
  *
17
- * **Graceful layer-absent guards (2b task 7, decision 6).** Both BDC-backed tools treat a missing/unreadable
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
18
24
  * database file as absence, never a raw `node:sqlite` throw ("unable to open database file"): `bdcFilingLandscape`
19
25
  * requires bdc.db unconditionally, so a missing file becomes one friendly thrown `Error` naming the layer;
20
26
  * `plausibilityCheck`'s `bdcDB`/`poi` deps are each OPTIONAL, so a missing/absent `bdc_database_path`/
@@ -25,12 +31,12 @@
25
31
  * this file opens at import time (which is exactly why THIS file can't be unit-tested directly; see
26
32
  * `layer-guards.test.ts` for their branch coverage).
27
33
  *
28
- * `mailwoman_filer_lookup` (3a task 7) follows the SAME "requires the layer unconditionally" discipline as
34
+ * `mailwoman_filer_lookup` follows the SAME "requires the layer unconditionally" discipline as
29
35
  * `mailwoman_bdc_filing_landscape` (`assertFilerDatabaseExists` + `openFilerDatabaseIfPresent`, mirroring
30
36
  * `assertBDCDatabaseExists` + the BDC open) — `filerLookup` itself has no optional-dep abstain shape (gate 4 makes
31
37
  * it throw rather than answer unstamped), so a missing filer.db becomes one friendly thrown Error naming the layer.
32
38
  *
33
- * `mailwoman_filer_family` (3b task 9) follows the IDENTICAL discipline, reusing the same two guards — `familyRollup`
39
+ * `mailwoman_filer_family` follows the IDENTICAL discipline, reusing the same two guards — `familyRollup`
34
40
  * has no optional-dep abstain shape either (it throws on a bad `familyID`/`nodeID` XOR or a pre-`filer_family`
35
41
  * schema), so filer.db is required unconditionally here too. Its result — always `FamilyRollup[]`, never `null` or
36
42
  * a bare object — is passed through untouched: this data is who-owns-whom, and a silent reshape here would be a
@@ -57,6 +63,7 @@ import { createRuntimePipeline, type PipelineResult } from "mailwoman"
57
63
  import { geocodeAddress, ShardProvider } from "mailwoman/geocode-core"
58
64
  import { emitOverpassQL } from "mailwoman/poi-overpass"
59
65
  import {
66
+ buildNoGazetteerMessage,
60
67
  createResolverBackend,
61
68
  mailwomanDataRoot,
62
69
  resolveCandidateDBPath,
@@ -94,14 +101,59 @@ const poiDatabasePath = values["poi-db"]
94
101
  */
95
102
  let corePromise: Promise<{ classifier: NeuralAddressClassifier; resolver: Resolver; shards: ShardProvider }> | undefined
96
103
 
104
+ /**
105
+ * The four tools that need {@link loadCore} — every path through `getPlainPipeline`/`getPoiPipeline`/`resolveGeocode`.
106
+ * `mailwoman_layer_manifest`, `mailwoman_bdc_filing_landscape`, `mailwoman_filer_lookup` and `mailwoman_filer_family`
107
+ * never call it, so they keep working when this fails; `mailwoman_plausibility_check` only reaches it when it geocodes.
108
+ * Named in both guard messages below because an agent that just got one needs to know what it can still do.
109
+ */
110
+ const CORE_BACKED_TOOLS = "mailwoman_parse, mailwoman_geocode, mailwoman_poi_search, mailwoman_overpass_export"
111
+
112
+ const CORE_FREE_TOOLS =
113
+ "mailwoman_layer_manifest, mailwoman_bdc_filing_landscape, mailwoman_filer_lookup, mailwoman_filer_family"
114
+
97
115
  function loadCore(): Promise<{ classifier: NeuralAddressClassifier; resolver: Resolver; shards: ShardProvider }> {
98
116
  corePromise ??= (async () => {
99
117
  const resolverMod = await import("@mailwoman/resolver-wof-sqlite")
100
118
  const wofPaths = wofShardPaths().filter(existsSync)
101
119
  const candidateDb = resolveCandidateDBPath()
120
+
121
+ // #1009 friendly-failure discipline, the MCP shape of it. `server.ts` turns a thrown Error into an
122
+ // `isError` tool result carrying `error.message`, so the message an agent reads IS whatever is thrown
123
+ // here — which made the raw internal `resolveShards: at least one shard is required` the first thing a
124
+ // stranger saw from `mailwoman_parse` on a fresh install (measured 2026-08-03 against a standalone
125
+ // `npm install @mailwoman/mcp`). Same preflight as `photon`/`nominatim`/`mailwoman serve`, and the same
126
+ // discovery: #1444 moved the `<data-root>/wof/candidate.db` convention fallback INTO
127
+ // `resolveCandidateDBPath`, so this bare call picks a pulled gazetteer up with nothing exported. The
128
+ // `MAILWOMAN_DATA_ROOT` in the client's `env` block is enough on its own.
129
+ if (!candidateDb && !wofPaths.length) {
130
+ throw new Error(
131
+ `${buildNoGazetteerMessage({
132
+ dataRoot: mailwomanDataRoot(),
133
+ docsPath: "/docs/developers/how-to/use-the-mcp-server",
134
+ })}\n\n Needs it: ${CORE_BACKED_TOOLS}\n Works without it: ${CORE_FREE_TOOLS}`
135
+ )
136
+ }
137
+
102
138
  const backend = createResolverBackend(resolverMod, { wofPaths, candidateDb })
103
139
  const resolver = createWOFResolver(backend)
104
- const classifier = await NeuralAddressClassifier.loadFromWeights({ locale: "en-US" })
140
+
141
+ // Same discipline for the model weights. `@mailwoman/neural-weights-en-us` is a declared dependency of
142
+ // this package as of 2026-08-03 — before that a standalone `npm install @mailwoman/mcp` resolved
143
+ // nothing and every core-backed tool answered with `resolveWeights`' raw not-found text. The guard keeps
144
+ // that text (it already names the exact fix command) and adds what an agent mid-conversation needs next:
145
+ // which tools are down and which are not.
146
+ let classifier: NeuralAddressClassifier
147
+
148
+ try {
149
+ classifier = await NeuralAddressClassifier.loadFromWeights({ locale: "en-US" })
150
+ } catch (error) {
151
+ throw new Error(
152
+ `✗ ${error instanceof Error ? error.message : String(error)}\n\n` +
153
+ ` Needs it: ${CORE_BACKED_TOOLS}\n Works without it: ${CORE_FREE_TOOLS}`
154
+ )
155
+ }
156
+
105
157
  const shards = new ShardProvider(resolverMod, mailwomanDataRoot())
106
158
 
107
159
  return { classifier, resolver, shards }
@@ -150,9 +202,9 @@ async function getPoiPipeline(dbPath: string | undefined): Promise<Pipeline> {
150
202
 
151
203
  /**
152
204
  * `plausibilityCheck`'s geocode dep — reuses the SAME shared classifier+resolver `deps.geocode` builds from (see the
153
- * module header's laziness note), wired at this CLI/MCP layer per the 2b task 5 brief ("`deriveGeocodeRegister`/
154
- * formatted register is the geocode dep's concern, wired at the CLI/MCP layer"). The real return type (`GeocodeResult`)
155
- * is structurally assignable to `plausibility.ts`'s minimal `GeocodeLike` — no adapter needed.
205
+ * module header's laziness note). `deriveGeocodeRegister`/the formatted register is the geocode dep's concern, so it is
206
+ * wired at this CLI/MCP layer rather than inside `plausibility.ts`. The real return type (`GeocodeResult`) is
207
+ * structurally assignable to `plausibility.ts`'s minimal `GeocodeLike` — no adapter needed.
156
208
  */
157
209
  async function resolveGeocode(address: string) {
158
210
  const { classifier, resolver, shards } = await loadCore()
@@ -220,7 +272,7 @@ const deps: MCPToolDeps = {
220
272
  },
221
273
 
222
274
  async bdcFilingLandscape(q) {
223
- // Decision 6 (2b task 7): `mailwoman_bdc_filing_landscape` requires bdc.db unconditionally (no optional-dep
275
+ // Decision 6: `mailwoman_bdc_filing_landscape` requires bdc.db unconditionally (no optional-dep
224
276
  // abstain shape exists for this tool), so a missing file becomes a friendly thrown Error naming the layer —
225
277
  // never the raw `node:sqlite` "unable to open database file" message.
226
278
  assertBDCDatabaseExists("mailwoman_bdc_filing_landscape", q.databasePath)
@@ -252,7 +304,7 @@ const deps: MCPToolDeps = {
252
304
  },
253
305
 
254
306
  async filerLookup(q) {
255
- // Decision 6/gate 4 (3a task 7): filerLookup has no optional-dep abstain shape — it throws rather than
307
+ // Decision 6/gate 4: filerLookup has no optional-dep abstain shape — it throws rather than
256
308
  // answer unstamped — so filer.db is required unconditionally, same discipline as bdc.db is for
257
309
  // mailwoman_bdc_filing_landscape.
258
310
  assertFilerDatabaseExists("mailwoman_filer_lookup", q.databasePath)
@@ -280,7 +332,7 @@ const deps: MCPToolDeps = {
280
332
  },
281
333
 
282
334
  async filerFamily(q) {
283
- // Same discipline as mailwoman_filer_lookup (3a task 7) — familyRollup has no optional-dep abstain shape
335
+ // Same discipline as mailwoman_filer_lookup — familyRollup has no optional-dep abstain shape
284
336
  // either, so filer.db is required unconditionally.
285
337
  assertFilerDatabaseExists("mailwoman_filer_family", q.databasePath)
286
338
 
package/layer-guards.ts CHANGED
@@ -3,8 +3,8 @@
3
3
  * @license AGPL-3.0
4
4
  * @author Teffen Ellis, et al.
5
5
  *
6
- * Decision 6 (2b task 7) layer-absent guards — pulled out of `cli.ts` into their own importable module (task 7
7
- * fix round 1 review finding) so the branching itself has direct unit coverage (`layer-guards.test.ts`), not just
6
+ * Decision 6 layer-absent guards — kept out of `cli.ts` in their own importable module so the
7
+ * branching itself has direct unit coverage (`layer-guards.test.ts`), not just
8
8
  * "the tool handler passes an abstain through" (`tools.test.ts`'s stub-level dispatch tests). `cli.ts`
9
9
  * top-level-`await`s a real stdio transport connection at import time, so IT can't be imported by vitest — these
10
10
  * three functions have no such dependency (pure existence-check + open, or a thrown Error), so they live here and
@@ -17,7 +17,7 @@
17
17
  * - `assertBDCDatabaseExists` — `mailwoman_bdc_filing_landscape` requires bdc.db unconditionally (no optional-dep
18
18
  * abstain shape exists for that tool), so a missing file becomes one friendly thrown `Error` naming the layer
19
19
  * instead of the raw `node:sqlite` "unable to open database file" message.
20
- * - `openFilerDatabaseIfPresent` / `assertFilerDatabaseExists` (3a task 7) — the SAME pairing, for filer.db.
20
+ * - `openFilerDatabaseIfPresent` / `assertFilerDatabaseExists` — the SAME pairing, for filer.db.
21
21
  * `mailwoman_filer_lookup` requires filer.db unconditionally (mirrors `mailwoman_bdc_filing_landscape`'s own
22
22
  * "requires the layer" discipline — `filerLookup` itself has no optional-dep abstain shape either, since gate
23
23
  * 4 makes it throw rather than answer unstamped), so `cli.ts` pairs `assertFilerDatabaseExists` (the friendly
@@ -77,7 +77,7 @@ export function assertBDCDatabaseExists(toolName: string, databasePath: string):
77
77
 
78
78
  /**
79
79
  * Open a filer.db, or return `undefined` when `databasePath` is unset or the file is missing — NEVER a raw sqlite throw
80
- * (3a task 7, mirroring {@link openBDCDatabaseIfPresent}). Used by `cli.ts`'s `mailwoman_filer_lookup` handler after
80
+ * (mirroring {@link openBDCDatabaseIfPresent}). Used by `cli.ts`'s `mailwoman_filer_lookup` handler after
81
81
  * {@link assertFilerDatabaseExists} has already confirmed the file is present.
82
82
  */
83
83
  export function openFilerDatabaseIfPresent(
@@ -89,9 +89,9 @@ export function openFilerDatabaseIfPresent(
89
89
  }
90
90
 
91
91
  /**
92
- * Throws a friendly Error naming the layer when `databasePath` doesn't exist — `mailwoman_filer_lookup`'s guard (3a
93
- * task 7, mirroring {@link assertBDCDatabaseExists}). `filerLookup` itself has no optional-dep abstain shape (gate 4
94
- * makes it throw rather than answer unstamped), so filer.db is required unconditionally, same as bdc.db is for
92
+ * Throws a friendly Error naming the layer when `databasePath` doesn't exist — `mailwoman_filer_lookup`'s guard
93
+ * (mirroring {@link assertBDCDatabaseExists}). `filerLookup` itself has no optional-dep abstain shape (gate 4 makes it
94
+ * throw rather than answer unstamped), so filer.db is required unconditionally, same as bdc.db is for
95
95
  * `mailwoman_bdc_filing_landscape`.
96
96
  */
97
97
  export function assertFilerDatabaseExists(toolName: string, databasePath: string): void {
package/out/cli.d.ts CHANGED
@@ -10,11 +10,17 @@
10
10
  * manifest tool, and `@mailwoman/bdc`'s `filingLandscape`/`plausibilityCheck` for the two BDC tools.
11
11
  *
12
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 `mailwoman_overpass_export`/`mailwoman_layer_manifest`,
14
- * neither of which needs the classifier at all). The shared classifier+resolver are built once, on the FIRST call
15
- * to any tool that needs them, and cached for the process lifetime.
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.
16
17
  *
17
- * **Graceful layer-absent guards (2b task 7, decision 6).** Both BDC-backed tools treat a missing/unreadable
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
18
24
  * database file as absence, never a raw `node:sqlite` throw ("unable to open database file"): `bdcFilingLandscape`
19
25
  * requires bdc.db unconditionally, so a missing file becomes one friendly thrown `Error` naming the layer;
20
26
  * `plausibilityCheck`'s `bdcDB`/`poi` deps are each OPTIONAL, so a missing/absent `bdc_database_path`/
@@ -25,12 +31,12 @@
25
31
  * this file opens at import time (which is exactly why THIS file can't be unit-tested directly; see
26
32
  * `layer-guards.test.ts` for their branch coverage).
27
33
  *
28
- * `mailwoman_filer_lookup` (3a task 7) follows the SAME "requires the layer unconditionally" discipline as
34
+ * `mailwoman_filer_lookup` follows the SAME "requires the layer unconditionally" discipline as
29
35
  * `mailwoman_bdc_filing_landscape` (`assertFilerDatabaseExists` + `openFilerDatabaseIfPresent`, mirroring
30
36
  * `assertBDCDatabaseExists` + the BDC open) — `filerLookup` itself has no optional-dep abstain shape (gate 4 makes
31
37
  * it throw rather than answer unstamped), so a missing filer.db becomes one friendly thrown Error naming the layer.
32
38
  *
33
- * `mailwoman_filer_family` (3b task 9) follows the IDENTICAL discipline, reusing the same two guards — `familyRollup`
39
+ * `mailwoman_filer_family` follows the IDENTICAL discipline, reusing the same two guards — `familyRollup`
34
40
  * has no optional-dep abstain shape either (it throws on a bad `familyID`/`nodeID` XOR or a pre-`filer_family`
35
41
  * schema), so filer.db is required unconditionally here too. Its result — always `FamilyRollup[]`, never `null` or
36
42
  * a bare object — is passed through untouched: this data is who-owns-whom, and a silent reshape here would be a
package/out/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG"}
package/out/cli.js CHANGED
@@ -10,11 +10,17 @@
10
10
  * manifest tool, and `@mailwoman/bdc`'s `filingLandscape`/`plausibilityCheck` for the two BDC tools.
11
11
  *
12
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 `mailwoman_overpass_export`/`mailwoman_layer_manifest`,
14
- * neither of which needs the classifier at all). The shared classifier+resolver are built once, on the FIRST call
15
- * to any tool that needs them, and cached for the process lifetime.
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.
16
17
  *
17
- * **Graceful layer-absent guards (2b task 7, decision 6).** Both BDC-backed tools treat a missing/unreadable
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
18
24
  * database file as absence, never a raw `node:sqlite` throw ("unable to open database file"): `bdcFilingLandscape`
19
25
  * requires bdc.db unconditionally, so a missing file becomes one friendly thrown `Error` naming the layer;
20
26
  * `plausibilityCheck`'s `bdcDB`/`poi` deps are each OPTIONAL, so a missing/absent `bdc_database_path`/
@@ -25,12 +31,12 @@
25
31
  * this file opens at import time (which is exactly why THIS file can't be unit-tested directly; see
26
32
  * `layer-guards.test.ts` for their branch coverage).
27
33
  *
28
- * `mailwoman_filer_lookup` (3a task 7) follows the SAME "requires the layer unconditionally" discipline as
34
+ * `mailwoman_filer_lookup` follows the SAME "requires the layer unconditionally" discipline as
29
35
  * `mailwoman_bdc_filing_landscape` (`assertFilerDatabaseExists` + `openFilerDatabaseIfPresent`, mirroring
30
36
  * `assertBDCDatabaseExists` + the BDC open) — `filerLookup` itself has no optional-dep abstain shape (gate 4 makes
31
37
  * it throw rather than answer unstamped), so a missing filer.db becomes one friendly thrown Error naming the layer.
32
38
  *
33
- * `mailwoman_filer_family` (3b task 9) follows the IDENTICAL discipline, reusing the same two guards — `familyRollup`
39
+ * `mailwoman_filer_family` follows the IDENTICAL discipline, reusing the same two guards — `familyRollup`
34
40
  * has no optional-dep abstain shape either (it throws on a bad `familyID`/`nodeID` XOR or a pre-`filer_family`
35
41
  * schema), so filer.db is required unconditionally here too. Its result — always `FamilyRollup[]`, never `null` or
36
42
  * a bare object — is passed through untouched: this data is who-owns-whom, and a silent reshape here would be a
@@ -54,7 +60,7 @@ import { createWOFResolver } from "@mailwoman/resolver";
54
60
  import { createRuntimePipeline } from "mailwoman";
55
61
  import { geocodeAddress, ShardProvider } from "mailwoman/geocode-core";
56
62
  import { emitOverpassQL } from "mailwoman/poi-overpass";
57
- import { createResolverBackend, mailwomanDataRoot, resolveCandidateDBPath, wofShardPaths, } from "mailwoman/resolver-backend";
63
+ import { buildNoGazetteerMessage, createResolverBackend, mailwomanDataRoot, resolveCandidateDBPath, wofShardPaths, } from "mailwoman/resolver-backend";
58
64
  import { assertBDCDatabaseExists, assertFilerDatabaseExists, openBDCDatabaseIfPresent, openFilerDatabaseIfPresent, openPlausibilityPOIDeps, } from "./layer-guards.js";
59
65
  import { createMCPServer } from "./server.js";
60
66
  const { values } = parseArgs({
@@ -75,14 +81,48 @@ const poiDatabasePath = values["poi-db"];
75
81
  * already on the data root — same selection `nominatim`/`photon`'s CLIs make.
76
82
  */
77
83
  let corePromise;
84
+ /**
85
+ * The four tools that need {@link loadCore} — every path through `getPlainPipeline`/`getPoiPipeline`/`resolveGeocode`.
86
+ * `mailwoman_layer_manifest`, `mailwoman_bdc_filing_landscape`, `mailwoman_filer_lookup` and `mailwoman_filer_family`
87
+ * never call it, so they keep working when this fails; `mailwoman_plausibility_check` only reaches it when it geocodes.
88
+ * Named in both guard messages below because an agent that just got one needs to know what it can still do.
89
+ */
90
+ const CORE_BACKED_TOOLS = "mailwoman_parse, mailwoman_geocode, mailwoman_poi_search, mailwoman_overpass_export";
91
+ const CORE_FREE_TOOLS = "mailwoman_layer_manifest, mailwoman_bdc_filing_landscape, mailwoman_filer_lookup, mailwoman_filer_family";
78
92
  function loadCore() {
79
93
  corePromise ??= (async () => {
80
94
  const resolverMod = await import("@mailwoman/resolver-wof-sqlite");
81
95
  const wofPaths = wofShardPaths().filter(existsSync);
82
96
  const candidateDb = resolveCandidateDBPath();
97
+ // #1009 friendly-failure discipline, the MCP shape of it. `server.ts` turns a thrown Error into an
98
+ // `isError` tool result carrying `error.message`, so the message an agent reads IS whatever is thrown
99
+ // here — which made the raw internal `resolveShards: at least one shard is required` the first thing a
100
+ // stranger saw from `mailwoman_parse` on a fresh install (measured 2026-08-03 against a standalone
101
+ // `npm install @mailwoman/mcp`). Same preflight as `photon`/`nominatim`/`mailwoman serve`, and the same
102
+ // discovery: #1444 moved the `<data-root>/wof/candidate.db` convention fallback INTO
103
+ // `resolveCandidateDBPath`, so this bare call picks a pulled gazetteer up with nothing exported. The
104
+ // `MAILWOMAN_DATA_ROOT` in the client's `env` block is enough on its own.
105
+ if (!candidateDb && !wofPaths.length) {
106
+ throw new Error(`${buildNoGazetteerMessage({
107
+ dataRoot: mailwomanDataRoot(),
108
+ docsPath: "/docs/developers/how-to/use-the-mcp-server",
109
+ })}\n\n Needs it: ${CORE_BACKED_TOOLS}\n Works without it: ${CORE_FREE_TOOLS}`);
110
+ }
83
111
  const backend = createResolverBackend(resolverMod, { wofPaths, candidateDb });
84
112
  const resolver = createWOFResolver(backend);
85
- const classifier = await NeuralAddressClassifier.loadFromWeights({ locale: "en-US" });
113
+ // Same discipline for the model weights. `@mailwoman/neural-weights-en-us` is a declared dependency of
114
+ // this package as of 2026-08-03 — before that a standalone `npm install @mailwoman/mcp` resolved
115
+ // nothing and every core-backed tool answered with `resolveWeights`' raw not-found text. The guard keeps
116
+ // that text (it already names the exact fix command) and adds what an agent mid-conversation needs next:
117
+ // which tools are down and which are not.
118
+ let classifier;
119
+ try {
120
+ classifier = await NeuralAddressClassifier.loadFromWeights({ locale: "en-US" });
121
+ }
122
+ catch (error) {
123
+ throw new Error(`✗ ${error instanceof Error ? error.message : String(error)}\n\n` +
124
+ ` Needs it: ${CORE_BACKED_TOOLS}\n Works without it: ${CORE_FREE_TOOLS}`);
125
+ }
86
126
  const shards = new ShardProvider(resolverMod, mailwomanDataRoot());
87
127
  return { classifier, resolver, shards };
88
128
  })();
@@ -118,9 +158,9 @@ async function getPoiPipeline(dbPath) {
118
158
  }
119
159
  /**
120
160
  * `plausibilityCheck`'s geocode dep — reuses the SAME shared classifier+resolver `deps.geocode` builds from (see the
121
- * module header's laziness note), wired at this CLI/MCP layer per the 2b task 5 brief ("`deriveGeocodeRegister`/
122
- * formatted register is the geocode dep's concern, wired at the CLI/MCP layer"). The real return type (`GeocodeResult`)
123
- * is structurally assignable to `plausibility.ts`'s minimal `GeocodeLike` — no adapter needed.
161
+ * module header's laziness note). `deriveGeocodeRegister`/the formatted register is the geocode dep's concern, so it is
162
+ * wired at this CLI/MCP layer rather than inside `plausibility.ts`. The real return type (`GeocodeResult`) is
163
+ * structurally assignable to `plausibility.ts`'s minimal `GeocodeLike` — no adapter needed.
124
164
  */
125
165
  async function resolveGeocode(address) {
126
166
  const { classifier, resolver, shards } = await loadCore();
@@ -170,7 +210,7 @@ const deps = {
170
210
  return { manifest, coverage };
171
211
  },
172
212
  async bdcFilingLandscape(q) {
173
- // Decision 6 (2b task 7): `mailwoman_bdc_filing_landscape` requires bdc.db unconditionally (no optional-dep
213
+ // Decision 6: `mailwoman_bdc_filing_landscape` requires bdc.db unconditionally (no optional-dep
174
214
  // abstain shape exists for this tool), so a missing file becomes a friendly thrown Error naming the layer —
175
215
  // never the raw `node:sqlite` "unable to open database file" message.
176
216
  assertBDCDatabaseExists("mailwoman_bdc_filing_landscape", q.databasePath);
@@ -195,7 +235,7 @@ const deps = {
195
235
  }
196
236
  },
197
237
  async filerLookup(q) {
198
- // Decision 6/gate 4 (3a task 7): filerLookup has no optional-dep abstain shape — it throws rather than
238
+ // Decision 6/gate 4: filerLookup has no optional-dep abstain shape — it throws rather than
199
239
  // answer unstamped — so filer.db is required unconditionally, same discipline as bdc.db is for
200
240
  // mailwoman_bdc_filing_landscape.
201
241
  assertFilerDatabaseExists("mailwoman_filer_lookup", q.databasePath);
@@ -216,7 +256,7 @@ const deps = {
216
256
  });
217
257
  },
218
258
  async filerFamily(q) {
219
- // Same discipline as mailwoman_filer_lookup (3a task 7) — familyRollup has no optional-dep abstain shape
259
+ // Same discipline as mailwoman_filer_lookup — familyRollup has no optional-dep abstain shape
220
260
  // either, so filer.db is required unconditionally.
221
261
  assertFilerDatabaseExists("mailwoman_filer_family", q.databasePath);
222
262
  using db = openFilerDatabaseIfPresent(q.databasePath);
package/out/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAErC,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAoB,MAAM,gBAAgB,CAAA;AACrF,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAA8B,MAAM,wBAAwB,CAAA;AACtF,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,EAAY,MAAM,sBAAsB,CAAA;AACjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAiB,MAAM,qBAAqB,CAAA;AACtE,OAAO,EAAE,qBAAqB,EAAuB,MAAM,WAAW,CAAA;AACtE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,EACN,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,aAAa,GACb,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EACN,uBAAuB,EACvB,yBAAyB,EACzB,wBAAwB,EACxB,0BAA0B,EAC1B,uBAAuB,GACvB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAG7C,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5B,OAAO,EAAE;QACR,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;KAC5B;IACD,gBAAgB,EAAE,IAAI;CACtB,CAAC,CAAA;AAEF;;;GAGG;AACH,MAAM,eAAe,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAA;AAExC;;;;;GAKG;AACH,IAAI,WAAoH,CAAA;AAExH,SAAS,QAAQ;IAChB,WAAW,KAAK,CAAC,KAAK,IAAI,EAAE;QAC3B,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,gCAAgC,CAAC,CAAA;QAClE,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;QACnD,MAAM,WAAW,GAAG,sBAAsB,EAAE,CAAA;QAC5C,MAAM,OAAO,GAAG,qBAAqB,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAA;QAC7E,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAA;QAC3C,MAAM,UAAU,GAAG,MAAM,uBAAuB,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;QACrF,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,WAAW,EAAE,iBAAiB,EAAE,CAAC,CAAA;QAElE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;IACxC,CAAC,CAAC,EAAE,CAAA;IAEJ,OAAO,WAAW,CAAA;AACnB,CAAC;AAID,IAAI,aAAmC,CAAA;AACvC;;;;GAIG;AACH,MAAM,YAAY,GAAG,IAAI,GAAG,EAAoB,CAAA;AAEhD,KAAK,UAAU,gBAAgB;IAC9B,IAAI,CAAC,aAAa,EAAE,CAAC;QACpB,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAA;QAEjD,aAAa,GAAG,qBAAqB,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAA;IAChE,CAAC;IAED,OAAO,aAAa,CAAA;AACrB,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,MAA0B;IACvD,MAAM,GAAG,GAAG,MAAM,IAAI,EAAE,CAAA;IACxB,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAEpC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAA;IACzB,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAA;IAEjD,MAAM,QAAQ,GAAG,qBAAqB,CAAC;QACtC,UAAU;QACV,QAAQ;QACR,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI;KACzD,CAAC,CAAA;IAEF,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IAE/B,OAAO,QAAQ,CAAA;AAChB,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,cAAc,CAAC,OAAe;IAC5C,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAA;IAEzD,OAAO,cAAc,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAA;AAC7E,CAAC;AAED,MAAM,IAAI,GAAgB;IACzB,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI;QACrB,MAAM,QAAQ,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,cAAc,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,MAAM,gBAAgB,EAAE,CAAA;QAE7F,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAA;IACtB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAI;QACjB,OAAO,cAAc,CAAC,IAAI,CAAC,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,CAAC;QAChB,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,CAAC,CAAC,eAAe,IAAI,eAAe,CAAC,CAAA;QAC3E,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;QAEtC,OAAO,MAAM,CAAC,SAAS,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAA;IACzE,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,KAAK;QACzB,uGAAuG;QACvG,sGAAsG;QACtG,mGAAmG;QACnG,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,eAAe,CAAC,CAAA;QACtD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAA;QACpC,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAA;QAEhC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3C,MAAM,MAAM,GAAG,OAAO,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;YAEvE,MAAM,IAAI,KAAK,CACd,uDAAuD,OAAO,EAAE,IAAI,IAAI,eAAe,GAAG,MAAM,GAAG,CACnG,CAAA;QACF,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,CAAA;QAClC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;QAEnG,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAChE,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,YAAY;QAC/B,MAAM,EAAE,GAAG,IAAI,cAAc,CAAwB;YACpD,QAAQ,EAAE,IAAI,YAAY,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;SAC5D,CAAC,CAAA;QAEF,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,EAAE,CAAC,CAAA;QAE5C,MAAM,QAAQ,GAAG,MAAM,EAAE;aACvB,UAAU,CAAC,gBAAgB,CAAC;aAC5B,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC;YACf,EAAE,CAAC,EAAE,CAAC,KAAK,CAAS,SAAS,CAAC,CAAC,EAAE,CAAC,mBAAmB,CAAC;YACtD,EAAE,CAAC,EAAE,CAAC,GAAG,CAAS,cAAc,CAAC,CAAC,EAAE,CAAC,qBAAqB,CAAC;YAC3D,EAAE,CAAC,EAAE,CAAC,GAAG,CAAS,eAAe,CAAC,CAAC,EAAE,CAAC,mBAAmB,CAAC;SAC1D,CAAC;aACD,gBAAgB,EAAE,CAAA;QAEpB,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAA;IAC9B,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACzB,4GAA4G;QAC5G,4GAA4G;QAC5G,sEAAsE;QACtE,uBAAuB,CAAC,gCAAgC,EAAE,CAAC,CAAC,YAAY,CAAC,CAAA;QAEzE,MAAM,EAAE,GAAG,IAAI,cAAc,CAAc,EAAE,QAAQ,EAAE,IAAI,YAAY,CAAC,CAAC,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA;QAE9G,OAAO,eAAe,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;IACrE,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACxB,MAAM,KAAK,GAAG,wBAAwB,CAAC,CAAC,CAAC,eAAe,CAAC,CAAA;QACzD,MAAM,GAAG,GAAG,MAAM,uBAAuB,CAAC,CAAC,CAAC,eAAe,CAAC,CAAA;QAE5D,IAAI,CAAC;YACJ,OAAO,MAAM,iBAAiB,CAC7B;gBACC,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,cAAc,EAAE,CAAC,CAAC,cAAc;gBAChC,mBAAmB,EAAE,CAAC,CAAC,mBAAmB;aAC1C,EACD,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,CACvC,CAAA;QACF,CAAC;gBAAS,CAAC;YACV,KAAK,EAAE,OAAO,EAAE,CAAA;YAChB,GAAG,EAAE,UAAU,CAAC,OAAO,EAAE,CAAA;QAC1B,CAAC;IACF,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,CAAC;QAClB,uGAAuG;QACvG,+FAA+F;QAC/F,kCAAkC;QAClC,yBAAyB,CAAC,wBAAwB,EAAE,CAAC,CAAC,YAAY,CAAC,CAAA;QAEnE,MAAM,EAAE,GAAG,0BAA0B,CAAC,CAAC,CAAC,YAAY,CAAE,CAAA;QAEtD,IAAI,GAAoB,CAAA;QAExB,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;YAE3B,IAAI,CAAC,MAAM,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC,GAAG,sBAAsB,CAAC,CAAA;YACzE,CAAC;YAED,GAAG,GAAG,MAAM,CAAA;QACb,CAAC;QAED,OAAO,WAAW,CAAC,EAAE,EAAE;YACtB,GAAG;YACH,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,aAAa,EAAE,CAAC,CAAC,aAAa;YAC9B,IAAI,EAAE,CAAC,CAAC,IAAI;SACZ,CAAC,CAAA;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,CAAC;QAClB,yGAAyG;QACzG,mDAAmD;QACnD,yBAAyB,CAAC,wBAAwB,EAAE,CAAC,CAAC,YAAY,CAAC,CAAA;QAEnE,MAAM,EAAE,GAAG,0BAA0B,CAAC,CAAC,CAAC,YAAY,CAAE,CAAA;QAEtD,OAAO,YAAY,CAAC,EAAE,EAAE;YACvB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,IAAI,EAAE,CAAC,CAAC,IAAI;SACZ,CAAC,CAAA;IACH,CAAC;CACD,CAAA;AAED,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,CAAC,CAAA;AACpC,MAAM,EAAE,oBAAoB,EAAE,GAAG,MAAM,MAAM,CAAC,2CAA2C,CAAC,CAAA;AAE1F,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAA"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":"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"}
@@ -3,8 +3,8 @@
3
3
  * @license AGPL-3.0
4
4
  * @author Teffen Ellis, et al.
5
5
  *
6
- * Decision 6 (2b task 7) layer-absent guards — pulled out of `cli.ts` into their own importable module (task 7
7
- * fix round 1 review finding) so the branching itself has direct unit coverage (`layer-guards.test.ts`), not just
6
+ * Decision 6 layer-absent guards — kept out of `cli.ts` in their own importable module so the
7
+ * branching itself has direct unit coverage (`layer-guards.test.ts`), not just
8
8
  * "the tool handler passes an abstain through" (`tools.test.ts`'s stub-level dispatch tests). `cli.ts`
9
9
  * top-level-`await`s a real stdio transport connection at import time, so IT can't be imported by vitest — these
10
10
  * three functions have no such dependency (pure existence-check + open, or a thrown Error), so they live here and
@@ -17,7 +17,7 @@
17
17
  * - `assertBDCDatabaseExists` — `mailwoman_bdc_filing_landscape` requires bdc.db unconditionally (no optional-dep
18
18
  * abstain shape exists for that tool), so a missing file becomes one friendly thrown `Error` naming the layer
19
19
  * instead of the raw `node:sqlite` "unable to open database file" message.
20
- * - `openFilerDatabaseIfPresent` / `assertFilerDatabaseExists` (3a task 7) — the SAME pairing, for filer.db.
20
+ * - `openFilerDatabaseIfPresent` / `assertFilerDatabaseExists` — the SAME pairing, for filer.db.
21
21
  * `mailwoman_filer_lookup` requires filer.db unconditionally (mirrors `mailwoman_bdc_filing_landscape`'s own
22
22
  * "requires the layer" discipline — `filerLookup` itself has no optional-dep abstain shape either, since gate
23
23
  * 4 makes it throw rather than answer unstamped), so `cli.ts` pairs `assertFilerDatabaseExists` (the friendly
@@ -50,14 +50,14 @@ export declare function openPlausibilityPOIDeps(databasePath: string | undefined
50
50
  export declare function assertBDCDatabaseExists(toolName: string, databasePath: string): void;
51
51
  /**
52
52
  * Open a filer.db, or return `undefined` when `databasePath` is unset or the file is missing — NEVER a raw sqlite throw
53
- * (3a task 7, mirroring {@link openBDCDatabaseIfPresent}). Used by `cli.ts`'s `mailwoman_filer_lookup` handler after
53
+ * (mirroring {@link openBDCDatabaseIfPresent}). Used by `cli.ts`'s `mailwoman_filer_lookup` handler after
54
54
  * {@link assertFilerDatabaseExists} has already confirmed the file is present.
55
55
  */
56
56
  export declare function openFilerDatabaseIfPresent(databasePath: string | undefined): DatabaseClient<FilerDatabase> | undefined;
57
57
  /**
58
- * Throws a friendly Error naming the layer when `databasePath` doesn't exist — `mailwoman_filer_lookup`'s guard (3a
59
- * task 7, mirroring {@link assertBDCDatabaseExists}). `filerLookup` itself has no optional-dep abstain shape (gate 4
60
- * makes it throw rather than answer unstamped), so filer.db is required unconditionally, same as bdc.db is for
58
+ * Throws a friendly Error naming the layer when `databasePath` doesn't exist — `mailwoman_filer_lookup`'s guard
59
+ * (mirroring {@link assertBDCDatabaseExists}). `filerLookup` itself has no optional-dep abstain shape (gate 4 makes it
60
+ * throw rather than answer unstamped), so filer.db is required unconditionally, same as bdc.db is for
61
61
  * `mailwoman_bdc_filing_landscape`.
62
62
  */
63
63
  export declare function assertFilerDatabaseExists(toolName: string, databasePath: string): void;
@@ -3,8 +3,8 @@
3
3
  * @license AGPL-3.0
4
4
  * @author Teffen Ellis, et al.
5
5
  *
6
- * Decision 6 (2b task 7) layer-absent guards — pulled out of `cli.ts` into their own importable module (task 7
7
- * fix round 1 review finding) so the branching itself has direct unit coverage (`layer-guards.test.ts`), not just
6
+ * Decision 6 layer-absent guards — kept out of `cli.ts` in their own importable module so the
7
+ * branching itself has direct unit coverage (`layer-guards.test.ts`), not just
8
8
  * "the tool handler passes an abstain through" (`tools.test.ts`'s stub-level dispatch tests). `cli.ts`
9
9
  * top-level-`await`s a real stdio transport connection at import time, so IT can't be imported by vitest — these
10
10
  * three functions have no such dependency (pure existence-check + open, or a thrown Error), so they live here and
@@ -17,7 +17,7 @@
17
17
  * - `assertBDCDatabaseExists` — `mailwoman_bdc_filing_landscape` requires bdc.db unconditionally (no optional-dep
18
18
  * abstain shape exists for that tool), so a missing file becomes one friendly thrown `Error` naming the layer
19
19
  * instead of the raw `node:sqlite` "unable to open database file" message.
20
- * - `openFilerDatabaseIfPresent` / `assertFilerDatabaseExists` (3a task 7) — the SAME pairing, for filer.db.
20
+ * - `openFilerDatabaseIfPresent` / `assertFilerDatabaseExists` — the SAME pairing, for filer.db.
21
21
  * `mailwoman_filer_lookup` requires filer.db unconditionally (mirrors `mailwoman_bdc_filing_landscape`'s own
22
22
  * "requires the layer" discipline — `filerLookup` itself has no optional-dep abstain shape either, since gate
23
23
  * 4 makes it throw rather than answer unstamped), so `cli.ts` pairs `assertFilerDatabaseExists` (the friendly
@@ -67,7 +67,7 @@ export function assertBDCDatabaseExists(toolName, databasePath) {
67
67
  }
68
68
  /**
69
69
  * Open a filer.db, or return `undefined` when `databasePath` is unset or the file is missing — NEVER a raw sqlite throw
70
- * (3a task 7, mirroring {@link openBDCDatabaseIfPresent}). Used by `cli.ts`'s `mailwoman_filer_lookup` handler after
70
+ * (mirroring {@link openBDCDatabaseIfPresent}). Used by `cli.ts`'s `mailwoman_filer_lookup` handler after
71
71
  * {@link assertFilerDatabaseExists} has already confirmed the file is present.
72
72
  */
73
73
  export function openFilerDatabaseIfPresent(databasePath) {
@@ -76,9 +76,9 @@ export function openFilerDatabaseIfPresent(databasePath) {
76
76
  return new DatabaseClient({ database: new DatabaseSync(databasePath, { readOnly: true }) });
77
77
  }
78
78
  /**
79
- * Throws a friendly Error naming the layer when `databasePath` doesn't exist — `mailwoman_filer_lookup`'s guard (3a
80
- * task 7, mirroring {@link assertBDCDatabaseExists}). `filerLookup` itself has no optional-dep abstain shape (gate 4
81
- * makes it throw rather than answer unstamped), so filer.db is required unconditionally, same as bdc.db is for
79
+ * Throws a friendly Error naming the layer when `databasePath` doesn't exist — `mailwoman_filer_lookup`'s guard
80
+ * (mirroring {@link assertBDCDatabaseExists}). `filerLookup` itself has no optional-dep abstain shape (gate 4 makes it
81
+ * throw rather than answer unstamped), so filer.db is required unconditionally, same as bdc.db is for
82
82
  * `mailwoman_bdc_filing_landscape`.
83
83
  */
84
84
  export function assertFilerDatabaseExists(toolName, databasePath) {
package/out/tools.d.ts CHANGED
@@ -24,12 +24,12 @@
24
24
  * - `mailwoman_plausibility_check` — score one claimed broadband-service assertion against BDC filing evidence and
25
25
  * nearby telecom infrastructure (`@mailwoman/bdc`'s `plausibilityCheck`), returning a positive-evidence-only bundle
26
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 (2b task 7, decision 6).
28
- * - `mailwoman_filer_lookup` (3a task 7) — read the FCC filer identity crosswalk (`@mailwoman/filer`'s
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
29
  * `filerLookup`) for one identifier (FRN, Form 499 ID, or BDC provider ID): every OTHER identifier it shares an
30
30
  * authoritative edge with, its current attributes, its authoritative entity cluster, and any inferred links —
31
31
  * reported separately, never merged into the cluster. `as_of` is always present (defaults to today).
32
- * - `mailwoman_filer_family` (3b task 9) — read a corporate family's membership (`@mailwoman/filer/sdk`'s
32
+ * - `mailwoman_filer_family` — read a corporate family's membership (`@mailwoman/filer/sdk`'s
33
33
  * `familyRollup`) from a filer.db layer database, given a `family_id` or a `node_id`. Distinct from an entity
34
34
  * cluster (same filer, different identifiers) — a corporate family spans several DIFFERENT filers under a
35
35
  * holding/parent/subsidiary/management relationship. The handler passes `familyRollup`'s result through
package/out/tools.js CHANGED
@@ -24,12 +24,12 @@
24
24
  * - `mailwoman_plausibility_check` — score one claimed broadband-service assertion against BDC filing evidence and
25
25
  * nearby telecom infrastructure (`@mailwoman/bdc`'s `plausibilityCheck`), returning a positive-evidence-only bundle
26
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 (2b task 7, decision 6).
28
- * - `mailwoman_filer_lookup` (3a task 7) — read the FCC filer identity crosswalk (`@mailwoman/filer`'s
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
29
  * `filerLookup`) for one identifier (FRN, Form 499 ID, or BDC provider ID): every OTHER identifier it shares an
30
30
  * authoritative edge with, its current attributes, its authoritative entity cluster, and any inferred links —
31
31
  * reported separately, never merged into the cluster. `as_of` is always present (defaults to today).
32
- * - `mailwoman_filer_family` (3b task 9) — read a corporate family's membership (`@mailwoman/filer/sdk`'s
32
+ * - `mailwoman_filer_family` — read a corporate family's membership (`@mailwoman/filer/sdk`'s
33
33
  * `familyRollup`) from a filer.db layer database, given a `family_id` or a `node_id`. Distinct from an entity
34
34
  * cluster (same filer, different identifiers) — a corporate family spans several DIFFERENT filers under a
35
35
  * holding/parent/subsidiary/management relationship. The handler passes `familyRollup`'s result through
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mailwoman/mcp",
3
- "version": "8.5.0",
3
+ "version": "9.0.0",
4
4
  "description": "MCP server — mailwoman's spatial toolset for agents (parse, geocode, poi_search, overpass_export, layer_manifest).",
5
5
  "license": "AGPL-3.0-only OR LicenseRef-Commercial",
6
6
  "repository": {
@@ -45,19 +45,20 @@
45
45
  }
46
46
  },
47
47
  "dependencies": {
48
- "@mailwoman/bdc": "8.5.0",
49
- "@mailwoman/core": "8.5.0",
50
- "@mailwoman/filer": "8.5.0",
51
- "@mailwoman/neural": "8.5.0",
52
- "@mailwoman/poi-taxonomy": "8.5.0",
53
- "@mailwoman/resolver": "8.5.0",
54
- "@mailwoman/resolver-wof-sqlite": "8.5.0",
55
- "@modelcontextprotocol/sdk": "^1.29.0",
56
- "mailwoman": "8.5.0",
48
+ "@mailwoman/bdc": "9.0.0",
49
+ "@mailwoman/core": "9.0.0",
50
+ "@mailwoman/filer": "9.0.0",
51
+ "@mailwoman/neural": "9.0.0",
52
+ "@mailwoman/neural-weights-en-us": "9.0.0",
53
+ "@mailwoman/poi-taxonomy": "9.0.0",
54
+ "@mailwoman/resolver": "9.0.0",
55
+ "@mailwoman/resolver-wof-sqlite": "9.0.0",
56
+ "@modelcontextprotocol/sdk": "^1.30.0",
57
+ "mailwoman": "9.0.0",
57
58
  "zod": "^4.4.3"
58
59
  },
59
60
  "peerDependencies": {
60
- "@mailwoman/resolver-wof-sqlite": "8.5.0"
61
+ "@mailwoman/resolver-wof-sqlite": "9.0.0"
61
62
  },
62
63
  "peerDependenciesMeta": {
63
64
  "@mailwoman/resolver-wof-sqlite": {
package/tools.ts CHANGED
@@ -24,12 +24,12 @@
24
24
  * - `mailwoman_plausibility_check` — score one claimed broadband-service assertion against BDC filing evidence and
25
25
  * nearby telecom infrastructure (`@mailwoman/bdc`'s `plausibilityCheck`), returning a positive-evidence-only bundle
26
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 (2b task 7, decision 6).
28
- * - `mailwoman_filer_lookup` (3a task 7) — read the FCC filer identity crosswalk (`@mailwoman/filer`'s
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
29
  * `filerLookup`) for one identifier (FRN, Form 499 ID, or BDC provider ID): every OTHER identifier it shares an
30
30
  * authoritative edge with, its current attributes, its authoritative entity cluster, and any inferred links —
31
31
  * reported separately, never merged into the cluster. `as_of` is always present (defaults to today).
32
- * - `mailwoman_filer_family` (3b task 9) — read a corporate family's membership (`@mailwoman/filer/sdk`'s
32
+ * - `mailwoman_filer_family` — read a corporate family's membership (`@mailwoman/filer/sdk`'s
33
33
  * `familyRollup`) from a filer.db layer database, given a `family_id` or a `node_id`. Distinct from an entity
34
34
  * cluster (same filer, different identifiers) — a corporate family spans several DIFFERENT filers under a
35
35
  * holding/parent/subsidiary/management relationship. The handler passes `familyRollup`'s result through