@mailwoman/mcp 7.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 +28 -0
- package/out/cli.d.ts +23 -0
- package/out/cli.d.ts.map +1 -0
- package/out/cli.js +142 -0
- package/out/cli.js.map +1 -0
- package/out/index.d.ts +11 -0
- package/out/index.d.ts.map +1 -0
- package/out/index.js +11 -0
- package/out/index.js.map +1 -0
- package/out/server.d.ts +20 -0
- package/out/server.d.ts.map +1 -0
- package/out/server.js +42 -0
- package/out/server.js.map +1 -0
- package/out/tools.d.ts +50 -0
- package/out/tools.d.ts.map +1 -0
- package/out/tools.js +115 -0
- package/out/tools.js.map +1 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# @mailwoman/mcp
|
|
2
|
+
|
|
3
|
+
An **MCP server** exposing [Mailwoman](https://mailwoman.sister.software)'s parse/geocode/POI toolset to agents over stdio — no HTTP endpoint, just a subprocess an MCP client launches.
|
|
4
|
+
|
|
5
|
+
## Tools
|
|
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 |
|
|
14
|
+
|
|
15
|
+
## Config
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"mcpServers": {
|
|
20
|
+
"mailwoman": {
|
|
21
|
+
"command": "mailwoman-mcp",
|
|
22
|
+
"args": ["--poi-db", "/path/to/poi.db"]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`--poi-db <path>` wires `mailwoman_poi_search` (and `mailwoman_parse`'s `poi: true` path) to a real database; omit it and those tools degrade gracefully to intent-only.
|
package/out/cli.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @copyright Sister Software
|
|
4
|
+
* @license AGPL-3.0
|
|
5
|
+
* @author Teffen Ellis, et al.
|
|
6
|
+
*
|
|
7
|
+
* `mailwoman-mcp` — boot the MCP server over stdio. Wires the real `MCPToolDeps` (`tools.ts`) from the mailwoman
|
|
8
|
+
* library: `createRuntimePipeline` for parse/POI-intent, `geocode-core`'s `geocodeAddress` for geocode,
|
|
9
|
+
* `mailwoman/poi-overpass`'s `emitOverpassQL` for the export tool, and `@mailwoman/core/layers` for the layer
|
|
10
|
+
* manifest tool.
|
|
11
|
+
*
|
|
12
|
+
* Deps are LAZY: nothing here loads the neural weights or opens a gazetteer db at startup — an MCP client
|
|
13
|
+
* connects, lists tools, and may never call one (or may call `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.
|
|
16
|
+
*
|
|
17
|
+
* ```sh
|
|
18
|
+
* mailwoman-mcp # geocode/poi_search degrade gracefully with no poi.db wired
|
|
19
|
+
* mailwoman-mcp --poi-db poi.db # mailwoman_poi_search additionally executes against poi.db
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=cli.d.ts.map
|
package/out/cli.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;GAmBG"}
|
package/out/cli.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @copyright Sister Software
|
|
4
|
+
* @license AGPL-3.0
|
|
5
|
+
* @author Teffen Ellis, et al.
|
|
6
|
+
*
|
|
7
|
+
* `mailwoman-mcp` — boot the MCP server over stdio. Wires the real `MCPToolDeps` (`tools.ts`) from the mailwoman
|
|
8
|
+
* library: `createRuntimePipeline` for parse/POI-intent, `geocode-core`'s `geocodeAddress` for geocode,
|
|
9
|
+
* `mailwoman/poi-overpass`'s `emitOverpassQL` for the export tool, and `@mailwoman/core/layers` for the layer
|
|
10
|
+
* manifest tool.
|
|
11
|
+
*
|
|
12
|
+
* Deps are LAZY: nothing here loads the neural weights or opens a gazetteer db at startup — an MCP client
|
|
13
|
+
* connects, lists tools, and may never call one (or may call `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.
|
|
16
|
+
*
|
|
17
|
+
* ```sh
|
|
18
|
+
* mailwoman-mcp # geocode/poi_search degrade gracefully with no poi.db wired
|
|
19
|
+
* mailwoman-mcp --poi-db poi.db # mailwoman_poi_search additionally executes against poi.db
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import { existsSync } from "node:fs";
|
|
23
|
+
import { DatabaseSync } from "node:sqlite";
|
|
24
|
+
import { parseArgs } from "node:util";
|
|
25
|
+
import { DatabaseClient } from "@mailwoman/core/kysley/client";
|
|
26
|
+
import { readLayerManifest } from "@mailwoman/core/layers";
|
|
27
|
+
import { NeuralAddressClassifier } from "@mailwoman/neural";
|
|
28
|
+
import { getPOICategory } from "@mailwoman/poi-taxonomy";
|
|
29
|
+
import { createWOFResolver } from "@mailwoman/resolver";
|
|
30
|
+
import { createRuntimePipeline } from "mailwoman";
|
|
31
|
+
import { geocodeAddress, ShardProvider } from "mailwoman/geocode-core";
|
|
32
|
+
import { emitOverpassQL } from "mailwoman/poi-overpass";
|
|
33
|
+
import { createResolverBackend, mailwomanDataRoot, resolveCandidateDBPath, wofShardPaths, } from "mailwoman/resolver-backend";
|
|
34
|
+
import { createMCPServer } from "./server.js";
|
|
35
|
+
const { values } = parseArgs({
|
|
36
|
+
options: {
|
|
37
|
+
"poi-db": { type: "string" },
|
|
38
|
+
},
|
|
39
|
+
allowPositionals: true,
|
|
40
|
+
});
|
|
41
|
+
/**
|
|
42
|
+
* `--poi-db` wires `mailwoman_poi_search` (and, via the same pipeline, `mailwoman_parse`'s `poi: true` path) to a real
|
|
43
|
+
* `poi.db`. Absent → intent-only (parses the query, extracts the subject/anchor, never executes a lookup).
|
|
44
|
+
*/
|
|
45
|
+
const poiDatabasePath = values["poi-db"];
|
|
46
|
+
/**
|
|
47
|
+
* The shared classifier + resolver, built exactly once on the first call that needs them (see the module header).
|
|
48
|
+
* `NeuralAddressClassifier.loadFromWeights` auto-resolves the bundled `en-US` weights; the resolver backend prefers a
|
|
49
|
+
* configured candidate gazetteer (`$MAILWOMAN_CANDIDATE_DB`) and otherwise falls back to the admin-only WOF shards
|
|
50
|
+
* already on the data root — same selection `nominatim`/`photon`'s CLIs make.
|
|
51
|
+
*/
|
|
52
|
+
let corePromise;
|
|
53
|
+
function loadCore() {
|
|
54
|
+
corePromise ??= (async () => {
|
|
55
|
+
const resolverMod = await import("@mailwoman/resolver-wof-sqlite");
|
|
56
|
+
const wofPaths = wofShardPaths().filter(existsSync);
|
|
57
|
+
const candidateDb = resolveCandidateDBPath();
|
|
58
|
+
const backend = createResolverBackend(resolverMod, { wofPaths, candidateDb });
|
|
59
|
+
const resolver = createWOFResolver(backend);
|
|
60
|
+
const classifier = await NeuralAddressClassifier.loadFromWeights({ locale: "en-US" });
|
|
61
|
+
const shards = new ShardProvider(resolverMod, mailwomanDataRoot());
|
|
62
|
+
return { classifier, resolver, shards };
|
|
63
|
+
})();
|
|
64
|
+
return corePromise;
|
|
65
|
+
}
|
|
66
|
+
let plainPipeline;
|
|
67
|
+
/**
|
|
68
|
+
* Keyed by the poi.db path used to build it (`""` = intent-only, no db) — `mailwoman_poi_search` can be called with a
|
|
69
|
+
* `poiDatabasePath` that differs from the server's `--poi-db`, in which case a fresh one-off pipeline is built and
|
|
70
|
+
* cached under that path instead of reusing the default.
|
|
71
|
+
*/
|
|
72
|
+
const poiPipelines = new Map();
|
|
73
|
+
async function getPlainPipeline() {
|
|
74
|
+
if (!plainPipeline) {
|
|
75
|
+
const { classifier, resolver } = await loadCore();
|
|
76
|
+
plainPipeline = createRuntimePipeline({ classifier, resolver });
|
|
77
|
+
}
|
|
78
|
+
return plainPipeline;
|
|
79
|
+
}
|
|
80
|
+
async function getPoiPipeline(dbPath) {
|
|
81
|
+
const key = dbPath ?? "";
|
|
82
|
+
const cached = poiPipelines.get(key);
|
|
83
|
+
if (cached)
|
|
84
|
+
return cached;
|
|
85
|
+
const { classifier, resolver } = await loadCore();
|
|
86
|
+
const pipeline = createRuntimePipeline({
|
|
87
|
+
classifier,
|
|
88
|
+
resolver,
|
|
89
|
+
poiQueryKind: dbPath ? { poiDatabasePath: dbPath } : true,
|
|
90
|
+
});
|
|
91
|
+
poiPipelines.set(key, pipeline);
|
|
92
|
+
return pipeline;
|
|
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
|
+
const { classifier, resolver, shards } = await loadCore();
|
|
101
|
+
return geocodeAddress(text, { classifier, resolver, shards: shards.for });
|
|
102
|
+
},
|
|
103
|
+
async poiSearch(q) {
|
|
104
|
+
const pipeline = await getPoiPipeline(q.poiDatabasePath ?? poiDatabasePath);
|
|
105
|
+
const result = await pipeline(q.query);
|
|
106
|
+
return result.poiIntent ?? { type: "abstain", reason: "not_poi_shaped" };
|
|
107
|
+
},
|
|
108
|
+
async overpassExport(query) {
|
|
109
|
+
// Intent-only is enough here — the export just needs the parsed subject/anchor, never executed results
|
|
110
|
+
// ("we print the query; we never run it", poi-overpass.ts). Reuses the server's wired poi pipeline (a
|
|
111
|
+
// real poi.db doesn't change the emitted OverpassQL) instead of forcing a second one-off pipeline.
|
|
112
|
+
const pipeline = await getPoiPipeline(poiDatabasePath);
|
|
113
|
+
const result = await pipeline(query);
|
|
114
|
+
const outcome = result.poiIntent;
|
|
115
|
+
if (!outcome || outcome.type !== "intent") {
|
|
116
|
+
const reason = outcome?.type === "abstain" ? `: ${outcome.reason}` : "";
|
|
117
|
+
throw new Error(`mailwoman_overpass_export: query is not POI-shaped (${outcome?.type ?? "no poi intent"}${reason})`);
|
|
118
|
+
}
|
|
119
|
+
const { subject } = outcome.intent;
|
|
120
|
+
const osmTag = subject.kind === "category" ? getPOICategory(subject.categoryID)?.osmTag : undefined;
|
|
121
|
+
return emitOverpassQL(outcome.intent, osmTag ? { osmTag } : {});
|
|
122
|
+
},
|
|
123
|
+
async layerManifest(databasePath) {
|
|
124
|
+
using db = new DatabaseClient({
|
|
125
|
+
database: new DatabaseSync(databasePath, { readOnly: true }),
|
|
126
|
+
});
|
|
127
|
+
const manifest = await readLayerManifest(db);
|
|
128
|
+
const coverage = await db
|
|
129
|
+
.selectFrom("layer_coverage")
|
|
130
|
+
.select((eb) => [
|
|
131
|
+
eb.fn.count("h3_cell").as("surveyedCellCount"),
|
|
132
|
+
eb.fn.avg("completeness").as("averageCompleteness"),
|
|
133
|
+
eb.fn.sum("observed_rows").as("totalObservedRows"),
|
|
134
|
+
])
|
|
135
|
+
.executeTakeFirst();
|
|
136
|
+
return { manifest, coverage };
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
const server = createMCPServer(deps);
|
|
140
|
+
const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
|
|
141
|
+
await server.connect(new StdioServerTransport());
|
|
142
|
+
//# sourceMappingURL=cli.js.map
|
package/out/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":"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"}
|
package/out/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `@mailwoman/mcp` public surface — the tool table + server factory, for a caller embedding the MCP server
|
|
7
|
+
* directly (custom transport, alternate deps) instead of running `mailwoman-mcp` as a subprocess.
|
|
8
|
+
*/
|
|
9
|
+
export * from "./server.ts";
|
|
10
|
+
export * from "./tools.ts";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA"}
|
package/out/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `@mailwoman/mcp` public surface — the tool table + server factory, for a caller embedding the MCP server
|
|
7
|
+
* directly (custom transport, alternate deps) instead of running `mailwoman-mcp` as a subprocess.
|
|
8
|
+
*/
|
|
9
|
+
export * from "./server.js";
|
|
10
|
+
export * from "./tools.js";
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
package/out/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA"}
|
package/out/server.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* MCP server wiring — thin glue that registers `tools.ts`'s tool table on an `McpServer`. The tool table is the
|
|
7
|
+
* stable, tested contract (`tools.test.ts`); this module only adapts it to the SDK's `registerTool` signature and
|
|
8
|
+
* `CallToolResult` envelope. `cli.ts` owns building the real `MCPToolDeps` and connecting a transport.
|
|
9
|
+
*/
|
|
10
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
11
|
+
import { type MCPToolDeps } from "./tools.ts";
|
|
12
|
+
/**
|
|
13
|
+
* Build an `McpServer` with every `tools.ts` tool registered. A handler's returned value is JSON-stringified into a
|
|
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 five tools need images, resource
|
|
16
|
+
* links, or other MCP content kinds. A thrown error becomes an `isError` tool result instead of a protocol-level
|
|
17
|
+
* failure, so a bad address / missing db surfaces to the agent as a normal (if unsuccessful) tool call.
|
|
18
|
+
*/
|
|
19
|
+
export declare function createMCPServer(deps: MCPToolDeps): McpServer;
|
|
20
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAGnE,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AAU7D;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,CAsB5D"}
|
package/out/server.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* MCP server wiring — thin glue that registers `tools.ts`'s tool table on an `McpServer`. The tool table is the
|
|
7
|
+
* stable, tested contract (`tools.test.ts`); this module only adapts it to the SDK's `registerTool` signature and
|
|
8
|
+
* `CallToolResult` envelope. `cli.ts` owns building the real `MCPToolDeps` and connecting a transport.
|
|
9
|
+
*/
|
|
10
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
11
|
+
import { buildToolTable } from "./tools.js";
|
|
12
|
+
/**
|
|
13
|
+
* The advertised server version — keep in lockstep with `package.json`'s `version` (not read from it dynamically: a
|
|
14
|
+
* static string avoids `resolveJsonModule`/`composite` friction for one cosmetic field, the same tradeoff
|
|
15
|
+
* `nominatim`/`photon`'s OpenAPI `info.version` DON'T make since theirs is a documented public contract; an MCP client
|
|
16
|
+
* only ever logs this).
|
|
17
|
+
*/
|
|
18
|
+
const MCP_SERVER_VERSION = "7.1.0";
|
|
19
|
+
/**
|
|
20
|
+
* Build an `McpServer` with every `tools.ts` tool registered. A handler's returned value is JSON-stringified into a
|
|
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 five tools need images, resource
|
|
23
|
+
* links, or other MCP content kinds. A thrown error becomes an `isError` tool result instead of a protocol-level
|
|
24
|
+
* failure, so a bad address / missing db surfaces to the agent as a normal (if unsuccessful) tool call.
|
|
25
|
+
*/
|
|
26
|
+
export function createMCPServer(deps) {
|
|
27
|
+
const server = new McpServer({ name: "mailwoman", version: MCP_SERVER_VERSION });
|
|
28
|
+
for (const tool of buildToolTable(deps)) {
|
|
29
|
+
server.registerTool(tool.name, { description: tool.description, inputSchema: tool.inputSchema.shape }, async (args) => {
|
|
30
|
+
try {
|
|
31
|
+
const result = await tool.handler(args);
|
|
32
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
36
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return server;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAGnE,OAAO,EAAE,cAAc,EAAoB,MAAM,YAAY,CAAA;AAE7D;;;;;GAKG;AACH,MAAM,kBAAkB,GAAG,OAAO,CAAA;AAElC;;;;;;GAMG;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,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;YAC9E,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
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
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
|
+
* Five tools, one per capability the exotic-POI arc's other packages expose to a human/CLI caller:
|
|
12
|
+
*
|
|
13
|
+
* - `mailwoman_parse` — the runtime pipeline's parse (optionally POI-aware).
|
|
14
|
+
* - `mailwoman_geocode` — the street-level geocode cascade (`mailwoman/geocode-core`).
|
|
15
|
+
* - `mailwoman_poi_search` — POI-intent extraction + (when a poi.db is wired) execution.
|
|
16
|
+
* - `mailwoman_overpass_export` — OverpassQL EXPORT emitter (`mailwoman/poi-overpass`) — "we print the query;
|
|
17
|
+
* we never run it".
|
|
18
|
+
* - `mailwoman_layer_manifest` — read a spatial-layer database's provenance manifest + coverage summary
|
|
19
|
+
* (`@mailwoman/core/layers`).
|
|
20
|
+
*/
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
/** The library surface every tool handler dispatches to. `cli.ts` builds the real implementation. */
|
|
23
|
+
export interface MCPToolDeps {
|
|
24
|
+
parse: (text: string, opts?: {
|
|
25
|
+
poi?: boolean;
|
|
26
|
+
}) => Promise<unknown>;
|
|
27
|
+
geocode: (text: string) => Promise<unknown>;
|
|
28
|
+
poiSearch: (q: {
|
|
29
|
+
query: string;
|
|
30
|
+
poiDatabasePath?: string;
|
|
31
|
+
}) => Promise<unknown>;
|
|
32
|
+
overpassExport: (query: string) => Promise<string>;
|
|
33
|
+
layerManifest: (databasePath: string) => Promise<unknown>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* One MCP tool. `inputSchema` is a plain Zod object (not `any` — this repo's oxlint config errors on
|
|
37
|
+
* `typescript/no-explicit-any`) — `z.ZodRawShape` is zod's own umbrella type for "any object shape", so this stays
|
|
38
|
+
* generic over the concrete per-tool schemas without reaching for `any`. `handler` re-parses `args` through the same
|
|
39
|
+
* schema (cheap; zod objects are small here) rather than trusting an unchecked cast, so the array of heterogeneous
|
|
40
|
+
* tools stays type-safe internally despite the necessarily-uniform external shape.
|
|
41
|
+
*/
|
|
42
|
+
export interface MCPToolDef {
|
|
43
|
+
name: string;
|
|
44
|
+
description: string;
|
|
45
|
+
inputSchema: z.ZodObject<z.ZodRawShape>;
|
|
46
|
+
handler: (args: Record<string, unknown>) => Promise<unknown>;
|
|
47
|
+
}
|
|
48
|
+
/** Build the tool table for a concrete `MCPToolDeps` implementation. Pure — no transport, no I/O of its own. */
|
|
49
|
+
export declare function buildToolTable(deps: MCPToolDeps): MCPToolDef[];
|
|
50
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,qGAAqG;AACrG,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;CACzD;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;AA2CD,gHAAgH;AAChH,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,EAAE,CAqE9D"}
|
package/out/tools.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
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
|
+
* Five tools, one per capability the exotic-POI arc's other packages expose to a human/CLI caller:
|
|
12
|
+
*
|
|
13
|
+
* - `mailwoman_parse` — the runtime pipeline's parse (optionally POI-aware).
|
|
14
|
+
* - `mailwoman_geocode` — the street-level geocode cascade (`mailwoman/geocode-core`).
|
|
15
|
+
* - `mailwoman_poi_search` — POI-intent extraction + (when a poi.db is wired) execution.
|
|
16
|
+
* - `mailwoman_overpass_export` — OverpassQL EXPORT emitter (`mailwoman/poi-overpass`) — "we print the query;
|
|
17
|
+
* we never run it".
|
|
18
|
+
* - `mailwoman_layer_manifest` — read a spatial-layer database's provenance manifest + coverage summary
|
|
19
|
+
* (`@mailwoman/core/layers`).
|
|
20
|
+
*/
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
const ParseInputSchema = z.object({
|
|
23
|
+
text: z.string().min(1).describe("The free-text location string to parse (a postal address or a POI query)."),
|
|
24
|
+
poi: z
|
|
25
|
+
.boolean()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe("Also run POI-intent detection/extraction (category/brand/name subject + spatial anchor). Default false — plain address parse."),
|
|
28
|
+
});
|
|
29
|
+
const GeocodeInputSchema = z.object({
|
|
30
|
+
text: z.string().min(1).describe("The free-text postal address to geocode."),
|
|
31
|
+
});
|
|
32
|
+
const POISearchInputSchema = z.object({
|
|
33
|
+
query: z
|
|
34
|
+
.string()
|
|
35
|
+
.min(1)
|
|
36
|
+
.describe("A free-text POI query with a spatial anchor, e.g. 'coffee shops near 350 5th Ave, New York' or 'starbucks in Chicago'."),
|
|
37
|
+
poiDatabasePath: z
|
|
38
|
+
.string()
|
|
39
|
+
.optional()
|
|
40
|
+
.describe("Path to a specific poi.db shard to search. Omit to use the server's configured default (if any)."),
|
|
41
|
+
});
|
|
42
|
+
const OverpassExportInputSchema = z.object({
|
|
43
|
+
query: z
|
|
44
|
+
.string()
|
|
45
|
+
.min(1)
|
|
46
|
+
.describe("A free-text POI query (same shape as mailwoman_poi_search) to render as an OverpassQL query."),
|
|
47
|
+
});
|
|
48
|
+
const LayerManifestInputSchema = z.object({
|
|
49
|
+
databasePath: z
|
|
50
|
+
.string()
|
|
51
|
+
.min(1)
|
|
52
|
+
.describe("Path to a mailwoman spatial-layer database (poi.db, an address-points shard, etc.)."),
|
|
53
|
+
});
|
|
54
|
+
/** Build the tool table for a concrete `MCPToolDeps` implementation. Pure — no transport, no I/O of its own. */
|
|
55
|
+
export function buildToolTable(deps) {
|
|
56
|
+
return [
|
|
57
|
+
{
|
|
58
|
+
name: "mailwoman_parse",
|
|
59
|
+
description: "Parse a free-text location string (postal address or POI query) into a structured address tree — house " +
|
|
60
|
+
"number, street, locality, region, postcode, country, and (with `poi: true`) a POI intent. Use this to " +
|
|
61
|
+
"understand a query's structure before geocoding or searching; it does not resolve coordinates.",
|
|
62
|
+
inputSchema: ParseInputSchema,
|
|
63
|
+
handler: async (args) => {
|
|
64
|
+
const { text, poi } = ParseInputSchema.parse(args);
|
|
65
|
+
return deps.parse(text, { poi });
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: "mailwoman_geocode",
|
|
70
|
+
description: "Geocode a free-text postal address to coordinates via the full parse-then-resolve cascade (rooftop > " +
|
|
71
|
+
"interpolated > street > admin resolution tiers). Returns lat/lon, the resolution tier, an uncertainty " +
|
|
72
|
+
"radius in meters, and the resolved admin hierarchy. Use this to convert an address string into a location.",
|
|
73
|
+
inputSchema: GeocodeInputSchema,
|
|
74
|
+
handler: async (args) => {
|
|
75
|
+
const { text } = GeocodeInputSchema.parse(args);
|
|
76
|
+
return deps.geocode(text);
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: "mailwoman_poi_search",
|
|
81
|
+
description: "Search for points of interest — a category ('coffee shop'), a brand ('Starbucks'), or a named place — " +
|
|
82
|
+
"near the spatial anchor extracted from the query text (e.g. 'pharmacies near 10 Downing St, London'). " +
|
|
83
|
+
"Returns the parsed intent and, when a POI database is available, ranked nearby results.",
|
|
84
|
+
inputSchema: POISearchInputSchema,
|
|
85
|
+
handler: async (args) => {
|
|
86
|
+
const { query, poiDatabasePath } = POISearchInputSchema.parse(args);
|
|
87
|
+
return deps.poiSearch({ query, poiDatabasePath });
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: "mailwoman_overpass_export",
|
|
92
|
+
description: "Turn a POI-shaped query into an OverpassQL query string for Overpass Turbo — this NEVER executes the " +
|
|
93
|
+
"query itself, it only prints it. Use this when the operator wants to explore or run the search " +
|
|
94
|
+
"themselves against live OpenStreetMap data.",
|
|
95
|
+
inputSchema: OverpassExportInputSchema,
|
|
96
|
+
handler: async (args) => {
|
|
97
|
+
const { query } = OverpassExportInputSchema.parse(args);
|
|
98
|
+
return deps.overpassExport(query);
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: "mailwoman_layer_manifest",
|
|
103
|
+
description: "Inspect a mailwoman spatial-layer database (poi.db, an address-points shard, etc.): read its provenance " +
|
|
104
|
+
"and licensing manifest (source, vintage, build command, license) plus a coverage summary (how many H3 " +
|
|
105
|
+
"cells were surveyed, average completeness, total observed rows). Use this to check what a layer " +
|
|
106
|
+
"actually covers before relying on it.",
|
|
107
|
+
inputSchema: LayerManifestInputSchema,
|
|
108
|
+
handler: async (args) => {
|
|
109
|
+
const { databasePath } = LayerManifestInputSchema.parse(args);
|
|
110
|
+
return deps.layerManifest(databasePath);
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
];
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=tools.js.map
|
package/out/tools.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mailwoman/mcp",
|
|
3
|
+
"version": "7.1.0",
|
|
4
|
+
"description": "MCP server — mailwoman's spatial toolset for agents (parse, geocode, poi_search, overpass_export, layer_manifest).",
|
|
5
|
+
"license": "AGPL-3.0-only OR LicenseRef-Commercial",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/sister-software/mailwoman.git",
|
|
9
|
+
"directory": "mcp"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"mailwoman-mcp": "./out/cli.js"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"out/**/*.js",
|
|
16
|
+
"out/**/*.js.map",
|
|
17
|
+
"out/**/*.d.ts",
|
|
18
|
+
"out/**/*.d.ts.map",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"type": "module",
|
|
22
|
+
"exports": {
|
|
23
|
+
"./package.json": "./package.json",
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./out/index.d.ts",
|
|
26
|
+
"default": "./out/index.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"exports": {
|
|
31
|
+
"./package.json": "./package.json",
|
|
32
|
+
".": {
|
|
33
|
+
"types": "./out/index.d.ts",
|
|
34
|
+
"default": "./out/index.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@mailwoman/core": "7.1.0",
|
|
41
|
+
"@mailwoman/neural": "7.1.0",
|
|
42
|
+
"@mailwoman/poi-taxonomy": "7.1.0",
|
|
43
|
+
"@mailwoman/resolver": "7.1.0",
|
|
44
|
+
"@mailwoman/resolver-wof-sqlite": "7.1.0",
|
|
45
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
46
|
+
"mailwoman": "7.1.0",
|
|
47
|
+
"zod": "^4.4.3"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"@mailwoman/resolver-wof-sqlite": "7.1.0"
|
|
51
|
+
},
|
|
52
|
+
"peerDependenciesMeta": {
|
|
53
|
+
"@mailwoman/resolver-wof-sqlite": {
|
|
54
|
+
"optional": true
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|