@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.
Files changed (87) hide show
  1. package/README.md +85 -4
  2. package/dist/index.js +0 -0
  3. package/dist/index.js.map +1 -1
  4. package/dist/tools/MapboxApiBasedTool.d.ts +7 -0
  5. package/dist/tools/MapboxApiBasedTool.d.ts.map +1 -1
  6. package/dist/tools/MapboxApiBasedTool.js +24 -2
  7. package/dist/tools/MapboxApiBasedTool.js.map +1 -1
  8. package/dist/tools/MapboxApiBasedTool.test.d.ts +2 -0
  9. package/dist/tools/MapboxApiBasedTool.test.d.ts.map +1 -0
  10. package/dist/tools/MapboxApiBasedTool.test.js +143 -0
  11. package/dist/tools/MapboxApiBasedTool.test.js.map +1 -0
  12. package/dist/tools/category-search-tool/CategorySearchTool.d.ts +55 -6
  13. package/dist/tools/category-search-tool/CategorySearchTool.d.ts.map +1 -1
  14. package/dist/tools/category-search-tool/CategorySearchTool.js +47 -19
  15. package/dist/tools/category-search-tool/CategorySearchTool.js.map +1 -1
  16. package/dist/tools/category-search-tool/CategorySearchTool.test.js +90 -10
  17. package/dist/tools/category-search-tool/CategorySearchTool.test.js.map +1 -1
  18. package/dist/tools/directions-tool/DirectionsTool.d.ts +4 -14
  19. package/dist/tools/directions-tool/DirectionsTool.d.ts.map +1 -1
  20. package/dist/tools/directions-tool/DirectionsTool.js +31 -55
  21. package/dist/tools/directions-tool/DirectionsTool.js.map +1 -1
  22. package/dist/tools/directions-tool/DirectionsTool.test.js +115 -160
  23. package/dist/tools/directions-tool/DirectionsTool.test.js.map +1 -1
  24. package/dist/tools/directions-tool/cleanResponseData.d.ts +11 -0
  25. package/dist/tools/directions-tool/cleanResponseData.d.ts.map +1 -0
  26. package/dist/tools/directions-tool/cleanResponseData.js +175 -0
  27. package/dist/tools/directions-tool/cleanResponseData.js.map +1 -0
  28. package/dist/tools/directions-tool/cleanResponseData.test.d.ts +2 -0
  29. package/dist/tools/directions-tool/cleanResponseData.test.d.ts.map +1 -0
  30. package/dist/tools/directions-tool/cleanResponseData.test.js +295 -0
  31. package/dist/tools/directions-tool/cleanResponseData.test.js.map +1 -0
  32. package/dist/tools/directions-tool/formatIsoDateTime.d.ts +8 -0
  33. package/dist/tools/directions-tool/formatIsoDateTime.d.ts.map +1 -0
  34. package/dist/tools/directions-tool/formatIsoDateTime.js +17 -0
  35. package/dist/tools/directions-tool/formatIsoDateTime.js.map +1 -0
  36. package/dist/tools/directions-tool/formatIsoDateTime.test.d.ts +2 -0
  37. package/dist/tools/directions-tool/formatIsoDateTime.test.d.ts.map +1 -0
  38. package/dist/tools/directions-tool/formatIsoDateTime.test.js +26 -0
  39. package/dist/tools/directions-tool/formatIsoDateTime.test.js.map +1 -0
  40. package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.d.ts +55 -9
  41. package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.d.ts.map +1 -1
  42. package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.js +44 -21
  43. package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.js.map +1 -1
  44. package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.test.js +90 -10
  45. package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.test.js.map +1 -1
  46. package/dist/tools/isochrone-tool/IsochroneTool.d.ts +18 -3
  47. package/dist/tools/isochrone-tool/IsochroneTool.d.ts.map +1 -1
  48. package/dist/tools/isochrone-tool/IsochroneTool.js +6 -3
  49. package/dist/tools/isochrone-tool/IsochroneTool.js.map +1 -1
  50. package/dist/tools/isochrone-tool/IsochroneTool.test.js +8 -7
  51. package/dist/tools/isochrone-tool/IsochroneTool.test.js.map +1 -1
  52. package/dist/tools/matrix-tool/MatrixTool.d.ts +18 -3
  53. package/dist/tools/matrix-tool/MatrixTool.d.ts.map +1 -1
  54. package/dist/tools/matrix-tool/MatrixTool.js +6 -6
  55. package/dist/tools/matrix-tool/MatrixTool.js.map +1 -1
  56. package/dist/tools/matrix-tool/MatrixTool.test.js +128 -115
  57. package/dist/tools/matrix-tool/MatrixTool.test.js.map +1 -1
  58. package/dist/tools/poi-search-tool/PoiSearchTool.d.ts +73 -9
  59. package/dist/tools/poi-search-tool/PoiSearchTool.d.ts.map +1 -1
  60. package/dist/tools/poi-search-tool/PoiSearchTool.js +53 -22
  61. package/dist/tools/poi-search-tool/PoiSearchTool.js.map +1 -1
  62. package/dist/tools/poi-search-tool/PoiSearchTool.test.js +90 -10
  63. package/dist/tools/poi-search-tool/PoiSearchTool.test.js.map +1 -1
  64. package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.d.ts +5 -2
  65. package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.d.ts.map +1 -1
  66. package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.js +13 -3
  67. package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.js.map +1 -1
  68. package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.test.js +70 -7
  69. package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.test.js.map +1 -1
  70. package/dist/tools/static-map-image-tool/StaticMapImageTool.d.ts +36 -6
  71. package/dist/tools/static-map-image-tool/StaticMapImageTool.d.ts.map +1 -1
  72. package/dist/tools/static-map-image-tool/StaticMapImageTool.js +12 -9
  73. package/dist/tools/static-map-image-tool/StaticMapImageTool.js.map +1 -1
  74. package/dist/tools/static-map-image-tool/StaticMapImageTool.test.js +48 -47
  75. package/dist/tools/static-map-image-tool/StaticMapImageTool.test.js.map +1 -1
  76. package/dist/utils/requestUtils.d.ts.map +1 -1
  77. package/dist/utils/requestUtils.js +33 -2
  78. package/dist/utils/requestUtils.js.map +1 -1
  79. package/dist/utils/requestUtils.test-helpers.d.ts.map +1 -1
  80. package/dist/utils/requestUtils.test-helpers.js +5 -1
  81. package/dist/utils/requestUtils.test-helpers.js.map +1 -1
  82. package/dist/utils/requestUtils.test.d.ts +2 -0
  83. package/dist/utils/requestUtils.test.d.ts.map +1 -0
  84. package/dist/utils/requestUtils.test.js +115 -0
  85. package/dist/utils/requestUtils.test.js.map +1 -0
  86. package/dist/version.json +4 -4
  87. package/package.json +2 -2
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Mapbox MCP Server
2
2
 
3
+ [![npm version](https://badge.fury.io/js/@mapbox%2Fmcp-server.svg)](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
- - Multiple geometry output formats (GeoJSON, polyline)
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
- ## Feedback
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
- For feedback and questions about this MCP server, email mcp-feedback@mapbox.com.
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,EACL,SAAS,EACV,MAAM,yCAAyC,CAAC;AACjD,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"}
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;IA2CnE;;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"}
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
- this.log('error', `${this.name}: Error during execution: ${error instanceof Error ? error.message : String(error)}`);
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: 'Internal error has occurred.'
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":"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"}
1
+ {"version":3,"file":"MapboxApiBasedTool.js","sourceRoot":"","sources":["../../src/tools/MapboxApiBasedTool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=MapboxApiBasedTool.test.d.ts.map
@@ -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.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, z.ZodEffects<z.ZodString, [number, number] | "ip", string>]>>;
8
- bbox: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
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?: [number, number] | "ip" | undefined;
17
- bbox?: [number, number, number, number] | undefined;
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 | [number, number] | undefined;
25
- bbox?: [number, number, number, number] | undefined;
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;;;;;;;;;;;;;;;;;;;;;;;;EAsE7B,CAAC;AAEH,qBAAa,kBAAmB,SAAQ,kBAAkB,CACxD,OAAO,yBAAyB,CACjC;IACC,IAAI,SAAwB;IAC5B,WAAW,SACwU;;IAMnV,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;CAgE3C"}
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.tuple([z.number().min(-180).max(180), z.number().min(-90).max(90)]),
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 [longitude, latitude], "longitude,latitude", or "ip"');
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 [longitude, latitude] or "ip" for IP-based location'),
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
- .tuple([
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 [minLon, minLat, maxLon, maxLat]'),
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 [lng, lat] = input.proximity;
615
- url.searchParams.append('proximity', `${lng},${lat}`);
637
+ const { longitude, latitude } = input.proximity;
638
+ url.searchParams.append('proximity', `${longitude},${latitude}`);
616
639
  }
617
640
  }
618
641
  if (input.bbox) {
619
- const [minLon, minLat, maxLon, maxLat] = input.bbox;
620
- url.searchParams.append('bbox', `${minLon},${minLat},${maxLon},${maxLat}`);
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
- return { type: 'text', text: this.formatGeoJsonToText(data) };
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