@haivx/tripmind-maps-mcp 0.3.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.
Files changed (46) hide show
  1. package/README.md +226 -0
  2. package/build/index.d.ts +3 -0
  3. package/build/index.d.ts.map +1 -0
  4. package/build/index.js +80 -0
  5. package/build/index.js.map +1 -0
  6. package/build/tools/directions.d.ts +44 -0
  7. package/build/tools/directions.d.ts.map +1 -0
  8. package/build/tools/directions.js +54 -0
  9. package/build/tools/directions.js.map +1 -0
  10. package/build/tools/distance-matrix.d.ts +41 -0
  11. package/build/tools/distance-matrix.d.ts.map +1 -0
  12. package/build/tools/distance-matrix.js +59 -0
  13. package/build/tools/distance-matrix.js.map +1 -0
  14. package/build/tools/geocode.d.ts +51 -0
  15. package/build/tools/geocode.d.ts.map +1 -0
  16. package/build/tools/geocode.js +90 -0
  17. package/build/tools/geocode.js.map +1 -0
  18. package/build/tools/place-details.d.ts +41 -0
  19. package/build/tools/place-details.d.ts.map +1 -0
  20. package/build/tools/place-details.js +57 -0
  21. package/build/tools/place-details.js.map +1 -0
  22. package/build/tools/search-places.d.ts +50 -0
  23. package/build/tools/search-places.d.ts.map +1 -0
  24. package/build/tools/search-places.js +57 -0
  25. package/build/tools/search-places.js.map +1 -0
  26. package/build/tools/timezone.d.ts +41 -0
  27. package/build/tools/timezone.d.ts.map +1 -0
  28. package/build/tools/timezone.js +47 -0
  29. package/build/tools/timezone.js.map +1 -0
  30. package/build/types.d.ts +107 -0
  31. package/build/types.d.ts.map +1 -0
  32. package/build/types.js +2 -0
  33. package/build/types.js.map +1 -0
  34. package/build/utils/cache.d.ts +21 -0
  35. package/build/utils/cache.d.ts.map +1 -0
  36. package/build/utils/cache.js +41 -0
  37. package/build/utils/cache.js.map +1 -0
  38. package/build/utils/google-client.d.ts +83 -0
  39. package/build/utils/google-client.d.ts.map +1 -0
  40. package/build/utils/google-client.js +330 -0
  41. package/build/utils/google-client.js.map +1 -0
  42. package/build/utils/rate-limiter.d.ts +25 -0
  43. package/build/utils/rate-limiter.d.ts.map +1 -0
  44. package/build/utils/rate-limiter.js +41 -0
  45. package/build/utils/rate-limiter.js.map +1 -0
  46. package/package.json +57 -0
package/README.md ADDED
@@ -0,0 +1,226 @@
1
+ # tripmind-maps-mcp
2
+
3
+ A travel-focused MCP (Model Context Protocol) server wrapping Google Maps API. Built for [TripMind](https://github.com/haivx/tripmind) — an AI-powered travel planning app.
4
+
5
+ This server provides 6 curated location tools that Claude can call for geocoding, place search, directions, and more. It works with Claude Code, Claude Desktop, and any MCP-compatible client.
6
+
7
+ ## Why Custom Instead of Existing Packages?
8
+
9
+ There are generic Google Maps MCP servers available (like `@cablate/mcp-google-map` with 17 tools). This custom server is purpose-built for travel planning:
10
+
11
+ - **Lean tool set** — 6 tools instead of 17, saving LLM context tokens
12
+ - **Built-in caching** — geocode results cached 30 days, reducing API costs
13
+ - **Rate limiting** — per-key throttling prevents credit burn
14
+ - **Travel-optimized** — tool descriptions tuned for trip planning queries
15
+ - **Cost-aware** — field masks on all Places API calls, Routes API over legacy
16
+
17
+ ## Tools
18
+
19
+ | Tool | Description | Google API | Cache TTL |
20
+ |------|-------------|------------|-----------|
21
+ | `maps_geocode` | Address ↔ coordinates conversion | Geocoding | 30 days |
22
+ | `maps_search_places` | Text search & nearby discovery | Places (New) | 24 hours |
23
+ | `maps_place_details` | Rich info: hours, reviews, photos | Place Details | 7 days |
24
+ | `maps_directions` | Route with time, distance, steps | Routes API | 1 hour |
25
+ | `maps_distance_matrix` | Multi-point distance/time grid | Distance Matrix | 1 hour |
26
+ | `maps_timezone` | Timezone by coordinates | Timezone | 90 days |
27
+
28
+ ## Quick Start
29
+
30
+ ### Prerequisites
31
+
32
+ - Node.js 20+
33
+ - Google Maps API key with these APIs enabled:
34
+ - Geocoding API
35
+ - Places API (New)
36
+ - Routes API
37
+ - Distance Matrix API
38
+ - Timezone API
39
+
40
+ ### Installation
41
+
42
+ **Via npm (recommended):**
43
+
44
+ ```bash
45
+ npm install -g @haivx/tripmind-maps-mcp
46
+ # or use directly with npx (no install needed)
47
+ ```
48
+
49
+ **From source:**
50
+
51
+ ```bash
52
+ git clone https://github.com/haivx/tripmind-maps-mcp.git
53
+ cd tripmind-maps-mcp
54
+ npm install
55
+ cp .env.example .env
56
+ # Edit .env and add your GOOGLE_MAPS_API_KEY
57
+ npm run build
58
+ ```
59
+
60
+ ### Use with Claude Code
61
+
62
+ ```bash
63
+ claude mcp add tripmind-maps -- npx -y @haivx/tripmind-maps-mcp
64
+ ```
65
+
66
+ Or manually add to your project's `.mcp.json`:
67
+
68
+ ```json
69
+ {
70
+ "mcpServers": {
71
+ "tripmind-maps": {
72
+ "command": "npx",
73
+ "args": ["-y", "@haivx/tripmind-maps-mcp"],
74
+ "env": {
75
+ "GOOGLE_MAPS_API_KEY": "${env:GOOGLE_MAPS_API_KEY}"
76
+ }
77
+ }
78
+ }
79
+ }
80
+ ```
81
+
82
+ ### Use with Claude Desktop
83
+
84
+ Add to `claude_desktop_config.json`:
85
+
86
+ ```json
87
+ {
88
+ "mcpServers": {
89
+ "tripmind-maps": {
90
+ "command": "node",
91
+ "args": ["/absolute/path/to/tripmind-maps-mcp/build/index.js"],
92
+ "env": {
93
+ "GOOGLE_MAPS_API_KEY": "your-api-key-here"
94
+ }
95
+ }
96
+ }
97
+ }
98
+ ```
99
+
100
+ ### HTTP Mode (Remote Deployment)
101
+
102
+ ```bash
103
+ npm run start:http
104
+ # Server runs on http://localhost:3000/mcp
105
+ ```
106
+
107
+ Connect from any MCP client:
108
+
109
+ ```json
110
+ {
111
+ "tripmind-maps": {
112
+ "transport": "streamableHttp",
113
+ "url": "http://localhost:3000/mcp"
114
+ }
115
+ }
116
+ ```
117
+
118
+ ## Development
119
+
120
+ ```bash
121
+ npm run dev # Watch mode
122
+ npm run test # Run tests
123
+ npm run typecheck # Type check
124
+ npm run inspect # MCP Inspector UI
125
+ npm run lint # ESLint
126
+ ```
127
+
128
+ ### Adding a New Tool
129
+
130
+ Use the Claude Code command: `/new-tool`
131
+
132
+ Or follow these steps:
133
+
134
+ 1. Create `src/tools/<name>.ts` with Zod schema + handler
135
+ 2. Register in `src/index.ts` via `server.registerTool()`
136
+ 3. Add tests to `tests/tools.test.ts`
137
+ 4. Update this README's tool table
138
+ 5. Run `npm run typecheck && npm run test`
139
+
140
+ ### Testing with MCP Inspector
141
+
142
+ ```bash
143
+ npx @modelcontextprotocol/inspector node build/index.js
144
+ ```
145
+
146
+ This opens a web UI where you can call each tool with test inputs and see responses.
147
+
148
+ ## Cost Estimation
149
+
150
+ For personal/MVP usage (< 1,000 calls/month per API), all usage falls within Google's free tiers:
151
+
152
+ | API | Free Tier | Price After |
153
+ |-----|-----------|-------------|
154
+ | Geocoding | 10,000/month | $5/1,000 |
155
+ | Places Text Search | 10,000/month | $32/1,000 |
156
+ | Place Details (Basic) | 10,000/month | $0 (basic fields) |
157
+ | Routes (Basic) | 10,000/month | $5/1,000 |
158
+ | Distance Matrix | 10,000/month | $5/1,000 elements |
159
+ | Timezone | 10,000/month | $5/1,000 |
160
+
161
+ **Estimated monthly cost for TripMind MVP: $0**
162
+
163
+ ## Project Structure
164
+
165
+ ```
166
+ tripmind-maps-mcp/
167
+ ├── .claude/ # Claude Code workflow
168
+ │ ├── settings.json # Hooks, permissions
169
+ │ ├── commands/ # Slash commands (/new-tool, /review, /ship, /debug)
170
+ │ ├── agents/ # Subagent definitions (code-reviewer)
171
+ │ ├── skills/ # Domain knowledge (mcp-tool-dev)
172
+ │ ├── rules/ # Behavior rules (behaviors, content-safety)
173
+ │ └── memory/ # Session continuity (today.md)
174
+ ├── docs/
175
+ │ └── IMPLEMENTATION_PLAN.md
176
+ ├── src/
177
+ │ ├── index.ts
178
+ │ ├── tools/
179
+ │ ├── utils/
180
+ │ └── types.ts
181
+ ├── tests/
182
+ ├── CLAUDE.md # Project context for Claude Code
183
+ ├── README.md
184
+ ├── package.json
185
+ ├── tsconfig.json
186
+ ├── .env.example
187
+ └── .gitignore
188
+ ```
189
+
190
+ ## Claude Code Workflow
191
+
192
+ This project includes a complete Claude Code workflow:
193
+
194
+ | Component | Purpose |
195
+ |-----------|---------|
196
+ | `CLAUDE.md` | Project context, tech stack, commands, standards |
197
+ | `.claude/rules/behaviors.md` | Development behavior rules (plan first, verify, cost awareness) |
198
+ | `.claude/rules/content-safety.md` | Travel data accuracy rules (never fabricate locations) |
199
+ | `.claude/commands/new-tool.md` | Step-by-step guide for adding MCP tools |
200
+ | `.claude/commands/review.md` | Code review checklist with severity levels |
201
+ | `.claude/commands/ship.md` | Pre-publish verification checklist |
202
+ | `.claude/commands/debug.md` | 5-phase systematic debugging guide |
203
+ | `.claude/agents/code-reviewer.md` | Sonnet-powered code review subagent |
204
+ | `.claude/skills/mcp-tool-dev/` | MCP SDK patterns and best practices |
205
+ | `.claude/hooks` | Auto typecheck on .ts writes, block .env writes, session reminders |
206
+
207
+ ## Environment Variables
208
+
209
+ | Variable | Required | Description |
210
+ |----------|----------|-------------|
211
+ | `GOOGLE_MAPS_API_KEY` | Yes | Google Maps Platform API key |
212
+ | `PORT` | No | HTTP server port (default: 3000) |
213
+ | `CACHE_ENABLED` | No | Enable/disable caching (default: true) |
214
+ | `RATE_LIMIT_RPM` | No | Requests per minute limit (default: 100) |
215
+ | `LOG_LEVEL` | No | debug, info, warn, error (default: info) |
216
+
217
+ ## Related
218
+
219
+ - [TripMind](https://github.com/haivx/tripmind) — The parent AI travel planning app
220
+ - [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) — Official SDK
221
+ - [MCP Inspector](https://github.com/modelcontextprotocol/inspector) — Testing tool
222
+ - [Google Maps Services JS](https://github.com/googlemaps/google-maps-services-js) — Google Maps client
223
+
224
+ ## License
225
+
226
+ MIT
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import "dotenv/config";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC"}
package/build/index.js ADDED
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env node
2
+ import "dotenv/config";
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
6
+ import express from "express";
7
+ import { toolName as geocodeName, toolConfig as geocodeConfig, handler as geocodeHandler } from "./tools/geocode.js";
8
+ import { toolName as searchPlacesName, toolConfig as searchPlacesConfig, handler as searchPlacesHandler } from "./tools/search-places.js";
9
+ import { toolName as placeDetailsName, toolConfig as placeDetailsConfig, handler as placeDetailsHandler } from "./tools/place-details.js";
10
+ import { toolName as directionsName, toolConfig as directionsConfig, handler as directionsHandler } from "./tools/directions.js";
11
+ import { toolName as distanceMatrixName, toolConfig as distanceMatrixConfig, handler as distanceMatrixHandler } from "./tools/distance-matrix.js";
12
+ import { toolName as timezoneName, toolConfig as timezoneConfig, handler as timezoneHandler } from "./tools/timezone.js";
13
+ import { assertRateLimit } from "./utils/rate-limiter.js";
14
+ /** Create and register all tools on a new McpServer instance. */
15
+ function createMcpServer() {
16
+ const server = new McpServer({ name: "tripmind-maps", version: "0.1.0" });
17
+ server.registerTool(geocodeName, geocodeConfig, geocodeHandler);
18
+ server.registerTool(searchPlacesName, searchPlacesConfig, searchPlacesHandler);
19
+ server.registerTool(placeDetailsName, placeDetailsConfig, placeDetailsHandler);
20
+ server.registerTool(directionsName, directionsConfig, directionsHandler);
21
+ server.registerTool(distanceMatrixName, distanceMatrixConfig, distanceMatrixHandler);
22
+ server.registerTool(timezoneName, timezoneConfig, timezoneHandler);
23
+ return server;
24
+ }
25
+ const useHttp = process.argv.includes("--http") || process.env["HTTP_MODE"] === "true";
26
+ if (useHttp) {
27
+ // ---------------------------------------------------------------------------
28
+ // HTTP transport (production / remote clients)
29
+ // ---------------------------------------------------------------------------
30
+ const port = parseInt(process.env["PORT"] ?? "3000", 10);
31
+ const app = express();
32
+ app.use(express.json());
33
+ // CORS — allow all origins for local development
34
+ app.use((_req, res, next) => {
35
+ res.setHeader("Access-Control-Allow-Origin", "*");
36
+ res.setHeader("Access-Control-Allow-Methods", "POST, OPTIONS");
37
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, mcp-session-id");
38
+ next();
39
+ });
40
+ app.options("/mcp", (_req, res) => {
41
+ res.sendStatus(204);
42
+ });
43
+ // Rate limit per IP before reaching MCP handler
44
+ app.use("/mcp", (req, res, next) => {
45
+ const ip = req.ip ?? req.socket.remoteAddress ?? "unknown";
46
+ try {
47
+ assertRateLimit(ip);
48
+ next();
49
+ }
50
+ catch (err) {
51
+ const message = err instanceof Error ? err.message : "Rate limit exceeded";
52
+ res.status(429).json({ error: message });
53
+ }
54
+ });
55
+ // Stateless: create a fresh server + transport per request
56
+ app.post("/mcp", async (req, res) => {
57
+ const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
58
+ const server = createMcpServer();
59
+ await server.connect(transport);
60
+ try {
61
+ await transport.handleRequest(req, res, req.body);
62
+ }
63
+ finally {
64
+ await server.close();
65
+ }
66
+ });
67
+ app.listen(port, () => {
68
+ console.error(`[tripmind-maps] HTTP server on port ${port}`);
69
+ });
70
+ }
71
+ else {
72
+ // ---------------------------------------------------------------------------
73
+ // Stdio transport (Claude Code / Desktop — default)
74
+ // ---------------------------------------------------------------------------
75
+ const server = createMcpServer();
76
+ const transport = new StdioServerTransport();
77
+ await server.connect(transport);
78
+ console.error("[tripmind-maps] MCP server started");
79
+ }
80
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,QAAQ,IAAI,WAAW,EAAE,UAAU,IAAI,aAAa,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACrH,OAAO,EAAE,QAAQ,IAAI,gBAAgB,EAAE,UAAU,IAAI,kBAAkB,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC1I,OAAO,EAAE,QAAQ,IAAI,gBAAgB,EAAE,UAAU,IAAI,kBAAkB,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC1I,OAAO,EAAE,QAAQ,IAAI,cAAc,EAAE,UAAU,IAAI,gBAAgB,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACjI,OAAO,EAAE,QAAQ,IAAI,kBAAkB,EAAE,UAAU,IAAI,oBAAoB,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAClJ,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,UAAU,IAAI,cAAc,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACzH,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,iEAAiE;AACjE,SAAS,eAAe;IACtB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAC1E,MAAM,CAAC,YAAY,CAAC,WAAW,EAAE,aAAa,EAAE,cAAc,CAAC,CAAC;IAChE,MAAM,CAAC,YAAY,CAAC,gBAAgB,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;IAC/E,MAAM,CAAC,YAAY,CAAC,gBAAgB,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;IAC/E,MAAM,CAAC,YAAY,CAAC,cAAc,EAAE,gBAAgB,EAAE,iBAAiB,CAAC,CAAC;IACzE,MAAM,CAAC,YAAY,CAAC,kBAAkB,EAAE,oBAAoB,EAAE,qBAAqB,CAAC,CAAC;IACrF,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;IACnE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,MAAM,CAAC;AAEvF,IAAI,OAAO,EAAE,CAAC;IACZ,8EAA8E;IAC9E,+CAA+C;IAC/C,8EAA8E;IAC9E,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;IACzD,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IAEtB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAExB,iDAAiD;IACjD,GAAG,CAAC,GAAG,CAAC,CAAC,IAAa,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QAC3D,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;QAClD,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,eAAe,CAAC,CAAC;QAC/D,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,8BAA8B,CAAC,CAAC;QAC9E,IAAI,EAAE,CAAC;IACT,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;QACnD,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,gDAAgD;IAChD,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QAClE,MAAM,EAAE,GAAG,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,SAAS,CAAC;QAC3D,IAAI,CAAC;YACH,eAAe,CAAC,EAAE,CAAC,CAAC;YACpB,IAAI,EAAE,CAAC;QACT,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;YAC3E,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,2DAA2D;IAC3D,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;QACrD,MAAM,SAAS,GAAG,IAAI,6BAA6B,CAAC,EAAE,kBAAkB,EAAE,SAAS,EAAE,CAAC,CAAC;QACvF,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;QACjC,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACpD,CAAC;gBAAS,CAAC;YACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QACpB,OAAO,CAAC,KAAK,CAAC,uCAAuC,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC;KAAM,CAAC;IACN,8EAA8E;IAC9E,oDAAoD;IACpD,8EAA8E;IAC9E,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { z } from "zod";
2
+ export declare const toolName = "maps_directions";
3
+ export declare const inputSchema: {
4
+ origin: z.ZodString;
5
+ destination: z.ZodString;
6
+ mode: z.ZodOptional<z.ZodEnum<["DRIVE", "WALK", "TRANSIT", "BICYCLE"]>>;
7
+ departure_time: z.ZodOptional<z.ZodString>;
8
+ };
9
+ export declare const toolConfig: {
10
+ title: string;
11
+ description: string;
12
+ inputSchema: {
13
+ origin: z.ZodString;
14
+ destination: z.ZodString;
15
+ mode: z.ZodOptional<z.ZodEnum<["DRIVE", "WALK", "TRANSIT", "BICYCLE"]>>;
16
+ departure_time: z.ZodOptional<z.ZodString>;
17
+ };
18
+ annotations: {
19
+ readOnlyHint: boolean;
20
+ destructiveHint: boolean;
21
+ openWorldHint: boolean;
22
+ };
23
+ };
24
+ type DirectionsArgs = {
25
+ origin: string;
26
+ destination: string;
27
+ mode?: "DRIVE" | "WALK" | "TRANSIT" | "BICYCLE";
28
+ departure_time?: string;
29
+ };
30
+ export declare function handler(args: DirectionsArgs): Promise<{
31
+ content: {
32
+ type: "text";
33
+ text: string;
34
+ }[];
35
+ isError?: undefined;
36
+ } | {
37
+ content: {
38
+ type: "text";
39
+ text: string;
40
+ }[];
41
+ isError: boolean;
42
+ }>;
43
+ export {};
44
+ //# sourceMappingURL=directions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directions.d.ts","sourceRoot":"","sources":["../../src/tools/directions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,eAAO,MAAM,QAAQ,oBAAoB,CAAC;AAE1C,eAAO,MAAM,WAAW;;;;;CAWvB,CAAC;AAEF,eAAO,MAAM,UAAU;;;;;;;;;;;;;;CAUtB,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IAChD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,wBAAsB,OAAO,CAAC,IAAI,EAAE,cAAc;;;;;;;;;;;;GA2BjD"}
@@ -0,0 +1,54 @@
1
+ import { z } from "zod";
2
+ import { cache } from "../utils/cache.js";
3
+ import { computeRoute } from "../utils/google-client.js";
4
+ const TTL_MS = 60 * 60 * 1000; // 1 hour
5
+ export const toolName = "maps_directions";
6
+ export const inputSchema = {
7
+ origin: z.string().describe("Starting point — address, landmark name, or 'place_id:ChIJ...'"),
8
+ destination: z.string().describe("End point — address, landmark name, or 'place_id:ChIJ...'"),
9
+ mode: z
10
+ .enum(["DRIVE", "WALK", "TRANSIT", "BICYCLE"])
11
+ .optional()
12
+ .describe("Travel mode. Default: TRANSIT (best for city travel)"),
13
+ departure_time: z
14
+ .string()
15
+ .optional()
16
+ .describe("ISO 8601 datetime for traffic-aware routing, e.g. '2026-04-10T09:00:00+09:00'"),
17
+ };
18
+ export const toolConfig = {
19
+ title: "Get Directions",
20
+ description: "Calculate a route between two places with travel time, distance, and step-by-step directions. Supports driving, walking, transit, and cycling. Use this when the user asks 'how to get from A to B' or when planning daily itinerary routes.",
21
+ inputSchema,
22
+ annotations: {
23
+ readOnlyHint: true,
24
+ destructiveHint: false,
25
+ openWorldHint: true,
26
+ },
27
+ };
28
+ export async function handler(args) {
29
+ try {
30
+ const mode = args.mode ?? "TRANSIT";
31
+ const cacheKey = `directions:${args.origin.toLowerCase().trim()}:${args.destination.toLowerCase().trim()}:${mode}`;
32
+ const cached = cache.get(cacheKey);
33
+ if (cached) {
34
+ return { content: [{ type: "text", text: JSON.stringify(cached) }] };
35
+ }
36
+ const result = await computeRoute({
37
+ origin: args.origin,
38
+ destination: args.destination,
39
+ mode,
40
+ departure_time: args.departure_time,
41
+ });
42
+ cache.set(cacheKey, result, TTL_MS);
43
+ return { content: [{ type: "text", text: JSON.stringify(result) }] };
44
+ }
45
+ catch (err) {
46
+ const message = err instanceof Error ? err.message : String(err);
47
+ console.error(`[maps_directions] error: ${message}`);
48
+ return {
49
+ content: [{ type: "text", text: JSON.stringify({ error: message }) }],
50
+ isError: true,
51
+ };
52
+ }
53
+ }
54
+ //# sourceMappingURL=directions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directions.js","sourceRoot":"","sources":["../../src/tools/directions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,SAAS;AAExC,MAAM,CAAC,MAAM,QAAQ,GAAG,iBAAiB,CAAC;AAE1C,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gEAAgE,CAAC;IAC7F,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2DAA2D,CAAC;IAC7F,IAAI,EAAE,CAAC;SACJ,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;SAC7C,QAAQ,EAAE;SACV,QAAQ,CAAC,sDAAsD,CAAC;IACnE,cAAc,EAAE,CAAC;SACd,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,+EAA+E,CAAC;CAC7F,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,KAAK,EAAE,gBAAgB;IACvB,WAAW,EACT,8OAA8O;IAChP,WAAW;IACX,WAAW,EAAE;QACX,YAAY,EAAE,IAAI;QAClB,eAAe,EAAE,KAAK;QACtB,aAAa,EAAE,IAAI;KACpB;CACF,CAAC;AASF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAoB;IAChD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC;QACpC,MAAM,QAAQ,GAAG,cAAc,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;QAEnH,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAmB,QAAQ,CAAC,CAAC;QACrD,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;QAChF,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;YAChC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,IAAI;YACJ,cAAc,EAAE,IAAI,CAAC,cAAc;SACpC,CAAC,CAAC;QAEH,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACpC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;IAChF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,CAAC,KAAK,CAAC,4BAA4B,OAAO,EAAE,CAAC,CAAC;QACrD,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;YAC9E,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { z } from "zod";
2
+ export declare const toolName = "maps_distance_matrix";
3
+ export declare const inputSchema: {
4
+ origins: z.ZodArray<z.ZodString, "many">;
5
+ destinations: z.ZodArray<z.ZodString, "many">;
6
+ mode: z.ZodOptional<z.ZodEnum<["DRIVE", "WALK", "TRANSIT", "BICYCLE"]>>;
7
+ };
8
+ export declare const toolConfig: {
9
+ title: string;
10
+ description: string;
11
+ inputSchema: {
12
+ origins: z.ZodArray<z.ZodString, "many">;
13
+ destinations: z.ZodArray<z.ZodString, "many">;
14
+ mode: z.ZodOptional<z.ZodEnum<["DRIVE", "WALK", "TRANSIT", "BICYCLE"]>>;
15
+ };
16
+ annotations: {
17
+ readOnlyHint: boolean;
18
+ destructiveHint: boolean;
19
+ openWorldHint: boolean;
20
+ };
21
+ };
22
+ type DistanceMatrixArgs = {
23
+ origins: string[];
24
+ destinations: string[];
25
+ mode?: "DRIVE" | "WALK" | "TRANSIT" | "BICYCLE";
26
+ };
27
+ export declare function handler(args: DistanceMatrixArgs): Promise<{
28
+ content: {
29
+ type: "text";
30
+ text: string;
31
+ }[];
32
+ isError?: undefined;
33
+ } | {
34
+ content: {
35
+ type: "text";
36
+ text: string;
37
+ }[];
38
+ isError: boolean;
39
+ }>;
40
+ export {};
41
+ //# sourceMappingURL=distance-matrix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distance-matrix.d.ts","sourceRoot":"","sources":["../../src/tools/distance-matrix.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,eAAO,MAAM,QAAQ,yBAAyB,CAAC;AAE/C,eAAO,MAAM,WAAW;;;;CAevB,CAAC;AAEF,eAAO,MAAM,UAAU;;;;;;;;;;;;;CAUtB,CAAC;AAEF,KAAK,kBAAkB,GAAG;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;CACjD,CAAC;AAEF,wBAAsB,OAAO,CAAC,IAAI,EAAE,kBAAkB;;;;;;;;;;;;GA4BrD"}
@@ -0,0 +1,59 @@
1
+ import { z } from "zod";
2
+ import { cache } from "../utils/cache.js";
3
+ import { distanceMatrix as googleDistanceMatrix } from "../utils/google-client.js";
4
+ const TTL_MS = 60 * 60 * 1000; // 1 hour
5
+ export const toolName = "maps_distance_matrix";
6
+ export const inputSchema = {
7
+ origins: z
8
+ .array(z.string())
9
+ .min(1)
10
+ .max(10)
11
+ .describe("List of starting points (addresses or place_ids)"),
12
+ destinations: z
13
+ .array(z.string())
14
+ .min(1)
15
+ .max(10)
16
+ .describe("List of end points (addresses or place_ids)"),
17
+ mode: z
18
+ .enum(["DRIVE", "WALK", "TRANSIT", "BICYCLE"])
19
+ .optional()
20
+ .describe("Travel mode. Default: TRANSIT"),
21
+ };
22
+ export const toolConfig = {
23
+ title: "Distance Matrix",
24
+ description: "Calculate travel distances and times between multiple origins and destinations at once. Returns a matrix of all pairs. Use this to optimize itinerary order — find which places are closest to each other for efficient day planning.",
25
+ inputSchema,
26
+ annotations: {
27
+ readOnlyHint: true,
28
+ destructiveHint: false,
29
+ openWorldHint: true,
30
+ },
31
+ };
32
+ export async function handler(args) {
33
+ try {
34
+ const mode = args.mode ?? "TRANSIT";
35
+ const originsKey = args.origins.map((o) => o.toLowerCase().trim()).join("|");
36
+ const destsKey = args.destinations.map((d) => d.toLowerCase().trim()).join("|");
37
+ const cacheKey = `distance-matrix:${originsKey}:${destsKey}:${mode}`;
38
+ const cached = cache.get(cacheKey);
39
+ if (cached) {
40
+ return { content: [{ type: "text", text: JSON.stringify(cached) }] };
41
+ }
42
+ const result = await googleDistanceMatrix({
43
+ origins: args.origins,
44
+ destinations: args.destinations,
45
+ mode,
46
+ });
47
+ cache.set(cacheKey, result, TTL_MS);
48
+ return { content: [{ type: "text", text: JSON.stringify(result) }] };
49
+ }
50
+ catch (err) {
51
+ const message = err instanceof Error ? err.message : String(err);
52
+ console.error(`[maps_distance_matrix] error: ${message}`);
53
+ return {
54
+ content: [{ type: "text", text: JSON.stringify({ error: message }) }],
55
+ isError: true,
56
+ };
57
+ }
58
+ }
59
+ //# sourceMappingURL=distance-matrix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distance-matrix.js","sourceRoot":"","sources":["../../src/tools/distance-matrix.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import { z } from "zod";
2
+ export declare const toolName = "maps_geocode";
3
+ /** Input schema shape for the maps_geocode tool. */
4
+ export declare const inputSchema: {
5
+ address: z.ZodOptional<z.ZodString>;
6
+ latitude: z.ZodOptional<z.ZodNumber>;
7
+ longitude: z.ZodOptional<z.ZodNumber>;
8
+ language: z.ZodOptional<z.ZodString>;
9
+ };
10
+ /** Tool registration config for McpServer.registerTool(). */
11
+ export declare const toolConfig: {
12
+ title: string;
13
+ description: string;
14
+ inputSchema: {
15
+ address: z.ZodOptional<z.ZodString>;
16
+ latitude: z.ZodOptional<z.ZodNumber>;
17
+ longitude: z.ZodOptional<z.ZodNumber>;
18
+ language: z.ZodOptional<z.ZodString>;
19
+ };
20
+ annotations: {
21
+ readOnlyHint: boolean;
22
+ destructiveHint: boolean;
23
+ openWorldHint: boolean;
24
+ };
25
+ };
26
+ type GeocodeArgs = {
27
+ address?: string;
28
+ latitude?: number;
29
+ longitude?: number;
30
+ language?: string;
31
+ };
32
+ /**
33
+ * Handler for the maps_geocode tool.
34
+ * Validates that either `address` or both `latitude`+`longitude` are provided,
35
+ * checks the cache, calls Google Geocoding API on miss, and caches the result.
36
+ */
37
+ export declare function handler(args: GeocodeArgs): Promise<{
38
+ content: {
39
+ type: "text";
40
+ text: string;
41
+ }[];
42
+ isError: boolean;
43
+ } | {
44
+ content: {
45
+ type: "text";
46
+ text: string;
47
+ }[];
48
+ isError?: undefined;
49
+ }>;
50
+ export {};
51
+ //# sourceMappingURL=geocode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geocode.d.ts","sourceRoot":"","sources":["../../src/tools/geocode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,eAAO,MAAM,QAAQ,iBAAiB,CAAC;AAEvC,oDAAoD;AACpD,eAAO,MAAM,WAAW;;;;;CAmBvB,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,UAAU;;;;;;;;;;;;;;CAUtB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,WAAW;;;;;;;;;;;;GAwD9C"}