@mailwoman/mcp 8.3.0 → 8.5.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/cli.ts +120 -5
- package/layer-guards.ts +101 -0
- package/out/cli.d.ts +24 -2
- package/out/cli.d.ts.map +1 -1
- package/out/cli.js +95 -4
- package/out/cli.js.map +1 -1
- package/out/layer-guards.d.ts +64 -0
- package/out/layer-guards.d.ts.map +1 -0
- package/out/layer-guards.js +89 -0
- package/out/layer-guards.js.map +1 -0
- package/out/server.d.ts +3 -3
- package/out/server.js +3 -3
- package/out/tools.d.ts +48 -1
- package/out/tools.d.ts.map +1 -1
- package/out/tools.js +189 -1
- package/out/tools.js.map +1 -1
- package/package.json +10 -8
- package/server.ts +3 -3
- package/tools.ts +251 -1
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
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
|
|
8
|
+
* "the tool handler passes an abstain through" (`tools.test.ts`'s stub-level dispatch tests). `cli.ts`
|
|
9
|
+
* top-level-`await`s a real stdio transport connection at import time, so IT can't be imported by vitest — these
|
|
10
|
+
* three functions have no such dependency (pure existence-check + open, or a thrown Error), so they live here and
|
|
11
|
+
* `cli.ts` just calls them.
|
|
12
|
+
*
|
|
13
|
+
* - `openBDCDatabaseIfPresent` / `openPlausibilityPOIDeps` — `mailwoman_plausibility_check`'s `bdcDB`/`poi` deps
|
|
14
|
+
* (`PlausibilityDeps`) are each OPTIONAL, so a missing/absent path degrades to `undefined`, which
|
|
15
|
+
* `plausibilityCheck` (`@mailwoman/bdc`) already turns into a typed abstain evidence entry
|
|
16
|
+
* (`{type:"abstain", reason:"requires_bdc_layer"|"requires_build_local_layer"}`) — never a raw sqlite throw.
|
|
17
|
+
* - `assertBDCDatabaseExists` — `mailwoman_bdc_filing_landscape` requires bdc.db unconditionally (no optional-dep
|
|
18
|
+
* abstain shape exists for that tool), so a missing file becomes one friendly thrown `Error` naming the layer
|
|
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.
|
|
21
|
+
* `mailwoman_filer_lookup` requires filer.db unconditionally (mirrors `mailwoman_bdc_filing_landscape`'s own
|
|
22
|
+
* "requires the layer" discipline — `filerLookup` itself has no optional-dep abstain shape either, since gate
|
|
23
|
+
* 4 makes it throw rather than answer unstamped), so `cli.ts` pairs `assertFilerDatabaseExists` (the friendly
|
|
24
|
+
* throw) with `openFilerDatabaseIfPresent` (the actual open) the same way `bdcFilingLandscape`'s handler does.
|
|
25
|
+
*/
|
|
26
|
+
import { existsSync } from "node:fs";
|
|
27
|
+
import { DatabaseSync } from "node:sqlite";
|
|
28
|
+
import { DatabaseClient } from "@mailwoman/core/kysley/client";
|
|
29
|
+
/**
|
|
30
|
+
* Open a bdc.db, or return `undefined` when `databasePath` is unset or the file is missing — NEVER a raw sqlite throw.
|
|
31
|
+
* See the module header.
|
|
32
|
+
*/
|
|
33
|
+
export function openBDCDatabaseIfPresent(databasePath) {
|
|
34
|
+
if (!databasePath || !existsSync(databasePath))
|
|
35
|
+
return undefined;
|
|
36
|
+
return new DatabaseClient({ database: new DatabaseSync(databasePath, { readOnly: true }) });
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Same graceful discipline as {@link openBDCDatabaseIfPresent}, for the poi.db side of `plausibilityCheck`'s deps —
|
|
40
|
+
* `undefined` here becomes the `{type:"abstain", reason:"requires_build_local_layer"}` entry `plausibilityCheck`
|
|
41
|
+
* already produces when a claimed technology's physical-plant categories can't be searched. `POILookup` is dynamically
|
|
42
|
+
* imported (matching `cli.ts`'s existing `resolver-wof-sqlite` laziness) since it's only ever needed when a caller
|
|
43
|
+
* actually wires a poi.db. `lookup` and `contractDB` share ONE `DatabaseSync` handle (the AGENTS.md "one connection,
|
|
44
|
+
* shared" convention) — a real poi.db's rows and its `layer_manifest`/`layer_coverage` tables live in the same file in
|
|
45
|
+
* production, so disposing `contractDB` (which closes the shared handle) is enough; `POILookup` never owns it
|
|
46
|
+
* (constructed with `{database}`, not `{databasePath}` — see `poi-lookup.ts`), so it never double-closes.
|
|
47
|
+
*/
|
|
48
|
+
export async function openPlausibilityPOIDeps(databasePath) {
|
|
49
|
+
if (!databasePath || !existsSync(databasePath))
|
|
50
|
+
return undefined;
|
|
51
|
+
const { POILookup } = await import("@mailwoman/resolver-wof-sqlite/poi-lookup");
|
|
52
|
+
const database = new DatabaseSync(databasePath, { readOnly: true });
|
|
53
|
+
return {
|
|
54
|
+
lookup: new POILookup({ database }),
|
|
55
|
+
contractDB: new DatabaseClient({ database }),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Throws a friendly Error naming the layer when `databasePath` doesn't exist — `mailwoman_bdc_filing_landscape`'s guard
|
|
60
|
+
* (decision 6b). `toolName` is threaded through so the message matches whichever tool calls this (today: only
|
|
61
|
+
* `mailwoman_bdc_filing_landscape`).
|
|
62
|
+
*/
|
|
63
|
+
export function assertBDCDatabaseExists(toolName, databasePath) {
|
|
64
|
+
if (!existsSync(databasePath)) {
|
|
65
|
+
throw new Error(`${toolName}: bdc.db not found at "${databasePath}"`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
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
|
|
71
|
+
* {@link assertFilerDatabaseExists} has already confirmed the file is present.
|
|
72
|
+
*/
|
|
73
|
+
export function openFilerDatabaseIfPresent(databasePath) {
|
|
74
|
+
if (!databasePath || !existsSync(databasePath))
|
|
75
|
+
return undefined;
|
|
76
|
+
return new DatabaseClient({ database: new DatabaseSync(databasePath, { readOnly: true }) });
|
|
77
|
+
}
|
|
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
|
|
82
|
+
* `mailwoman_bdc_filing_landscape`.
|
|
83
|
+
*/
|
|
84
|
+
export function assertFilerDatabaseExists(toolName, databasePath) {
|
|
85
|
+
if (!existsSync(databasePath)) {
|
|
86
|
+
throw new Error(`${toolName}: filer.db not found at "${databasePath}"`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=layer-guards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layer-guards.js","sourceRoot":"","sources":["../layer-guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG1C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAI9D;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,YAAgC;IACxE,IAAI,CAAC,YAAY,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,SAAS,CAAA;IAEhE,OAAO,IAAI,cAAc,CAAc,EAAE,QAAQ,EAAE,IAAI,YAAY,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA;AACzG,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,YAAgC;IAC7E,IAAI,CAAC,YAAY,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,SAAS,CAAA;IAEhE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,2CAA2C,CAAC,CAAA;IAC/E,MAAM,QAAQ,GAAG,IAAI,YAAY,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IAEnE,OAAO;QACN,MAAM,EAAE,IAAI,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;QACnC,UAAU,EAAE,IAAI,cAAc,CAAwB,EAAE,QAAQ,EAAE,CAAC;KACnE,CAAA;AACF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAgB,EAAE,YAAoB;IAC7E,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,0BAA0B,YAAY,GAAG,CAAC,CAAA;IACtE,CAAC;AACF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CACzC,YAAgC;IAEhC,IAAI,CAAC,YAAY,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,SAAS,CAAA;IAEhE,OAAO,IAAI,cAAc,CAAgB,EAAE,QAAQ,EAAE,IAAI,YAAY,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA;AAC3G,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,QAAgB,EAAE,YAAoB;IAC/E,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,4BAA4B,YAAY,GAAG,CAAC,CAAA;IACxE,CAAC;AACF,CAAC"}
|
package/out/server.d.ts
CHANGED
|
@@ -12,9 +12,9 @@ import { type MCPToolDeps } from "./tools.ts";
|
|
|
12
12
|
/**
|
|
13
13
|
* Build an `McpServer` with every `tools.ts` tool registered. A handler's returned value is JSON-stringified into a
|
|
14
14
|
* single `text` content block — every tool here answers with structured data (parse trees, geocode results, search
|
|
15
|
-
* hits), so a plain JSON text block is the simplest faithful rendering; none of the
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* hits), so a plain JSON text block is the simplest faithful rendering; none of the tools need images, resource links,
|
|
16
|
+
* or other MCP content kinds. A thrown error becomes an `isError` tool result instead of a protocol-level failure, so a
|
|
17
|
+
* bad address / missing db surfaces to the agent as a normal (if unsuccessful) tool call.
|
|
18
18
|
*/
|
|
19
19
|
export declare function createMCPServer(deps: MCPToolDeps): McpServer;
|
|
20
20
|
//# sourceMappingURL=server.d.ts.map
|
package/out/server.js
CHANGED
|
@@ -19,9 +19,9 @@ const MCP_SERVER_VERSION = "7.1.0";
|
|
|
19
19
|
/**
|
|
20
20
|
* Build an `McpServer` with every `tools.ts` tool registered. A handler's returned value is JSON-stringified into a
|
|
21
21
|
* single `text` content block — every tool here answers with structured data (parse trees, geocode results, search
|
|
22
|
-
* hits), so a plain JSON text block is the simplest faithful rendering; none of the
|
|
23
|
-
*
|
|
24
|
-
*
|
|
22
|
+
* hits), so a plain JSON text block is the simplest faithful rendering; none of the tools need images, resource links,
|
|
23
|
+
* or other MCP content kinds. A thrown error becomes an `isError` tool result instead of a protocol-level failure, so a
|
|
24
|
+
* bad address / missing db surfaces to the agent as a normal (if unsuccessful) tool call.
|
|
25
25
|
*/
|
|
26
26
|
export function createMCPServer(deps) {
|
|
27
27
|
const server = new McpServer({ name: "mailwoman", version: MCP_SERVER_VERSION });
|
package/out/tools.d.ts
CHANGED
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
* file (the actual product surface) is testable without any MCP plumbing — `tools.test.ts` calls
|
|
9
9
|
* `buildToolTable` directly with stub deps.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
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):
|
|
12
14
|
*
|
|
13
15
|
* - `mailwoman_parse` — the runtime pipeline's parse (optionally POI-aware).
|
|
14
16
|
* - `mailwoman_geocode` — the street-level geocode cascade (`mailwoman/geocode-core`).
|
|
@@ -17,6 +19,21 @@
|
|
|
17
19
|
* we never run it".
|
|
18
20
|
* - `mailwoman_layer_manifest` — read a spatial-layer database's provenance manifest + coverage summary
|
|
19
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 (2b task 7, decision 6).
|
|
28
|
+
* - `mailwoman_filer_lookup` (3a task 7) — 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` (3b task 9) — 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.
|
|
20
37
|
*/
|
|
21
38
|
import { z } from "zod";
|
|
22
39
|
/**
|
|
@@ -33,6 +50,36 @@ export interface MCPToolDeps {
|
|
|
33
50
|
}) => Promise<unknown>;
|
|
34
51
|
overpassExport: (query: string) => Promise<string>;
|
|
35
52
|
layerManifest: (databasePath: string) => Promise<unknown>;
|
|
53
|
+
bdcFilingLandscape: (q: {
|
|
54
|
+
databasePath: string;
|
|
55
|
+
geoids?: string[];
|
|
56
|
+
h3Cells?: number[];
|
|
57
|
+
}) => Promise<unknown>;
|
|
58
|
+
plausibilityCheck: (q: {
|
|
59
|
+
bdcDatabasePath?: string;
|
|
60
|
+
poiDatabasePath?: string;
|
|
61
|
+
address?: string;
|
|
62
|
+
point?: {
|
|
63
|
+
type: "Point";
|
|
64
|
+
coordinates: [number, number];
|
|
65
|
+
};
|
|
66
|
+
geoid?: string;
|
|
67
|
+
technologyCode: number;
|
|
68
|
+
claimedDownloadMbps: number;
|
|
69
|
+
}) => Promise<unknown>;
|
|
70
|
+
filerLookup: (q: {
|
|
71
|
+
databasePath: string;
|
|
72
|
+
frn?: string;
|
|
73
|
+
form499ID?: string;
|
|
74
|
+
bdcProviderID?: number;
|
|
75
|
+
asOf?: string;
|
|
76
|
+
}) => Promise<unknown>;
|
|
77
|
+
filerFamily: (q: {
|
|
78
|
+
databasePath: string;
|
|
79
|
+
familyID?: string;
|
|
80
|
+
nodeID?: string;
|
|
81
|
+
asOf?: string;
|
|
82
|
+
}) => Promise<unknown>;
|
|
36
83
|
}
|
|
37
84
|
/**
|
|
38
85
|
* One MCP tool. `inputSchema` is a plain Zod object (not `any` — this repo's oxlint config errors on
|
package/out/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../tools.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACnE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAC3C,SAAS,EAAE,CAAC,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAC/E,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAClD,aAAa,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACzD,kBAAkB,EAAE,CAAC,CAAC,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAC5G,iBAAiB,EAAE,CAAC,CAAC,EAAE;QACtB,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,KAAK,CAAC,EAAE;YAAE,IAAI,EAAE,OAAO,CAAC;YAAC,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;SAAE,CAAA;QACxD,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,cAAc,EAAE,MAAM,CAAA;QACtB,mBAAmB,EAAE,MAAM,CAAA;KAC3B,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACtB,WAAW,EAAE,CAAC,CAAC,EAAE;QAChB,YAAY,EAAE,MAAM,CAAA;QACpB,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,IAAI,CAAC,EAAE,MAAM,CAAA;KACb,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACtB,WAAW,EAAE,CAAC,CAAC,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACjH;AAED;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAA;IACvC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAC5D;AA+KD;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,EAAE,CAwJ9D"}
|
package/out/tools.js
CHANGED
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
* file (the actual product surface) is testable without any MCP plumbing — `tools.test.ts` calls
|
|
9
9
|
* `buildToolTable` directly with stub deps.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
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):
|
|
12
14
|
*
|
|
13
15
|
* - `mailwoman_parse` — the runtime pipeline's parse (optionally POI-aware).
|
|
14
16
|
* - `mailwoman_geocode` — the street-level geocode cascade (`mailwoman/geocode-core`).
|
|
@@ -17,6 +19,21 @@
|
|
|
17
19
|
* we never run it".
|
|
18
20
|
* - `mailwoman_layer_manifest` — read a spatial-layer database's provenance manifest + coverage summary
|
|
19
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 (2b task 7, decision 6).
|
|
28
|
+
* - `mailwoman_filer_lookup` (3a task 7) — 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` (3b task 9) — 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.
|
|
20
37
|
*/
|
|
21
38
|
import { z } from "zod";
|
|
22
39
|
const ParseInputSchema = z.object({
|
|
@@ -51,6 +68,103 @@ const LayerManifestInputSchema = z.object({
|
|
|
51
68
|
.min(1)
|
|
52
69
|
.describe("Path to a mailwoman spatial-layer database (poi.db, an address-points shard, etc.)."),
|
|
53
70
|
});
|
|
71
|
+
const BDCFilingLandscapeInputSchema = z.object({
|
|
72
|
+
database_path: z
|
|
73
|
+
.string()
|
|
74
|
+
.min(1)
|
|
75
|
+
.describe("Path to a bdc.db layer database (FCC Broadband Data Collection availability)."),
|
|
76
|
+
geoids: z
|
|
77
|
+
.array(z.string())
|
|
78
|
+
.min(1)
|
|
79
|
+
.optional()
|
|
80
|
+
.describe("15-character census block GEOIDs to query. Provide exactly one of `geoids` or `h3_cells` — never both, never neither, never empty."),
|
|
81
|
+
h3_cells: z
|
|
82
|
+
.array(z.number())
|
|
83
|
+
.min(1)
|
|
84
|
+
.optional()
|
|
85
|
+
.describe("Resolution-9 short H3 cell integers (the bdc.db availability spine) to query directly. Provide exactly " +
|
|
86
|
+
"one of `geoids` or `h3_cells` — never both, never neither, never empty."),
|
|
87
|
+
});
|
|
88
|
+
const PlausibilityCheckPointInputSchema = z.object({
|
|
89
|
+
type: z.literal("Point").describe('GeoJSON geometry type — always "Point".'),
|
|
90
|
+
coordinates: z
|
|
91
|
+
.tuple([z.number(), z.number()])
|
|
92
|
+
.describe("[longitude, latitude] pair, GeoJSON coordinate order (longitude first)."),
|
|
93
|
+
});
|
|
94
|
+
const PlausibilityCheckInputSchema = z.object({
|
|
95
|
+
bdc_database_path: z
|
|
96
|
+
.string()
|
|
97
|
+
.optional()
|
|
98
|
+
.describe("Path to a bdc.db layer database (FCC Broadband Data Collection availability). Omit — or point at a file " +
|
|
99
|
+
"that doesn't exist — to abstain on filing evidence rather than error."),
|
|
100
|
+
poi_database_path: z
|
|
101
|
+
.string()
|
|
102
|
+
.optional()
|
|
103
|
+
.describe("Path to a poi.db layer database carrying the telecom-infrastructure categories (`telecom_exchange`, " +
|
|
104
|
+
"`tower_comms`, etc.). Omit — or point at a file that doesn't exist — to abstain on physical-plant " +
|
|
105
|
+
"evidence rather than error."),
|
|
106
|
+
address: z
|
|
107
|
+
.string()
|
|
108
|
+
.optional()
|
|
109
|
+
.describe("The claimed service location as a free-text postal address, geocoded via the server's runtime pipeline " +
|
|
110
|
+
"when `point` isn't also given. At least one of `address`, `point`, or `geoid` is required."),
|
|
111
|
+
point: PlausibilityCheckPointInputSchema.optional().describe("The claimed service location as a GeoJSON Point, bypassing geocoding. At least one of `address`, `point`, " +
|
|
112
|
+
"or `geoid` is required."),
|
|
113
|
+
geoid: z
|
|
114
|
+
.string()
|
|
115
|
+
.optional()
|
|
116
|
+
.describe("15-character census block GEOID for the claimed service location — the exact, native filing-evidence " +
|
|
117
|
+
"path (no h3-cell approximation). May be supplied alongside `point`/`address` (geoid drives filing " +
|
|
118
|
+
"evidence; the point drives physical-plant evidence independently). At least one of `address`, " +
|
|
119
|
+
"`point`, or `geoid` is required."),
|
|
120
|
+
technology_code: z
|
|
121
|
+
.number()
|
|
122
|
+
.describe("FCC BDC technology code for the claimed service, e.g. 50 = optical carrier fiber (BroadbandTechnologyCode)."),
|
|
123
|
+
claimed_download_mbps: z.number().describe("The claimed downstream speed in Mbps."),
|
|
124
|
+
});
|
|
125
|
+
const FilerLookupInputSchema = z.object({
|
|
126
|
+
database_path: z.string().min(1).describe("Path to a filer.db layer database (FCC filer identity crosswalk)."),
|
|
127
|
+
frn: z
|
|
128
|
+
.string()
|
|
129
|
+
.optional()
|
|
130
|
+
.describe("The zero-padded 10-digit FCC Registration Number to look up, e.g. '0001753557'. Provide exactly one of " +
|
|
131
|
+
"`frn`, `form499_id`, or `bdc_provider_id` — never more than one, never none."),
|
|
132
|
+
form499_id: z
|
|
133
|
+
.string()
|
|
134
|
+
.optional()
|
|
135
|
+
.describe("The FCC Form 499 filer ID to look up. Provide exactly one of `frn`, `form499_id`, or `bdc_provider_id` — " +
|
|
136
|
+
"never more than one, never none."),
|
|
137
|
+
bdc_provider_id: z
|
|
138
|
+
.number()
|
|
139
|
+
.optional()
|
|
140
|
+
.describe("The FCC BDC provider_id to look up. Provide exactly one of `frn`, `form499_id`, or `bdc_provider_id` — " +
|
|
141
|
+
"never more than one, never none."),
|
|
142
|
+
as_of: z
|
|
143
|
+
.string()
|
|
144
|
+
.optional()
|
|
145
|
+
.describe("ISO date (YYYY-MM-DD) to scope the lookup as-of — only relationships valid on or before this date, and not " +
|
|
146
|
+
"yet closed by it, are included. Defaults to today; the result always states the date actually used."),
|
|
147
|
+
});
|
|
148
|
+
const FilerFamilyInputSchema = z.object({
|
|
149
|
+
database_path: z.string().min(1).describe("Path to a filer.db layer database (FCC filer identity crosswalk)."),
|
|
150
|
+
family_id: z
|
|
151
|
+
.string()
|
|
152
|
+
.optional()
|
|
153
|
+
.describe("The canonicalized family_id to roll up, e.g. as returned by mailwoman_filer_lookup's `families` field. " +
|
|
154
|
+
"Provide exactly one of `family_id` or `node_id` — never both, never neither."),
|
|
155
|
+
node_id: z
|
|
156
|
+
.string()
|
|
157
|
+
.optional()
|
|
158
|
+
.describe("A filer-graph node_id (e.g. 'frn:0001753557') to resolve EVERY corporate family it currently belongs to " +
|
|
159
|
+
"— a node may legitimately belong to more than one (e.g. a different holding company vs. management " +
|
|
160
|
+
"company). Provide exactly one of `family_id` or `node_id` — never both, never neither."),
|
|
161
|
+
as_of: z
|
|
162
|
+
.string()
|
|
163
|
+
.optional()
|
|
164
|
+
.describe("ISO date (YYYY-MM-DD) to scope the rollup as-of — only family memberships valid on or before this date, " +
|
|
165
|
+
"and not yet closed by it, are included. Defaults to today; each returned family states the date " +
|
|
166
|
+
"actually used."),
|
|
167
|
+
});
|
|
54
168
|
/**
|
|
55
169
|
* Build the tool table for a concrete `MCPToolDeps` implementation. Pure — no transport, no I/O of its own.
|
|
56
170
|
*/
|
|
@@ -112,6 +226,80 @@ export function buildToolTable(deps) {
|
|
|
112
226
|
return deps.layerManifest(databasePath);
|
|
113
227
|
},
|
|
114
228
|
},
|
|
229
|
+
{
|
|
230
|
+
name: "mailwoman_bdc_filing_landscape",
|
|
231
|
+
description: "Read the FCC Broadband Data Collection (BDC) provider/technology/speed-bucket filing census over a set " +
|
|
232
|
+
"of census blocks (`geoids`) or H3 cells (`h3_cells`) from a bdc.db layer database. Returns the source " +
|
|
233
|
+
"vintage, how many queried blocks were surveyed vs. unknown (never surveyed), and the filing summary. " +
|
|
234
|
+
"Provide exactly one of `geoids` or `h3_cells`.",
|
|
235
|
+
inputSchema: BDCFilingLandscapeInputSchema,
|
|
236
|
+
handler: async (args) => {
|
|
237
|
+
const { database_path, geoids, h3_cells } = BDCFilingLandscapeInputSchema.parse(args);
|
|
238
|
+
return deps.bdcFilingLandscape({ databasePath: database_path, geoids, h3Cells: h3_cells });
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
name: "mailwoman_plausibility_check",
|
|
243
|
+
description: "Score one claimed broadband-service assertion (technology + speed at a location) against the FCC BDC " +
|
|
244
|
+
"filing census and nearby telecom infrastructure, returning an evidence bundle: filings that corroborate " +
|
|
245
|
+
"(or don't), nearby physical plant, and a coverage_confidence reflecting survey completeness. NEVER " +
|
|
246
|
+
"returns a verdict stronger than 'no supporting evidence found' — absence of evidence degrades " +
|
|
247
|
+
"confidence, it never disproves the claim. Provide at least one of `address`, `point`, or `geoid`.",
|
|
248
|
+
inputSchema: PlausibilityCheckInputSchema,
|
|
249
|
+
handler: async (args) => {
|
|
250
|
+
const { bdc_database_path, poi_database_path, address, point, geoid, technology_code, claimed_download_mbps } = PlausibilityCheckInputSchema.parse(args);
|
|
251
|
+
return deps.plausibilityCheck({
|
|
252
|
+
bdcDatabasePath: bdc_database_path,
|
|
253
|
+
poiDatabasePath: poi_database_path,
|
|
254
|
+
address,
|
|
255
|
+
point,
|
|
256
|
+
geoid,
|
|
257
|
+
technologyCode: technology_code,
|
|
258
|
+
claimedDownloadMbps: claimed_download_mbps,
|
|
259
|
+
});
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
name: "mailwoman_filer_lookup",
|
|
264
|
+
description: "Look up the FCC filer identity crosswalk for one identifier (FRN, Form 499 filer ID, or BDC provider_id) " +
|
|
265
|
+
"from a filer.db layer database: every OTHER identifier it shares an authoritative edge with (never " +
|
|
266
|
+
"collapsed — a provider_id carrying multiple FRNs reports all of them), its current attributes, its " +
|
|
267
|
+
"authoritative entity cluster, and any inferred links reported SEPARATELY with their score — never merged " +
|
|
268
|
+
"into the cluster. Scoped `as_of` a date (defaults to today, always present in the result). Provide " +
|
|
269
|
+
"exactly one of `frn`, `form499_id`, or `bdc_provider_id`.",
|
|
270
|
+
inputSchema: FilerLookupInputSchema,
|
|
271
|
+
handler: async (args) => {
|
|
272
|
+
const { database_path, frn, form499_id, bdc_provider_id, as_of } = FilerLookupInputSchema.parse(args);
|
|
273
|
+
return deps.filerLookup({
|
|
274
|
+
databasePath: database_path,
|
|
275
|
+
frn,
|
|
276
|
+
form499ID: form499_id,
|
|
277
|
+
bdcProviderID: bdc_provider_id,
|
|
278
|
+
asOf: as_of,
|
|
279
|
+
});
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
name: "mailwoman_filer_family",
|
|
284
|
+
description: "Read a corporate family's full membership from a filer.db layer database — a holding/parent/subsidiary/" +
|
|
285
|
+
"management tree spanning several DIFFERENT filers, distinct from an entity cluster (same filer, " +
|
|
286
|
+
"different identifiers). Given `family_id`, returns that one family's members; given `node_id`, " +
|
|
287
|
+
"resolves EVERY family that node currently belongs to (a node MAY belong to more than one). Each " +
|
|
288
|
+
"returned family reports its members with relationship, source, and assertion (`authoritative` — the " +
|
|
289
|
+
"source document states the membership — vs `inferred` — a name match concluded it, with its " +
|
|
290
|
+
"match_score), a deduped distinct_member_count, and its known display names. Provide exactly one of " +
|
|
291
|
+
"`family_id` or `node_id`.",
|
|
292
|
+
inputSchema: FilerFamilyInputSchema,
|
|
293
|
+
handler: async (args) => {
|
|
294
|
+
const { database_path, family_id, node_id, as_of } = FilerFamilyInputSchema.parse(args);
|
|
295
|
+
return deps.filerFamily({
|
|
296
|
+
databasePath: database_path,
|
|
297
|
+
familyID: family_id,
|
|
298
|
+
nodeID: node_id,
|
|
299
|
+
asOf: as_of,
|
|
300
|
+
});
|
|
301
|
+
},
|
|
302
|
+
},
|
|
115
303
|
];
|
|
116
304
|
}
|
|
117
305
|
//# sourceMappingURL=tools.js.map
|
package/out/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../tools.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mailwoman/mcp",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.5.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,17 +45,19 @@
|
|
|
45
45
|
}
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@mailwoman/
|
|
49
|
-
"@mailwoman/
|
|
50
|
-
"@mailwoman/
|
|
51
|
-
"@mailwoman/
|
|
52
|
-
"@mailwoman/
|
|
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",
|
|
53
55
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
54
|
-
"mailwoman": "8.
|
|
56
|
+
"mailwoman": "8.5.0",
|
|
55
57
|
"zod": "^4.4.3"
|
|
56
58
|
},
|
|
57
59
|
"peerDependencies": {
|
|
58
|
-
"@mailwoman/resolver-wof-sqlite": "8.
|
|
60
|
+
"@mailwoman/resolver-wof-sqlite": "8.5.0"
|
|
59
61
|
},
|
|
60
62
|
"peerDependenciesMeta": {
|
|
61
63
|
"@mailwoman/resolver-wof-sqlite": {
|
package/server.ts
CHANGED
|
@@ -24,9 +24,9 @@ const MCP_SERVER_VERSION = "7.1.0"
|
|
|
24
24
|
/**
|
|
25
25
|
* Build an `McpServer` with every `tools.ts` tool registered. A handler's returned value is JSON-stringified into a
|
|
26
26
|
* single `text` content block — every tool here answers with structured data (parse trees, geocode results, search
|
|
27
|
-
* hits), so a plain JSON text block is the simplest faithful rendering; none of the
|
|
28
|
-
*
|
|
29
|
-
*
|
|
27
|
+
* hits), so a plain JSON text block is the simplest faithful rendering; none of the tools need images, resource links,
|
|
28
|
+
* or other MCP content kinds. A thrown error becomes an `isError` tool result instead of a protocol-level failure, so a
|
|
29
|
+
* bad address / missing db surfaces to the agent as a normal (if unsuccessful) tool call.
|
|
30
30
|
*/
|
|
31
31
|
export function createMCPServer(deps: MCPToolDeps): McpServer {
|
|
32
32
|
const server = new McpServer({ name: "mailwoman", version: MCP_SERVER_VERSION })
|