@mapbox/mcp-server 0.2.1-dev.1 → 0.2.1-dev.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 +85 -4
- package/dist/index.js +0 -0
- package/dist/index.js.map +1 -1
- package/dist/tools/MapboxApiBasedTool.d.ts +7 -0
- package/dist/tools/MapboxApiBasedTool.d.ts.map +1 -1
- package/dist/tools/MapboxApiBasedTool.js +24 -2
- package/dist/tools/MapboxApiBasedTool.js.map +1 -1
- package/dist/tools/MapboxApiBasedTool.test.d.ts +2 -0
- package/dist/tools/MapboxApiBasedTool.test.d.ts.map +1 -0
- package/dist/tools/MapboxApiBasedTool.test.js +143 -0
- package/dist/tools/MapboxApiBasedTool.test.js.map +1 -0
- package/dist/tools/category-search-tool/CategorySearchTool.d.ts +55 -6
- package/dist/tools/category-search-tool/CategorySearchTool.d.ts.map +1 -1
- package/dist/tools/category-search-tool/CategorySearchTool.js +47 -19
- package/dist/tools/category-search-tool/CategorySearchTool.js.map +1 -1
- package/dist/tools/category-search-tool/CategorySearchTool.test.js +90 -10
- package/dist/tools/category-search-tool/CategorySearchTool.test.js.map +1 -1
- package/dist/tools/directions-tool/DirectionsTool.d.ts +4 -14
- package/dist/tools/directions-tool/DirectionsTool.d.ts.map +1 -1
- package/dist/tools/directions-tool/DirectionsTool.js +31 -55
- package/dist/tools/directions-tool/DirectionsTool.js.map +1 -1
- package/dist/tools/directions-tool/DirectionsTool.test.js +115 -160
- package/dist/tools/directions-tool/DirectionsTool.test.js.map +1 -1
- package/dist/tools/directions-tool/cleanResponseData.d.ts +11 -0
- package/dist/tools/directions-tool/cleanResponseData.d.ts.map +1 -0
- package/dist/tools/directions-tool/cleanResponseData.js +175 -0
- package/dist/tools/directions-tool/cleanResponseData.js.map +1 -0
- package/dist/tools/directions-tool/cleanResponseData.test.d.ts +2 -0
- package/dist/tools/directions-tool/cleanResponseData.test.d.ts.map +1 -0
- package/dist/tools/directions-tool/cleanResponseData.test.js +295 -0
- package/dist/tools/directions-tool/cleanResponseData.test.js.map +1 -0
- package/dist/tools/directions-tool/formatIsoDateTime.d.ts +8 -0
- package/dist/tools/directions-tool/formatIsoDateTime.d.ts.map +1 -0
- package/dist/tools/directions-tool/formatIsoDateTime.js +17 -0
- package/dist/tools/directions-tool/formatIsoDateTime.js.map +1 -0
- package/dist/tools/directions-tool/formatIsoDateTime.test.d.ts +2 -0
- package/dist/tools/directions-tool/formatIsoDateTime.test.d.ts.map +1 -0
- package/dist/tools/directions-tool/formatIsoDateTime.test.js +26 -0
- package/dist/tools/directions-tool/formatIsoDateTime.test.js.map +1 -0
- package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.d.ts +55 -9
- package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.d.ts.map +1 -1
- package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.js +44 -21
- package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.js.map +1 -1
- package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.test.js +90 -10
- package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.test.js.map +1 -1
- package/dist/tools/isochrone-tool/IsochroneTool.d.ts +18 -3
- package/dist/tools/isochrone-tool/IsochroneTool.d.ts.map +1 -1
- package/dist/tools/isochrone-tool/IsochroneTool.js +6 -3
- package/dist/tools/isochrone-tool/IsochroneTool.js.map +1 -1
- package/dist/tools/isochrone-tool/IsochroneTool.test.js +8 -7
- package/dist/tools/isochrone-tool/IsochroneTool.test.js.map +1 -1
- package/dist/tools/matrix-tool/MatrixTool.d.ts +18 -3
- package/dist/tools/matrix-tool/MatrixTool.d.ts.map +1 -1
- package/dist/tools/matrix-tool/MatrixTool.js +6 -6
- package/dist/tools/matrix-tool/MatrixTool.js.map +1 -1
- package/dist/tools/matrix-tool/MatrixTool.test.js +128 -115
- package/dist/tools/matrix-tool/MatrixTool.test.js.map +1 -1
- package/dist/tools/poi-search-tool/PoiSearchTool.d.ts +73 -9
- package/dist/tools/poi-search-tool/PoiSearchTool.d.ts.map +1 -1
- package/dist/tools/poi-search-tool/PoiSearchTool.js +53 -22
- package/dist/tools/poi-search-tool/PoiSearchTool.js.map +1 -1
- package/dist/tools/poi-search-tool/PoiSearchTool.test.js +90 -10
- package/dist/tools/poi-search-tool/PoiSearchTool.test.js.map +1 -1
- package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.d.ts +5 -2
- package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.d.ts.map +1 -1
- package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.js +13 -3
- package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.js.map +1 -1
- package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.test.js +70 -7
- package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.test.js.map +1 -1
- package/dist/tools/static-map-image-tool/StaticMapImageTool.d.ts +36 -6
- package/dist/tools/static-map-image-tool/StaticMapImageTool.d.ts.map +1 -1
- package/dist/tools/static-map-image-tool/StaticMapImageTool.js +12 -9
- package/dist/tools/static-map-image-tool/StaticMapImageTool.js.map +1 -1
- package/dist/tools/static-map-image-tool/StaticMapImageTool.test.js +48 -47
- package/dist/tools/static-map-image-tool/StaticMapImageTool.test.js.map +1 -1
- package/dist/utils/requestUtils.d.ts.map +1 -1
- package/dist/utils/requestUtils.js +33 -2
- package/dist/utils/requestUtils.js.map +1 -1
- package/dist/utils/requestUtils.test-helpers.d.ts.map +1 -1
- package/dist/utils/requestUtils.test-helpers.js +5 -1
- package/dist/utils/requestUtils.test-helpers.js.map +1 -1
- package/dist/utils/requestUtils.test.d.ts +2 -0
- package/dist/utils/requestUtils.test.d.ts.map +1 -0
- package/dist/utils/requestUtils.test.js +115 -0
- package/dist/utils/requestUtils.test.js.map +1 -0
- package/dist/version.json +4 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Mapbox MCP Server
|
|
2
2
|
|
|
3
|
+
[](https://badge.fury.io/js/@mapbox%2Fmcp-server)
|
|
4
|
+
|
|
3
5
|
Node.js server implementing Model Context Protocol (MCP) for Mapbox APIs.
|
|
4
6
|
|
|
5
7
|
## Unlock Geospatial Intelligence for Your AI Applications
|
|
@@ -35,8 +37,44 @@ For detailed setup instructions for different integrations, refer to the followi
|
|
|
35
37
|
|
|
36
38
|
- [Claude Desktop Setup](./docs/claude-desktop-setup.md) - Instructions for configuring Claude Desktop to work with this MCP server
|
|
37
39
|
- [VS Code Setup](./docs/vscode-setup.md) - Setting up a development environment in Visual Studio Code
|
|
40
|
+
- [Cursor AI IDE Setup](./docs/cursor-setup.md) - Setting up a development environment in Cursor AI IDE
|
|
38
41
|
- [Smolagents Integration](./docs/using-mcp-with-smolagents/README.md) - Example showing how to connect Smolagents AI agents to Mapbox's tools
|
|
39
42
|
|
|
43
|
+
## Example Prompts
|
|
44
|
+
|
|
45
|
+
Try these prompts with Claude Desktop or other MCP clients after setup:
|
|
46
|
+
|
|
47
|
+
### Location Discovery
|
|
48
|
+
|
|
49
|
+
- "Find coffee shops within walking distance of the Empire State Building"
|
|
50
|
+
- "Show me gas stations along the route from Boston to New York"
|
|
51
|
+
- "What restaurants are near Times Square?"
|
|
52
|
+
|
|
53
|
+
### Navigation & Travel
|
|
54
|
+
|
|
55
|
+
- "Get driving directions from LAX to Hollywood with current traffic"
|
|
56
|
+
- "How long would it take to walk from Central Park to Times Square?"
|
|
57
|
+
- "Calculate travel time from my hotel (Four Seasons) to JFK Airport by taxi during rush hour"
|
|
58
|
+
|
|
59
|
+
### Visualization & Maps
|
|
60
|
+
|
|
61
|
+
- "Create a map image showing the route from Golden Gate Bridge to Fisherman's Wharf with markers at both locations"
|
|
62
|
+
- "Show me a satellite view of Manhattan with key landmarks marked"
|
|
63
|
+
- "Generate a map highlighting all Starbucks locations within a mile of downtown Seattle"
|
|
64
|
+
|
|
65
|
+
### Analysis & Planning
|
|
66
|
+
|
|
67
|
+
- "Show me areas reachable within 30 minutes of downtown Portland by car"
|
|
68
|
+
- "Calculate a travel time matrix between these 3 hotel locations (Marriott, Sheraton and Hilton) and the convention center in Denver"
|
|
69
|
+
- "Find the optimal route visiting these 3 tourist attractions (Golden Gate, Musical Stairs and Fisherman's Wharf) in San Francisco"
|
|
70
|
+
|
|
71
|
+
### Tips for Better Results
|
|
72
|
+
|
|
73
|
+
- Be specific about locations (use full addresses or landmark names)
|
|
74
|
+
- Specify your preferred travel method (driving, walking, cycling)
|
|
75
|
+
- Include time constraints when relevant ("during rush hour", "at 3 PM")
|
|
76
|
+
- Ask for specific output formats when needed ("as a map image", "in JSON format")
|
|
77
|
+
|
|
40
78
|
## Tools
|
|
41
79
|
|
|
42
80
|
### Mapbox API tools
|
|
@@ -112,13 +150,12 @@ Fetches routing directions using the [Mapbox Directions API](https://docs.mapbox
|
|
|
112
150
|
- Future departure time (`depart_at`) for driving and driving-traffic profiles
|
|
113
151
|
- Desired arrival time (`arrive_by`) for driving profile only
|
|
114
152
|
- Profile-specific optimizations:
|
|
115
|
-
- Walking: customizable walking speed and bias for/against walkways
|
|
116
153
|
- Driving: vehicle dimension constraints (height, width, weight)
|
|
117
154
|
- Exclusion options for routing:
|
|
118
155
|
- Common exclusions: ferry routes, cash-only tolls
|
|
119
156
|
- Driving-specific exclusions: tolls, motorways, unpaved roads, tunnels, country borders, state borders
|
|
120
157
|
- Custom point exclusions (up to 50 geographic points to avoid)
|
|
121
|
-
-
|
|
158
|
+
- GeoJSON geometry output format
|
|
122
159
|
|
|
123
160
|
#### Isochrone tool
|
|
124
161
|
|
|
@@ -169,9 +206,53 @@ Set `VERBOSE_ERRORS=true` to get detailed error messages from the MCP server. Th
|
|
|
169
206
|
|
|
170
207
|
By default, the server returns generic error messages. With verbose errors enabled, you'll receive the actual error details, which can help diagnose API connection issues, invalid parameters, or other problems.
|
|
171
208
|
|
|
172
|
-
##
|
|
209
|
+
## Data Usage & Privacy
|
|
210
|
+
|
|
211
|
+
### What data is sent to Mapbox APIs
|
|
212
|
+
|
|
213
|
+
When you use the MCP server tools, the following data is sent directly from your environment to Mapbox APIs:
|
|
214
|
+
|
|
215
|
+
- **Geocoding tools**: Address/location text, coordinates, country/region filters
|
|
216
|
+
- **Search tools**: Search queries, location coordinates for proximity, category filters
|
|
217
|
+
- **Directions tool**: Start/end coordinates, waypoints, routing preferences, vehicle constraints
|
|
218
|
+
- **Matrix tool**: Multiple coordinate pairs, travel profile, departure times
|
|
219
|
+
- **Static map tool**: Coordinates, zoom level, styling preferences, marker information
|
|
220
|
+
- **Isochrone tool**: Origin coordinates, time/distance parameters, travel profile
|
|
221
|
+
|
|
222
|
+
### Your privacy
|
|
223
|
+
|
|
224
|
+
- **Local execution**: All API calls are made directly from your environment to Mapbox APIs
|
|
225
|
+
- **Token security**: Your Mapbox API token remains on your local machine and is never transmitted to or stored by this MCP server
|
|
226
|
+
- **No data storage**: This MCP server does not store, log, or collect any of your data or API requests
|
|
227
|
+
- **Direct communication**: There is no intermediary server between you and Mapbox APIs
|
|
228
|
+
|
|
229
|
+
### Third-party data usage
|
|
230
|
+
|
|
231
|
+
- **Mapbox's privacy policy** governs data sent to their APIs: https://www.mapbox.com/legal/privacy/
|
|
232
|
+
- **API usage**: Standard Mapbox API terms apply to all requests made through these tools
|
|
233
|
+
- **Data retention**: Refer to Mapbox's documentation for their data retention policies
|
|
234
|
+
|
|
235
|
+
## Support & Contact
|
|
236
|
+
|
|
237
|
+
### For MCP Server Issues
|
|
238
|
+
|
|
239
|
+
- **Email**: mcp-feedback@mapbox.com
|
|
240
|
+
- **GitHub Issues**: [Report bugs and feature requests](https://github.com/mapbox/mcp-server/issues)
|
|
241
|
+
|
|
242
|
+
### For Mapbox API Questions
|
|
243
|
+
|
|
244
|
+
- **Mapbox Support**: https://support.mapbox.com/
|
|
245
|
+
- **Documentation**: https://docs.mapbox.com/
|
|
246
|
+
- **API Status**: https://status.mapbox.com/
|
|
247
|
+
|
|
248
|
+
### Maintenance Commitment
|
|
249
|
+
|
|
250
|
+
This MCP server is officially maintained by Mapbox, Inc. We provide:
|
|
173
251
|
|
|
174
|
-
|
|
252
|
+
- Regular updates for new Mapbox API features
|
|
253
|
+
- Bug fixes and security updates
|
|
254
|
+
- Compatibility with latest MCP protocol versions
|
|
255
|
+
- Community support through GitHub issues
|
|
175
256
|
|
|
176
257
|
---
|
|
177
258
|
|
package/dist/index.js
CHANGED
|
File without changes
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,oDAAoD,CAAC;AACxF,OAAO,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,oDAAoD,CAAC;AACxF,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oDAAoD,CAAC;AACxF,OAAO,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,8BAA8B;AAE9B,IAAI,iBAAiB,GAAG,cAAc,EAAE,CAAC;AACzC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;AAEpC,uBAAuB;AACvB,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;IACE,IAAI,EAAE,iBAAiB,CAAC,IAAI;IAC5B,OAAO,EAAE,iBAAiB,CAAC,OAAO;CACnC,EACD;IACE,YAAY,EAAE;QACZ,OAAO,EAAE,EAAE;KACZ;CACF,CACF,CAAC;AAEF,oCAAoC;AACpC,IAAI,UAAU,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AACnC,IAAI,kBAAkB,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAC3C,IAAI,kBAAkB,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAC3C,IAAI,aAAa,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AACtC,IAAI,aAAa,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AACtC,IAAI,kBAAkB,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAC3C,IAAI,kBAAkB,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAC3C,IAAI,cAAc,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAEvC,mEAAmE;AACnE,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
|
|
@@ -55,6 +55,13 @@ export declare abstract class MapboxApiBasedTool<InputSchema extends ZodTypeAny>
|
|
|
55
55
|
constructor(params: {
|
|
56
56
|
inputSchema: InputSchema;
|
|
57
57
|
});
|
|
58
|
+
/**
|
|
59
|
+
* Validates if a string has the format of a JWT token (header.payload.signature)
|
|
60
|
+
* Docs: https://docs.mapbox.com/api/accounts/tokens/#token-format
|
|
61
|
+
* @param token The token string to validate
|
|
62
|
+
* @returns boolean indicating if the token has valid JWT format
|
|
63
|
+
*/
|
|
64
|
+
private isValidJwtFormat;
|
|
58
65
|
/**
|
|
59
66
|
* Validates and runs the tool logic.
|
|
60
67
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapboxApiBasedTool.d.ts","sourceRoot":"","sources":["../../src/tools/MapboxApiBasedTool.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,cAAc,EACf,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAEpC,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAevB,CAAC;AAEH,8BAAsB,kBAAkB,CAAC,WAAW,SAAS,UAAU;IACrE,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAEtC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAAQ;IAE1C,MAAM,CAAC,QAAQ,CAAC,mBAAmB,qBAAmC;IACtE,MAAM,CAAC,QAAQ,CAAC,mBAAmB,SAC4B;gBAEnD,MAAM,EAAE;QAAE,WAAW,EAAE,WAAW,CAAA;KAAE;IAIhD;;OAEG;IACG,GAAG,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"MapboxApiBasedTool.d.ts","sourceRoot":"","sources":["../../src/tools/MapboxApiBasedTool.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,cAAc,EACf,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAEpC,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAevB,CAAC;AAEH,8BAAsB,kBAAkB,CAAC,WAAW,SAAS,UAAU;IACrE,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAEtC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAAQ;IAE1C,MAAM,CAAC,QAAQ,CAAC,mBAAmB,qBAAmC;IACtE,MAAM,CAAC,QAAQ,CAAC,mBAAmB,SAC4B;gBAEnD,MAAM,EAAE;QAAE,WAAW,EAAE,WAAW,CAAA;KAAE;IAIhD;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IASxB;;OAEG;IACG,GAAG,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;IAwDnE;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IAEtE;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,cAAc;IAU5C;;OAEG;IACH,SAAS,CAAC,GAAG,CACX,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,EAC7C,IAAI,EAAE,GAAG,GACR,IAAI;CAKR"}
|
|
@@ -21,6 +21,20 @@ export class MapboxApiBasedTool {
|
|
|
21
21
|
constructor(params) {
|
|
22
22
|
this.inputSchema = params.inputSchema;
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Validates if a string has the format of a JWT token (header.payload.signature)
|
|
26
|
+
* Docs: https://docs.mapbox.com/api/accounts/tokens/#token-format
|
|
27
|
+
* @param token The token string to validate
|
|
28
|
+
* @returns boolean indicating if the token has valid JWT format
|
|
29
|
+
*/
|
|
30
|
+
isValidJwtFormat(token) {
|
|
31
|
+
// JWT consists of three parts separated by dots: header.payload.signature
|
|
32
|
+
const parts = token.split('.');
|
|
33
|
+
if (parts.length !== 3)
|
|
34
|
+
return false;
|
|
35
|
+
// Check that all parts are non-empty
|
|
36
|
+
return parts.every((part) => part.length > 0);
|
|
37
|
+
}
|
|
24
38
|
/**
|
|
25
39
|
* Validates and runs the tool logic.
|
|
26
40
|
*/
|
|
@@ -29,6 +43,10 @@ export class MapboxApiBasedTool {
|
|
|
29
43
|
if (!MapboxApiBasedTool.MAPBOX_ACCESS_TOKEN) {
|
|
30
44
|
throw new Error('MAPBOX_ACCESS_TOKEN is not set');
|
|
31
45
|
}
|
|
46
|
+
// Validate that the token has the correct JWT format
|
|
47
|
+
if (!this.isValidJwtFormat(MapboxApiBasedTool.MAPBOX_ACCESS_TOKEN)) {
|
|
48
|
+
throw new Error('MAPBOX_ACCESS_TOKEN is not in valid JWT format');
|
|
49
|
+
}
|
|
32
50
|
const input = this.inputSchema.parse(rawInput);
|
|
33
51
|
const result = await this.execute(input);
|
|
34
52
|
// Check if result is already a content object (image or text)
|
|
@@ -47,12 +65,16 @@ export class MapboxApiBasedTool {
|
|
|
47
65
|
};
|
|
48
66
|
}
|
|
49
67
|
catch (error) {
|
|
50
|
-
|
|
68
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
69
|
+
this.log('error', `${this.name}: Error during execution: ${errorMessage}`);
|
|
70
|
+
const isVerboseErrors = process.env.VERBOSE_ERRORS === 'true';
|
|
51
71
|
return {
|
|
52
72
|
content: [
|
|
53
73
|
{
|
|
54
74
|
type: 'text',
|
|
55
|
-
text:
|
|
75
|
+
text: isVerboseErrors
|
|
76
|
+
? errorMessage
|
|
77
|
+
: 'Internal error has occurred.'
|
|
56
78
|
}
|
|
57
79
|
],
|
|
58
80
|
is_error: true
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapboxApiBasedTool.js","sourceRoot":"","sources":["../../src/tools/MapboxApiBasedTool.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAc,MAAM,KAAK,CAAC;AAEpC,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,OAAO,EAAE,CAAC,CAAC,KAAK,CACd,CAAC,CAAC,KAAK,CAAC;QACN,CAAC,CAAC,MAAM,CAAC;YACP,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;YACvB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;SACjB,CAAC;QACF,CAAC,CAAC,MAAM,CAAC;YACP,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;YACxB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;YAChB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;SACrB,CAAC;KACH,CAAC,CACH;IACD,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;CACrC,CAAC,CAAC;AAEH,MAAM,OAAgB,kBAAkB;IAI7B,WAAW,CAAc;IACxB,MAAM,GAAqB,IAAI,CAAC;IAE1C,MAAM,CAAU,mBAAmB,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;IACtE,MAAM,CAAU,mBAAmB,GACjC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,yBAAyB,CAAC;IAE/D,YAAY,MAAoC;QAC9C,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,QAAiB;QACzB,IAAI,CAAC;YACH,IAAI,CAAC,kBAAkB,CAAC,mBAAmB,EAAE,CAAC;gBAC5C,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;YACpD,CAAC;YAED,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAEzC,8DAA8D;YAC9D,IACE,MAAM;gBACN,OAAO,MAAM,KAAK,QAAQ;gBAC1B,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,EACnD,CAAC;gBACD,OAAO;oBACL,OAAO,EAAE,CAAC,MAAM,CAAC;oBACjB,QAAQ,EAAE,KAAK;iBAChB,CAAC;YACJ,CAAC;YAED,2BAA2B;YAC3B,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzD,QAAQ,EAAE,KAAK;aAChB,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,GAAG,CACN,OAAO,EACP,GAAG,IAAI,CAAC,IAAI,6BAA6B,
|
|
1
|
+
{"version":3,"file":"MapboxApiBasedTool.js","sourceRoot":"","sources":["../../src/tools/MapboxApiBasedTool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MapboxApiBasedTool.test.d.ts","sourceRoot":"","sources":["../../src/tools/MapboxApiBasedTool.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// Use a token with valid JWT format for tests
|
|
2
|
+
process.env.MAPBOX_ACCESS_TOKEN =
|
|
3
|
+
'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0In0.signature';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { MapboxApiBasedTool } from './MapboxApiBasedTool';
|
|
6
|
+
// Create a minimal implementation of MapboxApiBasedTool for testing
|
|
7
|
+
class TestTool extends MapboxApiBasedTool {
|
|
8
|
+
name = 'test-tool';
|
|
9
|
+
description = 'Tool for testing MapboxApiBasedTool error handling';
|
|
10
|
+
static inputSchema = z.object({
|
|
11
|
+
testParam: z.string()
|
|
12
|
+
});
|
|
13
|
+
constructor() {
|
|
14
|
+
super({ inputSchema: TestTool.inputSchema });
|
|
15
|
+
}
|
|
16
|
+
async execute(_input) {
|
|
17
|
+
throw new Error('Test error message');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
describe('MapboxApiBasedTool', () => {
|
|
21
|
+
let testTool;
|
|
22
|
+
const originalEnv = process.env;
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
testTool = new TestTool();
|
|
25
|
+
// Mock the log method to test that errors are properly logged
|
|
26
|
+
testTool['log'] = jest.fn();
|
|
27
|
+
});
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
// Restore the process.env to its original state
|
|
30
|
+
process.env = { ...originalEnv };
|
|
31
|
+
jest.clearAllMocks();
|
|
32
|
+
});
|
|
33
|
+
describe('JWT token validation', () => {
|
|
34
|
+
it('throws an error when the token is not in a valid JWT format', async () => {
|
|
35
|
+
// Test the private isValidJwtFormat method directly
|
|
36
|
+
const originalToken = MapboxApiBasedTool.MAPBOX_ACCESS_TOKEN;
|
|
37
|
+
try {
|
|
38
|
+
// Temporarily modify the static property for testing
|
|
39
|
+
Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', {
|
|
40
|
+
value: 'invalid-token-format',
|
|
41
|
+
writable: true,
|
|
42
|
+
configurable: true
|
|
43
|
+
});
|
|
44
|
+
// Create a new instance with the modified token
|
|
45
|
+
const toolWithInvalidToken = new TestTool();
|
|
46
|
+
// Mock the log method separately for this instance
|
|
47
|
+
toolWithInvalidToken['log'] = jest.fn();
|
|
48
|
+
// Try to call the run method, it should throw an error due to invalid JWT format
|
|
49
|
+
const result = await toolWithInvalidToken.run({ testParam: 'test' });
|
|
50
|
+
// Verify the error response
|
|
51
|
+
expect(result.is_error).toBe(true);
|
|
52
|
+
// Check for error message content
|
|
53
|
+
if (process.env.VERBOSE_ERRORS === 'true') {
|
|
54
|
+
expect(result.content[0].text).toContain('not in valid JWT format');
|
|
55
|
+
}
|
|
56
|
+
// Verify the error was logged
|
|
57
|
+
expect(toolWithInvalidToken['log']).toHaveBeenCalledWith('error', expect.stringMatching(/.*not in valid JWT format.*/));
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
// Restore the original value
|
|
61
|
+
Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', {
|
|
62
|
+
value: originalToken,
|
|
63
|
+
writable: true,
|
|
64
|
+
configurable: true
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
it('accepts a token with valid JWT format', async () => {
|
|
69
|
+
// Set a valid JWT format token (header.payload.signature)
|
|
70
|
+
process.env.MAPBOX_ACCESS_TOKEN =
|
|
71
|
+
'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0In0.signature';
|
|
72
|
+
// Override execute to return a success result instead of throwing an error
|
|
73
|
+
testTool['execute'] = jest.fn().mockResolvedValue({ success: true });
|
|
74
|
+
const result = await testTool.run({ testParam: 'test' });
|
|
75
|
+
// The token validation should pass, and we should get the success result
|
|
76
|
+
expect(result.is_error).toBe(false);
|
|
77
|
+
expect(result.content[0]).toHaveProperty('type', 'text');
|
|
78
|
+
expect(JSON.parse(result.content[0].text)).toEqual({ success: true });
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe('error handling', () => {
|
|
82
|
+
it('returns generic error message when VERBOSE_ERRORS is not set to true', async () => {
|
|
83
|
+
// Make sure VERBOSE_ERRORS is not set to true
|
|
84
|
+
delete process.env.VERBOSE_ERRORS;
|
|
85
|
+
const result = await testTool.run({ testParam: 'test' });
|
|
86
|
+
// Verify the response contains the generic error message
|
|
87
|
+
expect(result.is_error).toBe(true);
|
|
88
|
+
expect(result.content).toHaveLength(1);
|
|
89
|
+
expect(result.content[0]).toMatchObject({
|
|
90
|
+
type: 'text',
|
|
91
|
+
text: 'Internal error has occurred.'
|
|
92
|
+
});
|
|
93
|
+
// Verify the error was logged with the actual error message
|
|
94
|
+
expect(testTool['log']).toHaveBeenCalledWith('error', expect.stringContaining('Test error message'));
|
|
95
|
+
});
|
|
96
|
+
it('returns actual error message when VERBOSE_ERRORS=true', async () => {
|
|
97
|
+
// Set VERBOSE_ERRORS to true
|
|
98
|
+
process.env.VERBOSE_ERRORS = 'true';
|
|
99
|
+
const result = await testTool.run({ testParam: 'test' });
|
|
100
|
+
// Verify the response contains the actual error message
|
|
101
|
+
expect(result.is_error).toBe(true);
|
|
102
|
+
expect(result.content).toHaveLength(1);
|
|
103
|
+
expect(result.content[0]).toMatchObject({
|
|
104
|
+
type: 'text',
|
|
105
|
+
text: 'Test error message'
|
|
106
|
+
});
|
|
107
|
+
// Verify the error was logged with the actual error message
|
|
108
|
+
expect(testTool['log']).toHaveBeenCalledWith('error', expect.stringContaining('Test error message'));
|
|
109
|
+
});
|
|
110
|
+
it('returns generic error message when VERBOSE_ERRORS is set to a value other than true', async () => {
|
|
111
|
+
// Set VERBOSE_ERRORS to something other than 'true'
|
|
112
|
+
process.env.VERBOSE_ERRORS = 'yes';
|
|
113
|
+
const result = await testTool.run({ testParam: 'test' });
|
|
114
|
+
// Verify the response contains the generic error message
|
|
115
|
+
expect(result.is_error).toBe(true);
|
|
116
|
+
expect(result.content).toHaveLength(1);
|
|
117
|
+
expect(result.content[0]).toMatchObject({
|
|
118
|
+
type: 'text',
|
|
119
|
+
text: 'Internal error has occurred.'
|
|
120
|
+
});
|
|
121
|
+
// Verify the error was logged with the actual error message
|
|
122
|
+
expect(testTool['log']).toHaveBeenCalledWith('error', expect.stringContaining('Test error message'));
|
|
123
|
+
});
|
|
124
|
+
it('handles non-Error objects thrown', async () => {
|
|
125
|
+
// Override the execute method to throw a string instead of an Error
|
|
126
|
+
testTool['execute'] = jest.fn().mockImplementation(() => {
|
|
127
|
+
throw 'String error message';
|
|
128
|
+
});
|
|
129
|
+
process.env.VERBOSE_ERRORS = 'true';
|
|
130
|
+
const result = await testTool.run({ testParam: 'test' });
|
|
131
|
+
// Verify the response contains the string error
|
|
132
|
+
expect(result.is_error).toBe(true);
|
|
133
|
+
expect(result.content).toHaveLength(1);
|
|
134
|
+
expect(result.content[0]).toMatchObject({
|
|
135
|
+
type: 'text',
|
|
136
|
+
text: 'String error message'
|
|
137
|
+
});
|
|
138
|
+
// Verify the error was logged
|
|
139
|
+
expect(testTool['log']).toHaveBeenCalledWith('error', expect.stringContaining('String error message'));
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
//# sourceMappingURL=MapboxApiBasedTool.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MapboxApiBasedTool.test.js","sourceRoot":"","sources":["../../src/tools/MapboxApiBasedTool.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,26 +4,75 @@ declare const CategorySearchInputSchema: z.ZodObject<{
|
|
|
4
4
|
category: z.ZodString;
|
|
5
5
|
language: z.ZodOptional<z.ZodString>;
|
|
6
6
|
limit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
7
|
-
proximity: z.ZodOptional<z.ZodUnion<[z.
|
|
8
|
-
|
|
7
|
+
proximity: z.ZodOptional<z.ZodUnion<[z.ZodObject<{
|
|
8
|
+
longitude: z.ZodNumber;
|
|
9
|
+
latitude: z.ZodNumber;
|
|
10
|
+
}, "strip", z.ZodTypeAny, {
|
|
11
|
+
longitude: number;
|
|
12
|
+
latitude: number;
|
|
13
|
+
}, {
|
|
14
|
+
longitude: number;
|
|
15
|
+
latitude: number;
|
|
16
|
+
}>, z.ZodEffects<z.ZodString, "ip" | {
|
|
17
|
+
longitude: any;
|
|
18
|
+
latitude: any;
|
|
19
|
+
}, string>]>>;
|
|
20
|
+
bbox: z.ZodOptional<z.ZodObject<{
|
|
21
|
+
minLongitude: z.ZodNumber;
|
|
22
|
+
minLatitude: z.ZodNumber;
|
|
23
|
+
maxLongitude: z.ZodNumber;
|
|
24
|
+
maxLatitude: z.ZodNumber;
|
|
25
|
+
}, "strip", z.ZodTypeAny, {
|
|
26
|
+
minLongitude: number;
|
|
27
|
+
minLatitude: number;
|
|
28
|
+
maxLongitude: number;
|
|
29
|
+
maxLatitude: number;
|
|
30
|
+
}, {
|
|
31
|
+
minLongitude: number;
|
|
32
|
+
minLatitude: number;
|
|
33
|
+
maxLongitude: number;
|
|
34
|
+
maxLatitude: number;
|
|
35
|
+
}>>;
|
|
9
36
|
country: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
10
37
|
poi_category_exclusions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
38
|
+
format: z.ZodDefault<z.ZodOptional<z.ZodEnum<["json_string", "formatted_text"]>>>;
|
|
11
39
|
}, "strip", z.ZodTypeAny, {
|
|
12
40
|
category: string;
|
|
13
41
|
limit: number;
|
|
42
|
+
format: "json_string" | "formatted_text";
|
|
14
43
|
country?: string[] | undefined;
|
|
15
44
|
language?: string | undefined;
|
|
16
|
-
proximity?:
|
|
17
|
-
|
|
45
|
+
proximity?: {
|
|
46
|
+
longitude: number;
|
|
47
|
+
latitude: number;
|
|
48
|
+
} | "ip" | {
|
|
49
|
+
longitude: any;
|
|
50
|
+
latitude: any;
|
|
51
|
+
} | undefined;
|
|
52
|
+
bbox?: {
|
|
53
|
+
minLongitude: number;
|
|
54
|
+
minLatitude: number;
|
|
55
|
+
maxLongitude: number;
|
|
56
|
+
maxLatitude: number;
|
|
57
|
+
} | undefined;
|
|
18
58
|
poi_category_exclusions?: string[] | undefined;
|
|
19
59
|
}, {
|
|
20
60
|
category: string;
|
|
21
61
|
country?: string[] | undefined;
|
|
22
62
|
language?: string | undefined;
|
|
23
63
|
limit?: number | undefined;
|
|
24
|
-
proximity?: string |
|
|
25
|
-
|
|
64
|
+
proximity?: string | {
|
|
65
|
+
longitude: number;
|
|
66
|
+
latitude: number;
|
|
67
|
+
} | undefined;
|
|
68
|
+
bbox?: {
|
|
69
|
+
minLongitude: number;
|
|
70
|
+
minLatitude: number;
|
|
71
|
+
maxLongitude: number;
|
|
72
|
+
maxLatitude: number;
|
|
73
|
+
} | undefined;
|
|
26
74
|
poi_category_exclusions?: string[] | undefined;
|
|
75
|
+
format?: "json_string" | "formatted_text" | undefined;
|
|
27
76
|
}>;
|
|
28
77
|
export declare class CategorySearchTool extends MapboxApiBasedTool<typeof CategorySearchInputSchema> {
|
|
29
78
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CategorySearchTool.d.ts","sourceRoot":"","sources":["../../../src/tools/category-search-tool/CategorySearchTool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAwe9D,QAAA,MAAM,yBAAyB
|
|
1
|
+
{"version":3,"file":"CategorySearchTool.d.ts","sourceRoot":"","sources":["../../../src/tools/category-search-tool/CategorySearchTool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAwe9D,QAAA,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8F7B,CAAC;AAEH,qBAAa,kBAAmB,SAAQ,kBAAkB,CACxD,OAAO,yBAAyB,CACjC;IACC,IAAI,SAAwB;IAC5B,WAAW,SACoX;;IAM/X,OAAO,CAAC,mBAAmB;cAsDX,OAAO,CACrB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,GAC/C,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAsE3C"}
|
|
@@ -502,12 +502,30 @@ const CategorySearchInputSchema = z.object({
|
|
|
502
502
|
.describe('Maximum number of results to return (1-25)'),
|
|
503
503
|
proximity: z
|
|
504
504
|
.union([
|
|
505
|
-
z.
|
|
505
|
+
z.object({
|
|
506
|
+
longitude: z.number().min(-180).max(180),
|
|
507
|
+
latitude: z.number().min(-90).max(90)
|
|
508
|
+
}),
|
|
506
509
|
z.string().transform((val) => {
|
|
507
510
|
// Handle special case of 'ip'
|
|
508
511
|
if (val === 'ip') {
|
|
509
512
|
return 'ip';
|
|
510
513
|
}
|
|
514
|
+
// Handle JSON-stringified object: "{\"longitude\": -82.458107, \"latitude\": 27.937259}"
|
|
515
|
+
if (val.startsWith('{') && val.endsWith('}')) {
|
|
516
|
+
try {
|
|
517
|
+
const parsed = JSON.parse(val);
|
|
518
|
+
if (typeof parsed === 'object' &&
|
|
519
|
+
parsed !== null &&
|
|
520
|
+
typeof parsed.longitude === 'number' &&
|
|
521
|
+
typeof parsed.latitude === 'number') {
|
|
522
|
+
return { longitude: parsed.longitude, latitude: parsed.latitude };
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
catch {
|
|
526
|
+
// Fall back to other formats
|
|
527
|
+
}
|
|
528
|
+
}
|
|
511
529
|
// Handle string that looks like an array: "[-82.451668, 27.942964]"
|
|
512
530
|
if (val.startsWith('[') && val.endsWith(']')) {
|
|
513
531
|
const coords = val
|
|
@@ -515,28 +533,28 @@ const CategorySearchInputSchema = z.object({
|
|
|
515
533
|
.split(',')
|
|
516
534
|
.map((s) => Number(s.trim()));
|
|
517
535
|
if (coords.length === 2 && !isNaN(coords[0]) && !isNaN(coords[1])) {
|
|
518
|
-
return coords;
|
|
536
|
+
return { longitude: coords[0], latitude: coords[1] };
|
|
519
537
|
}
|
|
520
538
|
}
|
|
521
539
|
// Handle comma-separated string: "-82.451668,27.942964"
|
|
522
540
|
const parts = val.split(',').map((s) => Number(s.trim()));
|
|
523
541
|
if (parts.length === 2 && !isNaN(parts[0]) && !isNaN(parts[1])) {
|
|
524
|
-
return parts;
|
|
542
|
+
return { longitude: parts[0], latitude: parts[1] };
|
|
525
543
|
}
|
|
526
|
-
throw new Error('Invalid proximity format. Expected
|
|
544
|
+
throw new Error('Invalid proximity format. Expected {longitude, latitude}, "longitude,latitude", or "ip"');
|
|
527
545
|
})
|
|
528
546
|
])
|
|
529
547
|
.optional()
|
|
530
|
-
.describe('Location to bias results towards. Either
|
|
548
|
+
.describe('Location to bias results towards. Either coordinate object with longitude and latitude or "ip" for IP-based location'),
|
|
531
549
|
bbox: z
|
|
532
|
-
.
|
|
533
|
-
z.number().min(-180).max(180),
|
|
534
|
-
z.number().min(-90).max(90),
|
|
535
|
-
z.number().min(-180).max(180),
|
|
536
|
-
z.number().min(-90).max(90)
|
|
537
|
-
|
|
550
|
+
.object({
|
|
551
|
+
minLongitude: z.number().min(-180).max(180),
|
|
552
|
+
minLatitude: z.number().min(-90).max(90),
|
|
553
|
+
maxLongitude: z.number().min(-180).max(180),
|
|
554
|
+
maxLatitude: z.number().min(-90).max(90)
|
|
555
|
+
})
|
|
538
556
|
.optional()
|
|
539
|
-
.describe('Bounding box to limit results within
|
|
557
|
+
.describe('Bounding box to limit results within specified bounds'),
|
|
540
558
|
country: z
|
|
541
559
|
.array(z.string().length(2))
|
|
542
560
|
.optional()
|
|
@@ -544,11 +562,16 @@ const CategorySearchInputSchema = z.object({
|
|
|
544
562
|
poi_category_exclusions: z
|
|
545
563
|
.array(z.string())
|
|
546
564
|
.optional()
|
|
547
|
-
.describe('Array of POI categories to exclude from results')
|
|
565
|
+
.describe('Array of POI categories to exclude from results'),
|
|
566
|
+
format: z
|
|
567
|
+
.enum(['json_string', 'formatted_text'])
|
|
568
|
+
.optional()
|
|
569
|
+
.default('formatted_text')
|
|
570
|
+
.describe('Output format: "json_string" returns raw GeoJSON data as a JSON string that can be parsed; "formatted_text" returns human-readable text with place names, addresses, and coordinates. Both return as text content but json_string contains parseable JSON data while formatted_text is for display.')
|
|
548
571
|
});
|
|
549
572
|
export class CategorySearchTool extends MapboxApiBasedTool {
|
|
550
573
|
name = 'CategorySearchTool';
|
|
551
|
-
description = "Return all places that match a category (industry, amenity, or NAICS‑style code). Use when the user asks for a type of place, plural or generic terms like 'museums', 'coffee shops', 'electric‑vehicle chargers', or when the query includes is‑a phrases such as 'any', 'all', 'nearby'. Do not use when a unique name or brand is provided.";
|
|
574
|
+
description = "Return all places that match a category (industry, amenity, or NAICS‑style code). Use when the user asks for a type of place, plural or generic terms like 'museums', 'coffee shops', 'electric‑vehicle chargers', or when the query includes is‑a phrases such as 'any', 'all', 'nearby'. Do not use when a unique name or brand is provided. Supports both JSON and text output formats.";
|
|
552
575
|
constructor() {
|
|
553
576
|
super({ inputSchema: CategorySearchInputSchema });
|
|
554
577
|
}
|
|
@@ -611,13 +634,13 @@ export class CategorySearchTool extends MapboxApiBasedTool {
|
|
|
611
634
|
url.searchParams.append('proximity', 'ip');
|
|
612
635
|
}
|
|
613
636
|
else {
|
|
614
|
-
const
|
|
615
|
-
url.searchParams.append('proximity', `${
|
|
637
|
+
const { longitude, latitude } = input.proximity;
|
|
638
|
+
url.searchParams.append('proximity', `${longitude},${latitude}`);
|
|
616
639
|
}
|
|
617
640
|
}
|
|
618
641
|
if (input.bbox) {
|
|
619
|
-
const
|
|
620
|
-
url.searchParams.append('bbox', `${
|
|
642
|
+
const { minLongitude, minLatitude, maxLongitude, maxLatitude } = input.bbox;
|
|
643
|
+
url.searchParams.append('bbox', `${minLongitude},${minLatitude},${maxLongitude},${maxLatitude}`);
|
|
621
644
|
}
|
|
622
645
|
if (input.country && input.country.length > 0) {
|
|
623
646
|
url.searchParams.append('country', input.country.join(','));
|
|
@@ -632,7 +655,12 @@ export class CategorySearchTool extends MapboxApiBasedTool {
|
|
|
632
655
|
throw new Error(`Failed to search category: ${response.status} ${response.statusText}`);
|
|
633
656
|
}
|
|
634
657
|
const data = await response.json();
|
|
635
|
-
|
|
658
|
+
if (input.format === 'json_string') {
|
|
659
|
+
return { type: 'text', text: JSON.stringify(data, null, 2) };
|
|
660
|
+
}
|
|
661
|
+
else {
|
|
662
|
+
return { type: 'text', text: this.formatGeoJsonToText(data) };
|
|
663
|
+
}
|
|
636
664
|
}
|
|
637
665
|
}
|
|
638
666
|
//# sourceMappingURL=CategorySearchTool.js.map
|