@mailwoman/mcp 10.0.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/README.md +1 -1
- package/cli/main.ts +282 -0
- package/lib/layer-guards.ts +44 -27
- package/lib/server.ts +24 -12
- package/lib/tools.ts +8 -39
- package/out/cli/main.d.ts +8 -0
- package/out/cli/main.d.ts.map +1 -0
- package/out/cli/main.js +187 -0
- package/out/cli/main.js.map +1 -0
- package/out/layer-guards.d.ts +41 -26
- package/out/layer-guards.d.ts.map +1 -1
- package/out/layer-guards.js +36 -22
- package/out/layer-guards.js.map +1 -1
- package/out/server.d.ts +10 -6
- package/out/server.d.ts.map +1 -1
- package/out/server.js +23 -12
- package/out/server.js.map +1 -1
- package/out/tools.d.ts +8 -39
- package/out/tools.d.ts.map +1 -1
- package/out/tools.js +2 -33
- package/out/tools.js.map +1 -1
- package/package.json +44 -45
- package/lib/cli.ts +0 -373
- package/out/cli.d.ts +0 -51
- package/out/cli.d.ts.map +0 -1
- package/out/cli.js +0 -282
- package/out/cli.js.map +0 -1
package/out/cli/main.js
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @copyright Sister Software
|
|
4
|
+
* @license AGPL-3.0
|
|
5
|
+
* @author Teffen Ellis, et al.
|
|
6
|
+
*/
|
|
7
|
+
import { filingLandscape, plausibilityCheck } from "@mailwoman/bdc";
|
|
8
|
+
import { dataRootPath } from "@mailwoman/core/data-root";
|
|
9
|
+
import { pathExists } from "@mailwoman/core/fs/readers";
|
|
10
|
+
import { readLayerManifest } from "@mailwoman/core/layers";
|
|
11
|
+
import { parseArguments } from "@mailwoman/core/scripting/arguments";
|
|
12
|
+
import { familyRollup } from "@mailwoman/filer/family-rollup";
|
|
13
|
+
import { filerLookup } from "@mailwoman/filer/filer-lookup";
|
|
14
|
+
import { toFRN } from "@mailwoman/filer/frn";
|
|
15
|
+
import { NeuralAddressClassifier } from "@mailwoman/neural";
|
|
16
|
+
import { getPOICategory } from "@mailwoman/poi-taxonomy";
|
|
17
|
+
import { emitOverpassQL } from "@mailwoman/poi-taxonomy/overpass";
|
|
18
|
+
import { createWOFResolver } from "@mailwoman/resolver";
|
|
19
|
+
import { wofExtractPaths } from "@mailwoman/resolver-wof-sqlite/paths";
|
|
20
|
+
import { DatabaseClient } from "@mailwoman/sqlite/client";
|
|
21
|
+
import { createRuntimePipeline } from "mailwoman";
|
|
22
|
+
import { geocodeAddress, USStateDatabaseProvider } from "mailwoman/geocode";
|
|
23
|
+
import { buildNoGazetteerMessage, createResolverBackend, resolveCandidateDBPath } from "mailwoman/resolver-backend";
|
|
24
|
+
import { assertBDCDatabaseExists, assertFilerDatabaseExists, openBDCDatabaseIfPresent, openFilerDatabaseIfPresent, openPlausibilityPOIDeps, } from "#layer-guards";
|
|
25
|
+
import { createMCPServer } from "#server";
|
|
26
|
+
const { values } = parseArguments({
|
|
27
|
+
options: {
|
|
28
|
+
"poi-db": { type: "string" },
|
|
29
|
+
},
|
|
30
|
+
allowPositionals: true,
|
|
31
|
+
});
|
|
32
|
+
const poiDatabasePath = values["poi-db"];
|
|
33
|
+
let corePromise;
|
|
34
|
+
const CORE_BACKED_TOOLS = "mailwoman_parse, mailwoman_geocode, mailwoman_poi_search, mailwoman_overpass_export";
|
|
35
|
+
const CORE_FREE_TOOLS = "mailwoman_layer_manifest, mailwoman_bdc_filing_landscape, mailwoman_filer_lookup, mailwoman_filer_family";
|
|
36
|
+
function loadCore() {
|
|
37
|
+
corePromise ??= (async () => {
|
|
38
|
+
const resolverMod = await import("@mailwoman/resolver-wof-sqlite");
|
|
39
|
+
const wofPaths = [];
|
|
40
|
+
for (const extractPath of wofExtractPaths()) {
|
|
41
|
+
if (await pathExists(extractPath)) {
|
|
42
|
+
wofPaths.push(extractPath);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const candidateDB = await resolveCandidateDBPath();
|
|
46
|
+
if (!candidateDB && !wofPaths.length) {
|
|
47
|
+
throw new Error(`${buildNoGazetteerMessage({
|
|
48
|
+
dataRoot: dataRootPath(),
|
|
49
|
+
docsPath: "/docs/developers/how-to/use-the-mcp-server",
|
|
50
|
+
})}\n\n Needs it: ${CORE_BACKED_TOOLS}\n Works without it: ${CORE_FREE_TOOLS}`);
|
|
51
|
+
}
|
|
52
|
+
const backend = await createResolverBackend(resolverMod, { wofPaths, candidateDB });
|
|
53
|
+
const resolver = createWOFResolver(backend);
|
|
54
|
+
let classifier;
|
|
55
|
+
try {
|
|
56
|
+
classifier = await NeuralAddressClassifier.loadRoutedFromWeights({ locale: "en-US" });
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
throw new Error(`✗ ${error instanceof Error ? error.message : String(error)}\n\n` +
|
|
60
|
+
` Needs it: ${CORE_BACKED_TOOLS}\n Works without it: ${CORE_FREE_TOOLS}`);
|
|
61
|
+
}
|
|
62
|
+
const databases = await USStateDatabaseProvider.create(resolverMod, dataRootPath());
|
|
63
|
+
return { classifier, resolver, databases };
|
|
64
|
+
})();
|
|
65
|
+
return corePromise;
|
|
66
|
+
}
|
|
67
|
+
let plainPipeline;
|
|
68
|
+
const poiPipelines = new Map();
|
|
69
|
+
async function getPlainPipeline() {
|
|
70
|
+
if (!plainPipeline) {
|
|
71
|
+
const { classifier, resolver } = await loadCore();
|
|
72
|
+
plainPipeline = createRuntimePipeline({ classifier, resolver });
|
|
73
|
+
}
|
|
74
|
+
return plainPipeline;
|
|
75
|
+
}
|
|
76
|
+
async function getPoiPipeline(dbPath) {
|
|
77
|
+
const key = dbPath ?? "";
|
|
78
|
+
const cached = poiPipelines.get(key);
|
|
79
|
+
if (cached)
|
|
80
|
+
return cached;
|
|
81
|
+
const { classifier, resolver } = await loadCore();
|
|
82
|
+
const pipeline = createRuntimePipeline({
|
|
83
|
+
classifier,
|
|
84
|
+
resolver,
|
|
85
|
+
poiQueryKind: dbPath ? { poiDatabasePath: dbPath } : true,
|
|
86
|
+
});
|
|
87
|
+
poiPipelines.set(key, pipeline);
|
|
88
|
+
return pipeline;
|
|
89
|
+
}
|
|
90
|
+
async function resolveGeocode(address) {
|
|
91
|
+
const { classifier, resolver, databases } = await loadCore();
|
|
92
|
+
return geocodeAddress(address, { classifier, resolver, databases: databases.for });
|
|
93
|
+
}
|
|
94
|
+
const deps = {
|
|
95
|
+
async parse(text, opts) {
|
|
96
|
+
const pipeline = opts?.poi ? await getPoiPipeline(poiDatabasePath) : await getPlainPipeline();
|
|
97
|
+
return pipeline(text);
|
|
98
|
+
},
|
|
99
|
+
async geocode(text) {
|
|
100
|
+
return resolveGeocode(text);
|
|
101
|
+
},
|
|
102
|
+
async poiSearch(q) {
|
|
103
|
+
const pipeline = await getPoiPipeline(q.poiDatabasePath ?? poiDatabasePath);
|
|
104
|
+
const result = await pipeline(q.query);
|
|
105
|
+
return result.poiIntent ?? { type: "abstain", reason: "not_poi_shaped" };
|
|
106
|
+
},
|
|
107
|
+
async overpassExport(query) {
|
|
108
|
+
const pipeline = await getPoiPipeline(poiDatabasePath);
|
|
109
|
+
const result = await pipeline(query);
|
|
110
|
+
const outcome = result.poiIntent;
|
|
111
|
+
if (!outcome || outcome.type !== "intent") {
|
|
112
|
+
const reason = outcome?.type === "abstain" ? `: ${outcome.reason}` : "";
|
|
113
|
+
throw new Error(`mailwoman_overpass_export: query is not POI-shaped (${outcome?.type ?? "no poi intent"}${reason})`);
|
|
114
|
+
}
|
|
115
|
+
const { subject } = outcome.intent;
|
|
116
|
+
const osmTags = subject.kind === "category"
|
|
117
|
+
? subject.categoryIDs.map((id) => getPOICategory(id)?.osmTag).filter((tag) => tag !== undefined)
|
|
118
|
+
: [];
|
|
119
|
+
return emitOverpassQL(outcome.intent, subject.kind === "category" && osmTags.length === subject.categoryIDs.length ? { osmTags } : {});
|
|
120
|
+
},
|
|
121
|
+
async layerManifest(databasePath) {
|
|
122
|
+
using db = new DatabaseClient(databasePath, { readOnly: true });
|
|
123
|
+
const manifest = await readLayerManifest(db);
|
|
124
|
+
const coverage = await db
|
|
125
|
+
.selectFrom("layer_coverage")
|
|
126
|
+
.select((eb) => [
|
|
127
|
+
eb.fn.count("h3_cell").as("surveyedCellCount"),
|
|
128
|
+
eb.fn.avg("completeness").as("averageCompleteness"),
|
|
129
|
+
eb.fn.sum("observed_rows").as("totalObservedRows"),
|
|
130
|
+
])
|
|
131
|
+
.executeTakeFirst();
|
|
132
|
+
return { manifest, coverage };
|
|
133
|
+
},
|
|
134
|
+
async bdcFilingLandscape(q) {
|
|
135
|
+
await assertBDCDatabaseExists("mailwoman_bdc_filing_landscape", q.databasePath);
|
|
136
|
+
using db = new DatabaseClient(q.databasePath, { readOnly: true });
|
|
137
|
+
return await filingLandscape(db, { geoids: q.geoids, h3Cells: q.h3Cells });
|
|
138
|
+
},
|
|
139
|
+
async plausibilityCheck(q) {
|
|
140
|
+
const bdcDB = await openBDCDatabaseIfPresent(q.bdcDatabasePath);
|
|
141
|
+
const poi = await openPlausibilityPOIDeps(q.poiDatabasePath);
|
|
142
|
+
try {
|
|
143
|
+
return await plausibilityCheck({
|
|
144
|
+
address: q.address,
|
|
145
|
+
point: q.point,
|
|
146
|
+
geoid: q.geoid,
|
|
147
|
+
technologyCode: q.technologyCode,
|
|
148
|
+
claimedDownloadMbps: q.claimedDownloadMbps,
|
|
149
|
+
}, { bdcDB, poi, geocode: resolveGeocode });
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
bdcDB?.destroy();
|
|
153
|
+
poi?.schemadb.destroy();
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
async filerLookup(q) {
|
|
157
|
+
await assertFilerDatabaseExists("mailwoman_filer_lookup", q.databasePath);
|
|
158
|
+
using db = (await openFilerDatabaseIfPresent(q.databasePath));
|
|
159
|
+
let frn;
|
|
160
|
+
if (q.frn !== undefined) {
|
|
161
|
+
const parsed = toFRN(q.frn);
|
|
162
|
+
if (!parsed) {
|
|
163
|
+
throw new Error(`mailwoman_filer_lookup: "${q.frn}" is not a valid FRN`);
|
|
164
|
+
}
|
|
165
|
+
frn = parsed;
|
|
166
|
+
}
|
|
167
|
+
return await filerLookup(db, {
|
|
168
|
+
frn,
|
|
169
|
+
form499ID: q.form499ID,
|
|
170
|
+
bdcProviderID: q.bdcProviderID,
|
|
171
|
+
asOf: q.asOf,
|
|
172
|
+
});
|
|
173
|
+
},
|
|
174
|
+
async filerFamily(q) {
|
|
175
|
+
await assertFilerDatabaseExists("mailwoman_filer_family", q.databasePath);
|
|
176
|
+
using db = (await openFilerDatabaseIfPresent(q.databasePath));
|
|
177
|
+
return await familyRollup(db, {
|
|
178
|
+
familyID: q.familyID,
|
|
179
|
+
nodeID: q.nodeID,
|
|
180
|
+
asOf: q.asOf,
|
|
181
|
+
});
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
const server = createMCPServer(deps);
|
|
185
|
+
const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
|
|
186
|
+
await server.connect(new StdioServerTransport());
|
|
187
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../cli/main.ts"],"names":[],"mappings":"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"}
|
package/out/layer-guards.d.ts
CHANGED
|
@@ -6,18 +6,18 @@
|
|
|
6
6
|
* Decision 6 layer-absent guards — kept out of `cli.ts` in their own importable module so the
|
|
7
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
|
-
* top-level-`await`s a real stdio transport connection at import time, so IT can't be imported by vitest
|
|
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
|
|
11
11
|
* `cli.ts` just calls them.
|
|
12
12
|
*
|
|
13
13
|
* - `openBDCDatabaseIfPresent` / `openPlausibilityPOIDeps` — `mailwoman_plausibility_check`'s `bdcDB`/`poi` deps
|
|
14
|
-
* (`PlausibilityDeps`) are each
|
|
14
|
+
* (`PlausibilityDeps`) are each optional, so a missing/absent path degrades to `undefined`, which
|
|
15
15
|
* `plausibilityCheck` (`@mailwoman/bdc`) already turns into a typed abstain evidence entry
|
|
16
16
|
* (`{type:"abstain", reason:"requires_bdc_layer"|"requires_build_local_layer"}`) — never a raw sqlite throw.
|
|
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` — the
|
|
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 criterion
|
|
23
23
|
* 4 makes it throw rather than answer unstamped), so `cli.ts` pairs `assertFilerDatabaseExists` (the friendly
|
|
@@ -26,39 +26,54 @@
|
|
|
26
26
|
import type { BDCDatabase, PlausibilityDeps } from "@mailwoman/bdc";
|
|
27
27
|
import type { FilerDatabase } from "@mailwoman/filer";
|
|
28
28
|
import { DatabaseClient } from "@mailwoman/sqlite/client";
|
|
29
|
+
import type { PathBuilderLike } from "path-ts";
|
|
29
30
|
/**
|
|
30
|
-
* Open a bdc.db, or return `undefined` when `databasePath` is unset
|
|
31
|
+
* Open a bdc.db, or return `undefined` when `databasePath` is unset
|
|
32
|
+
* or the file is missing, never a raw sqlite throw.
|
|
33
|
+
*
|
|
31
34
|
* See the module header.
|
|
32
35
|
*/
|
|
33
|
-
export declare function openBDCDatabaseIfPresent(databasePath:
|
|
36
|
+
export declare function openBDCDatabaseIfPresent(databasePath: PathBuilderLike | undefined): Promise<DatabaseClient<BDCDatabase> | undefined>;
|
|
34
37
|
/**
|
|
35
|
-
* Same graceful discipline as {@link openBDCDatabaseIfPresent}, for the poi.db
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
38
|
+
* Same graceful discipline as {@link openBDCDatabaseIfPresent}, for the poi.db
|
|
39
|
+
* side of `plausibilityCheck`'s deps.
|
|
40
|
+
*
|
|
41
|
+
* `undefined` here becomes the `{type:"abstain", reason:"requires_build_local_layer"}`
|
|
42
|
+
* entry `plausibilityCheck` already produces when a claimed technology's
|
|
43
|
+
* physical-plant categories can't be searched.
|
|
44
|
+
*
|
|
45
|
+
* `POILookup` is dynamically imported (matching `cli.ts`'s existing `resolver-wof-sqlite` laziness)
|
|
46
|
+
* since it's only ever needed when a caller actually wires a poi.db.
|
|
47
|
+
* `lookup` and `schemadb` share one `DatabaseSync` handle
|
|
48
|
+
* (the agents.md "one connection, shared" convention) — a real poi.db's rows
|
|
49
|
+
* and its `layer_manifest`/`layer_coverage` tables live in the same file in production,
|
|
50
|
+
* so disposing `schemadb` (which closes the shared handle) is enough; `POILookup` never owns it
|
|
42
51
|
* (constructed with `{database}`, not `{databasePath}` — see `poi-lookup.ts`), so it never double-closes.
|
|
43
52
|
*/
|
|
44
|
-
export declare function openPlausibilityPOIDeps(databasePath:
|
|
53
|
+
export declare function openPlausibilityPOIDeps(databasePath: PathBuilderLike | undefined): Promise<PlausibilityDeps["poi"]>;
|
|
45
54
|
/**
|
|
46
|
-
* Throws a friendly Error naming the layer when `databasePath` doesn't exist —
|
|
47
|
-
* (decision 6b).
|
|
48
|
-
*
|
|
55
|
+
* Throws a friendly Error naming the layer when `databasePath` doesn't exist —
|
|
56
|
+
* `mailwoman_bdc_filing_landscape`'s guard (decision 6b).
|
|
57
|
+
*
|
|
58
|
+
* `toolName` is threaded through so the message matches whichever tool calls this
|
|
59
|
+
* (today: only `mailwoman_bdc_filing_landscape`).
|
|
49
60
|
*/
|
|
50
|
-
export declare function assertBDCDatabaseExists(toolName: string, databasePath:
|
|
61
|
+
export declare function assertBDCDatabaseExists(toolName: string, databasePath: PathBuilderLike): Promise<void>;
|
|
51
62
|
/**
|
|
52
|
-
* Open a filer.db, or return `undefined` when `databasePath` is unset or the file is missing
|
|
53
|
-
* (mirroring {@link openBDCDatabaseIfPresent}).
|
|
54
|
-
*
|
|
63
|
+
* Open a filer.db, or return `undefined` when `databasePath` is unset or the file is missing,
|
|
64
|
+
* never a raw sqlite throw (mirroring {@link openBDCDatabaseIfPresent}).
|
|
65
|
+
*
|
|
66
|
+
* Used by `cli.ts`'s `mailwoman_filer_lookup` handler after {@link assertFilerDatabaseExists}
|
|
67
|
+
* has already confirmed the file is present.
|
|
55
68
|
*/
|
|
56
|
-
export declare function openFilerDatabaseIfPresent(databasePath:
|
|
69
|
+
export declare function openFilerDatabaseIfPresent(databasePath: PathBuilderLike | undefined): Promise<DatabaseClient<FilerDatabase> | undefined>;
|
|
57
70
|
/**
|
|
58
|
-
* Throws a friendly Error naming the layer when `databasePath` doesn't exist —
|
|
59
|
-
* (mirroring {@link assertBDCDatabaseExists}).
|
|
60
|
-
*
|
|
61
|
-
* `
|
|
71
|
+
* Throws a friendly Error naming the layer when `databasePath` doesn't exist —
|
|
72
|
+
* `mailwoman_filer_lookup`'s guard (mirroring {@link assertBDCDatabaseExists}).
|
|
73
|
+
*
|
|
74
|
+
* `filerLookup` itself has no optional-dep abstain shape
|
|
75
|
+
* (criterion 4 makes it throw rather than answer unstamped), so filer.db is required
|
|
76
|
+
* unconditionally, same as bdc.db is for `mailwoman_bdc_filing_landscape`.
|
|
62
77
|
*/
|
|
63
|
-
export declare function assertFilerDatabaseExists(toolName: string, databasePath:
|
|
78
|
+
export declare function assertFilerDatabaseExists(toolName: string, databasePath: PathBuilderLike): Promise<void>;
|
|
64
79
|
//# sourceMappingURL=layer-guards.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layer-guards.d.ts","sourceRoot":"","sources":["../lib/layer-guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"layer-guards.d.ts","sourceRoot":"","sources":["../lib/layer-guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9C;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC7C,YAAY,EAAE,eAAe,GAAG,SAAS,GACvC,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC,CAIlD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,uBAAuB,CAC5C,YAAY,EAAE,eAAe,GAAG,SAAS,GACvC,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAUlC;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAI5G;AAED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC/C,YAAY,EAAE,eAAe,GAAG,SAAS,GACvC,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC,GAAG,SAAS,CAAC,CAIpD;AAED;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAI9G"}
|
package/out/layer-guards.js
CHANGED
|
@@ -6,18 +6,18 @@
|
|
|
6
6
|
* Decision 6 layer-absent guards — kept out of `cli.ts` in their own importable module so the
|
|
7
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
|
-
* top-level-`await`s a real stdio transport connection at import time, so IT can't be imported by vitest
|
|
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
|
|
11
11
|
* `cli.ts` just calls them.
|
|
12
12
|
*
|
|
13
13
|
* - `openBDCDatabaseIfPresent` / `openPlausibilityPOIDeps` — `mailwoman_plausibility_check`'s `bdcDB`/`poi` deps
|
|
14
|
-
* (`PlausibilityDeps`) are each
|
|
14
|
+
* (`PlausibilityDeps`) are each optional, so a missing/absent path degrades to `undefined`, which
|
|
15
15
|
* `plausibilityCheck` (`@mailwoman/bdc`) already turns into a typed abstain evidence entry
|
|
16
16
|
* (`{type:"abstain", reason:"requires_bdc_layer"|"requires_build_local_layer"}`) — never a raw sqlite throw.
|
|
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` — the
|
|
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 criterion
|
|
23
23
|
* 4 makes it throw rather than answer unstamped), so `cli.ts` pairs `assertFilerDatabaseExists` (the friendly
|
|
@@ -26,7 +26,9 @@
|
|
|
26
26
|
import { pathExists } from "@mailwoman/core/fs/readers";
|
|
27
27
|
import { DatabaseClient } from "@mailwoman/sqlite/client";
|
|
28
28
|
/**
|
|
29
|
-
* Open a bdc.db, or return `undefined` when `databasePath` is unset
|
|
29
|
+
* Open a bdc.db, or return `undefined` when `databasePath` is unset
|
|
30
|
+
* or the file is missing, never a raw sqlite throw.
|
|
31
|
+
*
|
|
30
32
|
* See the module header.
|
|
31
33
|
*/
|
|
32
34
|
export async function openBDCDatabaseIfPresent(databasePath) {
|
|
@@ -35,13 +37,19 @@ export async function openBDCDatabaseIfPresent(databasePath) {
|
|
|
35
37
|
return new DatabaseClient(databasePath, { readOnly: true });
|
|
36
38
|
}
|
|
37
39
|
/**
|
|
38
|
-
* Same graceful discipline as {@link openBDCDatabaseIfPresent}, for the poi.db
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
40
|
+
* Same graceful discipline as {@link openBDCDatabaseIfPresent}, for the poi.db
|
|
41
|
+
* side of `plausibilityCheck`'s deps.
|
|
42
|
+
*
|
|
43
|
+
* `undefined` here becomes the `{type:"abstain", reason:"requires_build_local_layer"}`
|
|
44
|
+
* entry `plausibilityCheck` already produces when a claimed technology's
|
|
45
|
+
* physical-plant categories can't be searched.
|
|
46
|
+
*
|
|
47
|
+
* `POILookup` is dynamically imported (matching `cli.ts`'s existing `resolver-wof-sqlite` laziness)
|
|
48
|
+
* since it's only ever needed when a caller actually wires a poi.db.
|
|
49
|
+
* `lookup` and `schemadb` share one `DatabaseSync` handle
|
|
50
|
+
* (the agents.md "one connection, shared" convention) — a real poi.db's rows
|
|
51
|
+
* and its `layer_manifest`/`layer_coverage` tables live in the same file in production,
|
|
52
|
+
* so disposing `schemadb` (which closes the shared handle) is enough; `POILookup` never owns it
|
|
45
53
|
* (constructed with `{database}`, not `{databasePath}` — see `poi-lookup.ts`), so it never double-closes.
|
|
46
54
|
*/
|
|
47
55
|
export async function openPlausibilityPOIDeps(databasePath) {
|
|
@@ -51,13 +59,15 @@ export async function openPlausibilityPOIDeps(databasePath) {
|
|
|
51
59
|
const database = new DatabaseClient(databasePath, { readOnly: true });
|
|
52
60
|
return {
|
|
53
61
|
lookup: new POILookup({ database }),
|
|
54
|
-
|
|
62
|
+
schemadb: database,
|
|
55
63
|
};
|
|
56
64
|
}
|
|
57
65
|
/**
|
|
58
|
-
* Throws a friendly Error naming the layer when `databasePath` doesn't exist —
|
|
59
|
-
* (decision 6b).
|
|
60
|
-
*
|
|
66
|
+
* Throws a friendly Error naming the layer when `databasePath` doesn't exist —
|
|
67
|
+
* `mailwoman_bdc_filing_landscape`'s guard (decision 6b).
|
|
68
|
+
*
|
|
69
|
+
* `toolName` is threaded through so the message matches whichever tool calls this
|
|
70
|
+
* (today: only `mailwoman_bdc_filing_landscape`).
|
|
61
71
|
*/
|
|
62
72
|
export async function assertBDCDatabaseExists(toolName, databasePath) {
|
|
63
73
|
if (!(await pathExists(databasePath))) {
|
|
@@ -65,9 +75,11 @@ export async function assertBDCDatabaseExists(toolName, databasePath) {
|
|
|
65
75
|
}
|
|
66
76
|
}
|
|
67
77
|
/**
|
|
68
|
-
* Open a filer.db, or return `undefined` when `databasePath` is unset or the file is missing
|
|
69
|
-
* (mirroring {@link openBDCDatabaseIfPresent}).
|
|
70
|
-
*
|
|
78
|
+
* Open a filer.db, or return `undefined` when `databasePath` is unset or the file is missing,
|
|
79
|
+
* never a raw sqlite throw (mirroring {@link openBDCDatabaseIfPresent}).
|
|
80
|
+
*
|
|
81
|
+
* Used by `cli.ts`'s `mailwoman_filer_lookup` handler after {@link assertFilerDatabaseExists}
|
|
82
|
+
* has already confirmed the file is present.
|
|
71
83
|
*/
|
|
72
84
|
export async function openFilerDatabaseIfPresent(databasePath) {
|
|
73
85
|
if (!databasePath || !(await pathExists(databasePath)))
|
|
@@ -75,10 +87,12 @@ export async function openFilerDatabaseIfPresent(databasePath) {
|
|
|
75
87
|
return new DatabaseClient(databasePath, { readOnly: true });
|
|
76
88
|
}
|
|
77
89
|
/**
|
|
78
|
-
* Throws a friendly Error naming the layer when `databasePath` doesn't exist —
|
|
79
|
-
* (mirroring {@link assertBDCDatabaseExists}).
|
|
80
|
-
*
|
|
81
|
-
* `
|
|
90
|
+
* Throws a friendly Error naming the layer when `databasePath` doesn't exist —
|
|
91
|
+
* `mailwoman_filer_lookup`'s guard (mirroring {@link assertBDCDatabaseExists}).
|
|
92
|
+
*
|
|
93
|
+
* `filerLookup` itself has no optional-dep abstain shape
|
|
94
|
+
* (criterion 4 makes it throw rather than answer unstamped), so filer.db is required
|
|
95
|
+
* unconditionally, same as bdc.db is for `mailwoman_bdc_filing_landscape`.
|
|
82
96
|
*/
|
|
83
97
|
export async function assertFilerDatabaseExists(toolName, databasePath) {
|
|
84
98
|
if (!(await pathExists(databasePath))) {
|
package/out/layer-guards.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layer-guards.js","sourceRoot":"","sources":["../lib/layer-guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAGvD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"layer-guards.js","sourceRoot":"","sources":["../lib/layer-guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAGvD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAGzD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC7C,YAAyC;IAEzC,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,YAAY,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IAExE,OAAO,IAAI,cAAc,CAAc,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;AACzE,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC5C,YAAyC;IAEzC,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,YAAY,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IAExE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,oCAAoC,CAAC,CAAA;IACxE,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAc,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IAElF,OAAO;QACN,MAAM,EAAE,IAAI,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;QACnC,QAAQ,EAAE,QAAQ;KAClB,CAAA;AACF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,QAAgB,EAAE,YAA6B;IAC5F,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,0BAA0B,YAAY,GAAG,CAAC,CAAA;IACtE,CAAC;AACF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC/C,YAAyC;IAEzC,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,YAAY,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IAExE,OAAO,IAAI,cAAc,CAAgB,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;AAC3E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,QAAgB,EAAE,YAA6B;IAC9F,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,4BAA4B,YAAY,GAAG,CAAC,CAAA;IACxE,CAAC;AACF,CAAC"}
|
package/out/server.d.ts
CHANGED
|
@@ -4,17 +4,21 @@
|
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*
|
|
6
6
|
* MCP server wiring — thin glue that registers `tools.ts`'s tool table on an `McpServer`. The tool table is the
|
|
7
|
-
* stable, tested
|
|
7
|
+
* stable, tested interface (`tools.test.ts`); this module only adapts it to the SDK's `registerTool` signature and
|
|
8
8
|
* `CallToolResult` envelope. `cli.ts` owns building the real `MCPToolDeps` and connecting a transport.
|
|
9
9
|
*/
|
|
10
10
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
11
11
|
import { type MCPToolDeps } from "#tools";
|
|
12
12
|
/**
|
|
13
|
-
* Build an `McpServer` with every `tools.ts` tool registered.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* Build an `McpServer` with every `tools.ts` tool registered.
|
|
14
|
+
*
|
|
15
|
+
* A handler's returned value is JSON-stringified into a single `text` content block.
|
|
16
|
+
* Every tool here answers with structured data (parse trees, geocode results, search hits),
|
|
17
|
+
* so a plain JSON text block is the simplest faithful rendering.
|
|
18
|
+
*
|
|
19
|
+
* None of the tools need images, resource links, or other MCP content kinds.
|
|
20
|
+
* A thrown error becomes an `isError` tool result instead of a protocol-level failure,
|
|
21
|
+
* so a bad address / missing db surfaces to the agent as a normal (if unsuccessful) tool call.
|
|
18
22
|
*/
|
|
19
23
|
export declare function createMCPServer(deps: MCPToolDeps): McpServer;
|
|
20
24
|
//# sourceMappingURL=server.d.ts.map
|
package/out/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../lib/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../lib/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAGnE,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAA;AAgBzD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,CAsB5D"}
|
package/out/server.js
CHANGED
|
@@ -4,24 +4,35 @@
|
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*
|
|
6
6
|
* MCP server wiring — thin glue that registers `tools.ts`'s tool table on an `McpServer`. The tool table is the
|
|
7
|
-
* stable, tested
|
|
7
|
+
* stable, tested interface (`tools.test.ts`); this module only adapts it to the SDK's `registerTool` signature and
|
|
8
8
|
* `CallToolResult` envelope. `cli.ts` owns building the real `MCPToolDeps` and connecting a transport.
|
|
9
9
|
*/
|
|
10
|
+
import { prettyJSON } from "@mailwoman/core/json";
|
|
11
|
+
import { readPackageJSON } from "@mailwoman/core/module/resolve-from";
|
|
10
12
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
11
13
|
import { buildToolTable } from "#tools";
|
|
12
14
|
/**
|
|
13
|
-
* The advertised server version
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* The advertised server version, read from this package's own manifest at load.
|
|
16
|
+
*
|
|
17
|
+
* A JSON import would make `tsc` copy the file into `out/`, where it becomes the package
|
|
18
|
+
* scope for the compiled tree, so the manifest is read through the module resolver instead.
|
|
17
19
|
*/
|
|
18
|
-
const MCP_SERVER_VERSION =
|
|
20
|
+
const MCP_SERVER_VERSION = await readPackageJSON(import.meta.url, "@mailwoman/mcp").then((manifest) => {
|
|
21
|
+
if (!manifest.version) {
|
|
22
|
+
throw new Error("@mailwoman/mcp: package.json carries no version to advertise");
|
|
23
|
+
}
|
|
24
|
+
return manifest.version;
|
|
25
|
+
});
|
|
19
26
|
/**
|
|
20
|
-
* Build an `McpServer` with every `tools.ts` tool registered.
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
27
|
+
* Build an `McpServer` with every `tools.ts` tool registered.
|
|
28
|
+
*
|
|
29
|
+
* A handler's returned value is JSON-stringified into a single `text` content block.
|
|
30
|
+
* Every tool here answers with structured data (parse trees, geocode results, search hits),
|
|
31
|
+
* so a plain JSON text block is the simplest faithful rendering.
|
|
32
|
+
*
|
|
33
|
+
* None of the tools need images, resource links, or other MCP content kinds.
|
|
34
|
+
* A thrown error becomes an `isError` tool result instead of a protocol-level failure,
|
|
35
|
+
* so a bad address / missing db surfaces to the agent as a normal (if unsuccessful) tool call.
|
|
25
36
|
*/
|
|
26
37
|
export function createMCPServer(deps) {
|
|
27
38
|
const server = new McpServer({ name: "mailwoman", version: MCP_SERVER_VERSION });
|
|
@@ -29,7 +40,7 @@ export function createMCPServer(deps) {
|
|
|
29
40
|
server.registerTool(tool.name, { description: tool.description, inputSchema: tool.inputSchema.shape }, async (args) => {
|
|
30
41
|
try {
|
|
31
42
|
const result = await tool.handler(args);
|
|
32
|
-
return { content: [{ type: "text", text:
|
|
43
|
+
return { content: [{ type: "text", text: prettyJSON(result) }] };
|
|
33
44
|
}
|
|
34
45
|
catch (error) {
|
|
35
46
|
const message = error instanceof Error ? error.message : String(error);
|
package/out/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../lib/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAGnE,OAAO,EAAE,cAAc,EAAoB,MAAM,QAAQ,CAAA;AAEzD;;;;;GAKG;AACH,MAAM,kBAAkB,GAAG,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../lib/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAA;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAGnE,OAAO,EAAE,cAAc,EAAoB,MAAM,QAAQ,CAAA;AAEzD;;;;;GAKG;AACH,MAAM,kBAAkB,GAAG,MAAM,eAAe,CAAC,OAAO,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;IACrG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAA;IAChF,CAAC;IAED,OAAO,QAAQ,CAAC,OAAO,CAAA;AACxB,CAAC,CAAC,CAAA;AAEF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAAC,IAAiB;IAChD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAA;IAEhF,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,CAAC,YAAY,CAClB,IAAI,CAAC,IAAI,EACT,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,EACtE,KAAK,EAAE,IAAI,EAA2B,EAAE;YACvC,IAAI,CAAC;gBACJ,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;gBAEvC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAA;YACjE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBAEtE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;YACrE,CAAC;QACF,CAAC,CACD,CAAA;IACF,CAAC;IAED,OAAO,MAAM,CAAA;AACd,CAAC"}
|
package/out/tools.d.ts
CHANGED
|
@@ -2,42 +2,11 @@
|
|
|
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
|
/**
|
|
40
|
-
*
|
|
8
|
+
* Defines the library operations that MCP tool handlers call.
|
|
9
|
+
* `cli.ts` implements those operations.
|
|
41
10
|
*/
|
|
42
11
|
export interface MCPToolDeps {
|
|
43
12
|
parse: (text: string, opts?: {
|
|
@@ -82,11 +51,10 @@ export interface MCPToolDeps {
|
|
|
82
51
|
}) => Promise<unknown>;
|
|
83
52
|
}
|
|
84
53
|
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* tools stays type-safe internally despite the necessarily-uniform external shape.
|
|
54
|
+
* Describes one MCP tool as registered with the server.
|
|
55
|
+
*
|
|
56
|
+
* Each `handler` re-parses `args` through its own `inputSchema` instead of trusting a cast,
|
|
57
|
+
* because the table's uniform signature erases the per-tool types.
|
|
90
58
|
*/
|
|
91
59
|
export interface MCPToolDef {
|
|
92
60
|
name: string;
|
|
@@ -95,7 +63,8 @@ export interface MCPToolDef {
|
|
|
95
63
|
handler: (args: Record<string, unknown>) => Promise<unknown>;
|
|
96
64
|
}
|
|
97
65
|
/**
|
|
98
|
-
*
|
|
66
|
+
* Builds the MCP tool table over the given dependencies, without opening a transport
|
|
67
|
+
* or performing I/O itself.
|
|
99
68
|
*/
|
|
100
69
|
export declare function buildToolTable(deps: MCPToolDeps): MCPToolDef[];
|
|
101
70
|
//# sourceMappingURL=tools.d.ts.map
|
package/out/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../lib/tools.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../lib/tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;GAGG;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;;;;;GAKG;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;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,EAAE,CAwJ9D"}
|