@mapbox/mcp-server 0.13.0 → 0.14.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 (110) hide show
  1. package/README.md +100 -14
  2. package/dist/commonjs/cli.d.ts.map +1 -1
  3. package/dist/commonjs/cli.js +5 -2
  4. package/dist/commonjs/cli.js.map +1 -1
  5. package/dist/commonjs/resources/resourceRegistry.d.ts +1 -2
  6. package/dist/commonjs/resources/resourceRegistry.d.ts.map +1 -1
  7. package/dist/commonjs/resources/resourceRegistry.js +0 -2
  8. package/dist/commonjs/resources/resourceRegistry.js.map +1 -1
  9. package/dist/commonjs/resources/ui-apps/mapAppHtml.d.ts +3 -3
  10. package/dist/commonjs/resources/ui-apps/mapAppHtml.d.ts.map +1 -1
  11. package/dist/commonjs/resources/ui-apps/mapAppHtml.js +18 -4
  12. package/dist/commonjs/resources/ui-apps/mapAppHtml.js.map +1 -1
  13. package/dist/commonjs/tools/directions-tool/DirectionsTool.d.ts +16 -0
  14. package/dist/commonjs/tools/directions-tool/DirectionsTool.d.ts.map +1 -1
  15. package/dist/commonjs/tools/directions-tool/DirectionsTool.js +105 -1
  16. package/dist/commonjs/tools/directions-tool/DirectionsTool.js.map +1 -1
  17. package/dist/commonjs/tools/place-details-tool/PlaceDetailsTool.d.ts.map +1 -1
  18. package/dist/commonjs/tools/place-details-tool/PlaceDetailsTool.input.schema.js +1 -1
  19. package/dist/commonjs/tools/place-details-tool/PlaceDetailsTool.input.schema.js.map +1 -1
  20. package/dist/commonjs/tools/place-details-tool/PlaceDetailsTool.js +7 -3
  21. package/dist/commonjs/tools/place-details-tool/PlaceDetailsTool.js.map +1 -1
  22. package/dist/commonjs/tools/search-and-geocode-tool/SearchAndGeocodeTool.d.ts.map +1 -1
  23. package/dist/commonjs/tools/search-and-geocode-tool/SearchAndGeocodeTool.js +2 -0
  24. package/dist/commonjs/tools/search-and-geocode-tool/SearchAndGeocodeTool.js.map +1 -1
  25. package/dist/commonjs/tools/static-map-image-tool/StaticMapImageTool.d.ts.map +1 -1
  26. package/dist/commonjs/tools/static-map-image-tool/StaticMapImageTool.input.schema.d.ts +3 -3
  27. package/dist/commonjs/tools/static-map-image-tool/StaticMapImageTool.input.schema.d.ts.map +1 -1
  28. package/dist/commonjs/tools/static-map-image-tool/StaticMapImageTool.input.schema.js +16 -2
  29. package/dist/commonjs/tools/static-map-image-tool/StaticMapImageTool.input.schema.js.map +1 -1
  30. package/dist/commonjs/tools/static-map-image-tool/StaticMapImageTool.js +15 -4
  31. package/dist/commonjs/tools/static-map-image-tool/StaticMapImageTool.js.map +1 -1
  32. package/dist/commonjs/utils/index.d.ts +2 -0
  33. package/dist/commonjs/utils/index.d.ts.map +1 -1
  34. package/dist/commonjs/utils/index.js +8 -1
  35. package/dist/commonjs/utils/index.js.map +1 -1
  36. package/dist/commonjs/utils/redactToken.d.ts +3 -0
  37. package/dist/commonjs/utils/redactToken.d.ts.map +1 -0
  38. package/dist/commonjs/utils/redactToken.js +55 -0
  39. package/dist/commonjs/utils/redactToken.js.map +1 -0
  40. package/dist/commonjs/utils/redactingSpanExporter.d.ts +24 -0
  41. package/dist/commonjs/utils/redactingSpanExporter.d.ts.map +1 -0
  42. package/dist/commonjs/utils/redactingSpanExporter.js +97 -0
  43. package/dist/commonjs/utils/redactingSpanExporter.js.map +1 -0
  44. package/dist/commonjs/utils/tracing.d.ts.map +1 -1
  45. package/dist/commonjs/utils/tracing.js +4 -1
  46. package/dist/commonjs/utils/tracing.js.map +1 -1
  47. package/dist/commonjs/utils/urlSafety.d.ts +23 -7
  48. package/dist/commonjs/utils/urlSafety.d.ts.map +1 -1
  49. package/dist/commonjs/utils/urlSafety.js +84 -66
  50. package/dist/commonjs/utils/urlSafety.js.map +1 -1
  51. package/dist/commonjs/version.json +3 -3
  52. package/dist/esm/cli.d.ts.map +1 -1
  53. package/dist/esm/cli.js +5 -2
  54. package/dist/esm/cli.js.map +1 -1
  55. package/dist/esm/resources/resourceRegistry.d.ts +1 -2
  56. package/dist/esm/resources/resourceRegistry.d.ts.map +1 -1
  57. package/dist/esm/resources/resourceRegistry.js +0 -2
  58. package/dist/esm/resources/resourceRegistry.js.map +1 -1
  59. package/dist/esm/resources/ui-apps/mapAppHtml.d.ts +3 -3
  60. package/dist/esm/resources/ui-apps/mapAppHtml.d.ts.map +1 -1
  61. package/dist/esm/resources/ui-apps/mapAppHtml.js +18 -4
  62. package/dist/esm/resources/ui-apps/mapAppHtml.js.map +1 -1
  63. package/dist/esm/tools/directions-tool/DirectionsTool.d.ts +16 -0
  64. package/dist/esm/tools/directions-tool/DirectionsTool.d.ts.map +1 -1
  65. package/dist/esm/tools/directions-tool/DirectionsTool.js +105 -1
  66. package/dist/esm/tools/directions-tool/DirectionsTool.js.map +1 -1
  67. package/dist/esm/tools/place-details-tool/PlaceDetailsTool.d.ts.map +1 -1
  68. package/dist/esm/tools/place-details-tool/PlaceDetailsTool.input.schema.js +1 -1
  69. package/dist/esm/tools/place-details-tool/PlaceDetailsTool.input.schema.js.map +1 -1
  70. package/dist/esm/tools/place-details-tool/PlaceDetailsTool.js +7 -3
  71. package/dist/esm/tools/place-details-tool/PlaceDetailsTool.js.map +1 -1
  72. package/dist/esm/tools/search-and-geocode-tool/SearchAndGeocodeTool.d.ts.map +1 -1
  73. package/dist/esm/tools/search-and-geocode-tool/SearchAndGeocodeTool.js +2 -0
  74. package/dist/esm/tools/search-and-geocode-tool/SearchAndGeocodeTool.js.map +1 -1
  75. package/dist/esm/tools/static-map-image-tool/StaticMapImageTool.d.ts.map +1 -1
  76. package/dist/esm/tools/static-map-image-tool/StaticMapImageTool.input.schema.d.ts +3 -3
  77. package/dist/esm/tools/static-map-image-tool/StaticMapImageTool.input.schema.d.ts.map +1 -1
  78. package/dist/esm/tools/static-map-image-tool/StaticMapImageTool.input.schema.js +17 -3
  79. package/dist/esm/tools/static-map-image-tool/StaticMapImageTool.input.schema.js.map +1 -1
  80. package/dist/esm/tools/static-map-image-tool/StaticMapImageTool.js +15 -4
  81. package/dist/esm/tools/static-map-image-tool/StaticMapImageTool.js.map +1 -1
  82. package/dist/esm/utils/index.d.ts +2 -0
  83. package/dist/esm/utils/index.d.ts.map +1 -1
  84. package/dist/esm/utils/index.js +5 -0
  85. package/dist/esm/utils/index.js.map +1 -1
  86. package/dist/esm/utils/redactToken.d.ts +3 -0
  87. package/dist/esm/utils/redactToken.d.ts.map +1 -0
  88. package/dist/esm/utils/redactToken.js +52 -0
  89. package/dist/esm/utils/redactToken.js.map +1 -0
  90. package/dist/esm/utils/redactingSpanExporter.d.ts +24 -0
  91. package/dist/esm/utils/redactingSpanExporter.d.ts.map +1 -0
  92. package/dist/esm/utils/redactingSpanExporter.js +93 -0
  93. package/dist/esm/utils/redactingSpanExporter.js.map +1 -0
  94. package/dist/esm/utils/tracing.d.ts.map +1 -1
  95. package/dist/esm/utils/tracing.js +4 -1
  96. package/dist/esm/utils/tracing.js.map +1 -1
  97. package/dist/esm/utils/urlSafety.d.ts +23 -7
  98. package/dist/esm/utils/urlSafety.d.ts.map +1 -1
  99. package/dist/esm/utils/urlSafety.js +80 -66
  100. package/dist/esm/utils/urlSafety.js.map +1 -1
  101. package/dist/esm/version.json +3 -3
  102. package/package.json +2 -1
  103. package/dist/commonjs/resources/ui-apps/StaticMapUIResource.d.ts +0 -15
  104. package/dist/commonjs/resources/ui-apps/StaticMapUIResource.d.ts.map +0 -1
  105. package/dist/commonjs/resources/ui-apps/StaticMapUIResource.js +0 -262
  106. package/dist/commonjs/resources/ui-apps/StaticMapUIResource.js.map +0 -1
  107. package/dist/esm/resources/ui-apps/StaticMapUIResource.d.ts +0 -15
  108. package/dist/esm/resources/ui-apps/StaticMapUIResource.d.ts.map +0 -1
  109. package/dist/esm/resources/ui-apps/StaticMapUIResource.js +0 -258
  110. package/dist/esm/resources/ui-apps/StaticMapUIResource.js.map +0 -1
@@ -6,14 +6,30 @@
6
6
  * Rejects:
7
7
  * - non-http(s) schemes (e.g. file:, gopher:, data:, javascript:)
8
8
  * - non-https URLs (markers should always be fetched over TLS)
9
- * - URLs whose host is an IP literal in a loopback, private, link-local,
10
- * unique-local, or otherwise non-routable range (CWE-918 SSRF)
11
- * - URLs whose host is a well-known local hostname
9
+ * - IPv4/IPv6 literals outside ipaddr.js's plain "unicast" range —
10
+ * deny-by-default, so loopback, private, link-local, multicast,
11
+ * broadcast, CGNAT, reserved, and every IPv4-in-IPv6 transition/
12
+ * translation mechanism (mapped, compatible, 6to4, NAT64, SIIT, Teredo,
13
+ * AMT, ORCHID, etc.) are all rejected without needing to be named
14
+ * individually (CWE-918 SSRF)
15
+ * - well-known local hostnames, reserved local/internal-use suffixes
16
+ * (.internal, .local, .arpa), and dotless single-label hostnames
12
17
  *
13
- * Note: we do not perform DNS resolution here — the upstream service will
14
- * still resolve the hostname when fetching. This validation is a defense in
15
- * depth against the most common SSRF vectors that prompt-injected agents
16
- * tend to produce (IP literals and "localhost").
18
+ * Out of scope, by design, for this pre-fetch string check — all three
19
+ * require validating the actual connection, not the URL string, so they
20
+ * belong where the fetch happens, not here:
21
+ * - DNS rebinding (an ordinary hostname resolving to an internal address
22
+ * at fetch time)
23
+ * - port restriction
24
+ * - network-specific hostname suffixes (.corp, .lan, .home, etc.) —
25
+ * unlike .internal/.local/.arpa, these aren't globally reserved, so
26
+ * they can't be enumerated in general
17
27
  */
18
28
  export declare function isSafeExternalUrl(rawUrl: string): boolean;
29
+ /**
30
+ * Same validation as isSafeExternalUrl, but returns the parsed URL on
31
+ * success (null otherwise) so callers that need the WHATWG-canonical form
32
+ * of the validated URL don't have to re-parse the raw string.
33
+ */
34
+ export declare function parseSafeExternalUrl(rawUrl: string): URL | null;
19
35
  //# sourceMappingURL=urlSafety.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"urlSafety.d.ts","sourceRoot":"","sources":["../../../src/utils/urlSafety.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CA0EzD"}
1
+ {"version":3,"file":"urlSafety.d.ts","sourceRoot":"","sources":["../../../src/utils/urlSafety.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAoF/D"}
@@ -1,8 +1,13 @@
1
1
  "use strict";
2
2
  // Copyright (c) Mapbox, Inc.
3
3
  // Licensed under the MIT License.
4
+ var __importDefault = (this && this.__importDefault) || function (mod) {
5
+ return (mod && mod.__esModule) ? mod : { "default": mod };
6
+ };
4
7
  Object.defineProperty(exports, "__esModule", { value: true });
5
8
  exports.isSafeExternalUrl = isSafeExternalUrl;
9
+ exports.parseSafeExternalUrl = parseSafeExternalUrl;
10
+ const ipaddr_js_1 = __importDefault(require("ipaddr.js"));
6
11
  /**
7
12
  * Validates that a URL is safe for server-side fetching by an upstream service
8
13
  * (in particular, the Mapbox Static Images API which fetches custom marker
@@ -11,30 +16,55 @@ exports.isSafeExternalUrl = isSafeExternalUrl;
11
16
  * Rejects:
12
17
  * - non-http(s) schemes (e.g. file:, gopher:, data:, javascript:)
13
18
  * - non-https URLs (markers should always be fetched over TLS)
14
- * - URLs whose host is an IP literal in a loopback, private, link-local,
15
- * unique-local, or otherwise non-routable range (CWE-918 SSRF)
16
- * - URLs whose host is a well-known local hostname
19
+ * - IPv4/IPv6 literals outside ipaddr.js's plain "unicast" range —
20
+ * deny-by-default, so loopback, private, link-local, multicast,
21
+ * broadcast, CGNAT, reserved, and every IPv4-in-IPv6 transition/
22
+ * translation mechanism (mapped, compatible, 6to4, NAT64, SIIT, Teredo,
23
+ * AMT, ORCHID, etc.) are all rejected without needing to be named
24
+ * individually (CWE-918 SSRF)
25
+ * - well-known local hostnames, reserved local/internal-use suffixes
26
+ * (.internal, .local, .arpa), and dotless single-label hostnames
17
27
  *
18
- * Note: we do not perform DNS resolution here — the upstream service will
19
- * still resolve the hostname when fetching. This validation is a defense in
20
- * depth against the most common SSRF vectors that prompt-injected agents
21
- * tend to produce (IP literals and "localhost").
28
+ * Out of scope, by design, for this pre-fetch string check — all three
29
+ * require validating the actual connection, not the URL string, so they
30
+ * belong where the fetch happens, not here:
31
+ * - DNS rebinding (an ordinary hostname resolving to an internal address
32
+ * at fetch time)
33
+ * - port restriction
34
+ * - network-specific hostname suffixes (.corp, .lan, .home, etc.) —
35
+ * unlike .internal/.local/.arpa, these aren't globally reserved, so
36
+ * they can't be enumerated in general
22
37
  */
23
38
  function isSafeExternalUrl(rawUrl) {
39
+ return parseSafeExternalUrl(rawUrl) !== null;
40
+ }
41
+ /**
42
+ * Same validation as isSafeExternalUrl, but returns the parsed URL on
43
+ * success (null otherwise) so callers that need the WHATWG-canonical form
44
+ * of the validated URL don't have to re-parse the raw string.
45
+ */
46
+ function parseSafeExternalUrl(rawUrl) {
24
47
  let parsed;
25
48
  try {
26
49
  parsed = new URL(rawUrl);
27
50
  }
28
51
  catch {
29
- return false;
52
+ return null;
30
53
  }
31
54
  if (parsed.protocol !== 'https:') {
32
- return false;
55
+ return null;
33
56
  }
34
- // Strip optional surrounding brackets from IPv6 literals
35
- const host = parsed.hostname.replace(/^\[|\]$/g, '').toLowerCase();
57
+ // Strip optional surrounding brackets from IPv6 literals and a trailing
58
+ // root-label dot (e.g. "localhost." is equivalent to "localhost"). The
59
+ // dotless-hostname check further below relies on this running first —
60
+ // without it, "intranet." would still contain a dot and slip past that
61
+ // check.
62
+ const host = parsed.hostname
63
+ .replace(/^\[|\]$/g, '')
64
+ .replace(/\.$/, '')
65
+ .toLowerCase();
36
66
  if (host.length === 0) {
37
- return false;
67
+ return null;
38
68
  }
39
69
  // Block well-known local hostnames
40
70
  const blockedHostnames = new Set([
@@ -43,62 +73,50 @@ function isSafeExternalUrl(rawUrl) {
43
73
  'ip6-loopback',
44
74
  'broadcasthost'
45
75
  ]);
46
- if (blockedHostnames.has(host) || host.endsWith('.localhost')) {
47
- return false;
76
+ // Suffixes reserved for local/internal use that no public marker image
77
+ // host is ever legitimately under: cloud-internal DNS zones (.internal,
78
+ // used by GCP/AWS service discovery — covers metadata.google.internal,
79
+ // the GCP metadata endpoint's actual hostname), mDNS (.local), and
80
+ // reverse-DNS / home-network zones reserved by RFC 6761/8375 (.arpa
81
+ // covers .in-addr.arpa, .ip6.arpa, and .home.arpa as suffixes of it).
82
+ const blockedSuffixes = ['.localhost', '.internal', '.local', '.arpa'];
83
+ if (blockedHostnames.has(host) ||
84
+ blockedSuffixes.some((suffix) => host.endsWith(suffix))) {
85
+ return null;
48
86
  }
49
- // IPv4 literal check (dotted quad)
50
- const ipv4Match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(host);
51
- if (ipv4Match) {
52
- const octets = ipv4Match.slice(1, 5).map((o) => Number(o));
53
- if (octets.some((o) => o < 0 || o > 255)) {
54
- return false;
55
- }
56
- const [a, b] = octets;
57
- // 0.0.0.0/8, 10/8, 127/8
58
- // 0.0.0.0/8 — "this network" (unspecified + reserved); block conservatively
59
- if (a === 0 || a === 10 || a === 127)
60
- return false;
61
- // 169.254/16 (link-local, includes cloud metadata 169.254.169.254)
62
- if (a === 169 && b === 254)
63
- return false;
64
- // 172.16/12
65
- if (a === 172 && b >= 16 && b <= 31)
66
- return false;
67
- // 192.168/16
68
- if (a === 192 && b === 168)
69
- return false;
70
- // 100.64/10 (CGNAT)
71
- if (a === 100 && b >= 64 && b <= 127)
72
- return false;
73
- // 224/4 multicast and 240/4 reserved
74
- if (a >= 224)
75
- return false;
76
- return true;
87
+ // If the host isn't a parseable IP literal at all, it's an ordinary
88
+ // hostname — allowed here (subject to the checks above), except that a
89
+ // public marker image host always has at least one dot; a dotless,
90
+ // single-label hostname only resolves via the fetcher's own network
91
+ // search-domain suffixing (e.g. "intranet", "metadata"), which is never
92
+ // the case for a legitimate external image URL. DNS rebinding on a
93
+ // multi-label hostname is out of scope for this pre-fetch check, see the
94
+ // module doc comment.
95
+ if (!ipaddr_js_1.default.isValid(host)) {
96
+ return host.includes('.') ? parsed : null;
97
+ }
98
+ const addr = ipaddr_js_1.default.parse(host);
99
+ // Deny by default for both IPv4 and IPv6: only plain global unicast
100
+ // addresses are allowed. Every other named range (private, loopback,
101
+ // link-local, multicast, broadcast, CGNAT, reserved, unique-local, and
102
+ // every IPv4-in-IPv6 transition/translation mechanism) is rejected,
103
+ // regardless of what it does or doesn't embed.
104
+ if (addr.range() !== 'unicast') {
105
+ return null;
77
106
  }
78
- // IPv6 literal check (presence of ':' indicates IPv6 since IPv4 was handled)
79
- if (host.includes(':')) {
80
- // ::1 loopback, :: unspecified
81
- if (host === '::1' || host === '::')
82
- return false;
83
- // fc00::/7 unique local (fc.. or fd..)
84
- if (/^f[cd][0-9a-f]{2}:/.test(host))
85
- return false;
86
- // fe80::/10 link-local
87
- if (/^fe[89ab][0-9a-f]:/.test(host))
88
- return false;
89
- // ff00::/8 multicast
90
- if (/^ff[0-9a-f]{2}:/.test(host))
91
- return false;
92
- // IPv4-mapped / IPv4-compatible IPv6: ::ffff:a.b.c.d or ::a.b.c.d
93
- // (Node's URL parser normalises ::ffff:127.0.0.1 to ::ffff:7f00:1, so
94
- // detect the embedded IPv4 either as a dotted-quad or as the
95
- // ::ffff:xxxx:xxxx hex form.)
96
- if (/\d+\.\d+\.\d+\.\d+/.test(host))
97
- return false;
98
- if (/^::ffff:[0-9a-f]{1,4}:[0-9a-f]{1,4}$/.test(host))
99
- return false;
100
- return true;
107
+ if (addr.kind() === 'ipv6') {
108
+ // ipaddr.js does not classify the deprecated IPv4-compatible form
109
+ // (::a.b.c.d, i.e. the leading 96 bits all zero) as a special range
110
+ // when written in plain hex, which is exactly the form Node's URL
111
+ // parser normalises a dotted-quad IPv4-compatible literal to — so it
112
+ // reaches here as ordinary 'unicast' and needs an explicit check.
113
+ // (::1 and :: are already excluded above via the loopback/unspecified
114
+ // ranges, so this only affects addresses with a genuine embedded IPv4.)
115
+ const bytes = addr.toByteArray();
116
+ if (bytes.slice(0, 12).every((b) => b === 0)) {
117
+ return null;
118
+ }
101
119
  }
102
- return true;
120
+ return parsed;
103
121
  }
104
122
  //# sourceMappingURL=urlSafety.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"urlSafety.js","sourceRoot":"","sources":["../../../src/utils/urlSafety.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"urlSafety.js","sourceRoot":"","sources":["../../../src/utils/urlSafety.ts"],"names":[],"mappings":";AAAA,6BAA6B;AAC7B,kCAAkC;;;;;AAgClC,8CAEC;AAOD,oDAoFC;AA3HD,0DAA+B;AAE/B;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,SAAgB,iBAAiB,CAAC,MAAc;IAC9C,OAAO,oBAAoB,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;AAC/C,CAAC;AAED;;;;GAIG;AACH,SAAgB,oBAAoB,CAAC,MAAc;IACjD,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,wEAAwE;IACxE,uEAAuE;IACvE,sEAAsE;IACtE,uEAAuE;IACvE,SAAS;IACT,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ;SACzB,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;SAClB,WAAW,EAAE,CAAC;IAEjB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mCAAmC;IACnC,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;QAC/B,WAAW;QACX,eAAe;QACf,cAAc;QACd,eAAe;KAChB,CAAC,CAAC;IACH,uEAAuE;IACvE,wEAAwE;IACxE,uEAAuE;IACvE,mEAAmE;IACnE,oEAAoE;IACpE,sEAAsE;IACtE,MAAM,eAAe,GAAG,CAAC,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACvE,IACE,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC;QAC1B,eAAe,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EACvD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oEAAoE;IACpE,uEAAuE;IACvE,mEAAmE;IACnE,oEAAoE;IACpE,wEAAwE;IACxE,mEAAmE;IACnE,yEAAyE;IACzE,sBAAsB;IACtB,IAAI,CAAC,mBAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5C,CAAC;IACD,MAAM,IAAI,GAAG,mBAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEhC,oEAAoE;IACpE,qEAAqE;IACrE,uEAAuE;IACvE,oEAAoE;IACpE,+CAA+C;IAC/C,IAAI,IAAI,CAAC,KAAK,EAAE,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC;QAC3B,kEAAkE;QAClE,oEAAoE;QACpE,kEAAkE;QAClE,qEAAqE;QACrE,kEAAkE;QAClE,sEAAsE;QACtE,wEAAwE;QACxE,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACjC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAC7C,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -1,6 +1,6 @@
1
1
  {
2
- "sha": "88ba37c5e1013138c5baea75c8db90e8ae8731b1",
3
- "tag": "v0.12.7-4-g88ba37c",
2
+ "sha": "8d26d7636a30dd0355db18bb2c64f3bc7112b41c",
3
+ "tag": "v0.13.0-6-g8d26d76",
4
4
  "branch": "HEAD",
5
- "version": "0.13.0"
5
+ "version": "0.14.0"
6
6
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAGA,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,iBAAiB;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAiCD,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EAAE,EACd,WAAW,EAAE,cAAc,GAC1B,iBAAiB,CAsCnB"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAGA,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,iBAAiB;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAoCD,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EAAE,EACd,WAAW,EAAE,cAAc,GAC1B,iBAAiB,CAsCnB"}
package/dist/esm/cli.js CHANGED
@@ -4,10 +4,13 @@ const OPTIONS = [
4
4
  '--help, -h Show this help message',
5
5
  '--version, -v Show the server version',
6
6
  '--enable-tools Enable only the comma-separated tools',
7
- '--disable-tools Disable the comma-separated tools',
8
- '--disable-mcp-ui Disable MCP-UI resources'
7
+ '--disable-tools Disable the comma-separated tools'
9
8
  ];
10
9
  const OPTIONS_WITH_VALUES = new Set(['--enable-tools', '--disable-tools']);
10
+ // --disable-mcp-ui is no longer a real option (MCP-UI support was removed
11
+ // entirely — see docs/mcp-ui.md) but stays recognized-and-ignored here, not
12
+ // in OPTIONS, so an existing launch config that still passes it keeps
13
+ // starting instead of hard-failing on "Unknown option".
11
14
  const KNOWN_FLAGS = new Set([
12
15
  '--help',
13
16
  '-h',
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,kCAAkC;AAclC,MAAM,OAAO,GAAG;IACd,6CAA6C;IAC7C,8CAA8C;IAC9C,4DAA4D;IAC5D,wDAAwD;IACxD,+CAA+C;CAChD,CAAC;AAEF,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,gBAAgB,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAC3E,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC1B,QAAQ;IACR,IAAI;IACJ,WAAW;IACX,IAAI;IACJ,gBAAgB;IAChB,iBAAiB;IACjB,kBAAkB;CACnB,CAAC,CAAC;AAEH,SAAS,UAAU,CAAC,WAA2B;IAC7C,OAAO;QACL,GAAG,WAAW,CAAC,IAAI,IAAI,WAAW,CAAC,OAAO,EAAE;QAC5C,EAAE;QACF,6BAA6B;QAC7B,EAAE;QACF,UAAU;QACV,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,MAAM,EAAE,CAAC;QACzC,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,IAAc,EACd,WAA2B;IAE3B,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC;SAChC,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACtD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,GAAG,WAAW,CAAC,OAAO,IAAI;SACnC,CAAC;IACJ,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEpB,IAAI,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACjC,CAAC,EAAE,CAAC;YACJ,SAAS;QACX,CAAC;QAED,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACjD,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,CAAC;gBACX,KAAK,EAAE,mBAAmB,GAAG,IAAI;aAClC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,KAAK;QACd,QAAQ,EAAE,CAAC;KACZ,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,kCAAkC;AAclC,MAAM,OAAO,GAAG;IACd,6CAA6C;IAC7C,8CAA8C;IAC9C,4DAA4D;IAC5D,wDAAwD;CACzD,CAAC;AAEF,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,gBAAgB,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAC3E,0EAA0E;AAC1E,4EAA4E;AAC5E,sEAAsE;AACtE,wDAAwD;AACxD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC1B,QAAQ;IACR,IAAI;IACJ,WAAW;IACX,IAAI;IACJ,gBAAgB;IAChB,iBAAiB;IACjB,kBAAkB;CACnB,CAAC,CAAC;AAEH,SAAS,UAAU,CAAC,WAA2B;IAC7C,OAAO;QACL,GAAG,WAAW,CAAC,IAAI,IAAI,WAAW,CAAC,OAAO,EAAE;QAC5C,EAAE;QACF,6BAA6B;QAC7B,EAAE;QACF,UAAU;QACV,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,MAAM,EAAE,CAAC;QACzC,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,IAAc,EACd,WAA2B;IAE3B,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC;SAChC,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACtD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,GAAG,WAAW,CAAC,OAAO,IAAI;SACnC,CAAC;IACJ,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEpB,IAAI,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACjC,CAAC,EAAE,CAAC;YACJ,SAAS;QACX,CAAC;QAED,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACjD,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,CAAC;gBACX,KAAK,EAAE,mBAAmB,GAAG,IAAI;aAClC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,KAAK;QACd,QAAQ,EAAE,CAAC;KACZ,CAAC;AACJ,CAAC"}
@@ -2,10 +2,9 @@ import { CategoryListResource } from './category-list/CategoryListResource.js';
2
2
  import { TemporaryDataResource } from './temporary/TemporaryDataResource.js';
3
3
  import { ComputeResource } from './compute/ComputeResource.js';
4
4
  import { InlinePayloadResource } from './inline-payload/InlinePayloadResource.js';
5
- import { StaticMapUIResource } from './ui-apps/StaticMapUIResource.js';
6
5
  import { MapAppUIResource } from './ui-apps/MapAppUIResource.js';
7
6
  import { VersionResource } from './version/VersionResource.js';
8
- export declare const ALL_RESOURCES: readonly [CategoryListResource, TemporaryDataResource, ComputeResource, InlinePayloadResource, StaticMapUIResource, MapAppUIResource, VersionResource];
7
+ export declare const ALL_RESOURCES: readonly [CategoryListResource, TemporaryDataResource, ComputeResource, InlinePayloadResource, MapAppUIResource, VersionResource];
9
8
  export type ResourceInstance = (typeof ALL_RESOURCES)[number];
10
9
  export declare function getAllResources(): readonly ResourceInstance[];
11
10
  export declare function getResourceByUri(uri: string): ResourceInstance | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"resourceRegistry.d.ts","sourceRoot":"","sources":["../../../src/resources/resourceRegistry.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2CAA2C,CAAC;AAClF,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAI/D,eAAO,MAAM,aAAa,wJAUhB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D,wBAAgB,eAAe,IAAI,SAAS,gBAAgB,EAAE,CAE7D;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAkB1E"}
1
+ {"version":3,"file":"resourceRegistry.d.ts","sourceRoot":"","sources":["../../../src/resources/resourceRegistry.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2CAA2C,CAAC;AAClF,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAI/D,eAAO,MAAM,aAAa,mIAShB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D,wBAAgB,eAAe,IAAI,SAAS,gBAAgB,EAAE,CAE7D;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAkB1E"}
@@ -5,7 +5,6 @@ import { CategoryListResource } from './category-list/CategoryListResource.js';
5
5
  import { TemporaryDataResource } from './temporary/TemporaryDataResource.js';
6
6
  import { ComputeResource } from './compute/ComputeResource.js';
7
7
  import { InlinePayloadResource } from './inline-payload/InlinePayloadResource.js';
8
- import { StaticMapUIResource } from './ui-apps/StaticMapUIResource.js';
9
8
  import { MapAppUIResource } from './ui-apps/MapAppUIResource.js';
10
9
  import { VersionResource } from './version/VersionResource.js';
11
10
  import { httpRequest } from '../utils/httpPipeline.js';
@@ -16,7 +15,6 @@ export const ALL_RESOURCES = [
16
15
  new TemporaryDataResource(),
17
16
  new ComputeResource(),
18
17
  new InlinePayloadResource(),
19
- new StaticMapUIResource(),
20
18
  // Single shared map renderer, targeted exclusively by render_map_tool.
21
19
  new MapAppUIResource({ httpRequest }),
22
20
  new VersionResource()
@@ -1 +1 @@
1
- {"version":3,"file":"resourceRegistry.js","sourceRoot":"","sources":["../../../src/resources/resourceRegistry.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,kCAAkC;AAElC,kCAAkC;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2CAA2C,CAAC;AAClF,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,oCAAoC;AACpC,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,oCAAoC;IACpC,IAAI,oBAAoB,CAAC,EAAE,WAAW,EAAE,CAAC;IACzC,IAAI,qBAAqB,EAAE;IAC3B,IAAI,eAAe,EAAE;IACrB,IAAI,qBAAqB,EAAE;IAC3B,IAAI,mBAAmB,EAAE;IACzB,uEAAuE;IACvE,IAAI,gBAAgB,CAAC,EAAE,WAAW,EAAE,CAAC;IACrC,IAAI,eAAe,EAAE;CACb,CAAC;AAIX,MAAM,UAAU,eAAe;IAC7B,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,yBAAyB;IACzB,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;IAC1E,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC;IAElC,gFAAgF;IAChF,6EAA6E;IAC7E,wEAAwE;IACxE,0EAA0E;IAC1E,iEAAiE;IACjE,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;QACrC,MAAM,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,UAAU,GACd,aAAa,KAAK,CAAC,CAAC;YAClB,CAAC,CAAC,QAAQ,CAAC,GAAG;YACd,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;QAC3C,OAAO,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"resourceRegistry.js","sourceRoot":"","sources":["../../../src/resources/resourceRegistry.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,kCAAkC;AAElC,kCAAkC;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2CAA2C,CAAC;AAClF,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,oCAAoC;AACpC,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,oCAAoC;IACpC,IAAI,oBAAoB,CAAC,EAAE,WAAW,EAAE,CAAC;IACzC,IAAI,qBAAqB,EAAE;IAC3B,IAAI,eAAe,EAAE;IACrB,IAAI,qBAAqB,EAAE;IAC3B,uEAAuE;IACvE,IAAI,gBAAgB,CAAC,EAAE,WAAW,EAAE,CAAC;IACrC,IAAI,eAAe,EAAE;CACb,CAAC;AAIX,MAAM,UAAU,eAAe;IAC7B,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,yBAAyB;IACzB,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;IAC1E,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC;IAElC,gFAAgF;IAChF,6EAA6E;IAC7E,wEAAwE;IACxE,0EAA0E;IAC1E,iEAAiE;IACjE,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;QACrC,MAAM,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,UAAU,GACd,aAAa,KAAK,CAAC,CAAC;YAClB,CAAC,CAAC,QAAQ,CAAC,GAAG;YACd,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;QAC3C,OAAO,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1,8 +1,8 @@
1
1
  import type { MapAppPayload } from '../../utils/mapAppPayload.js';
2
2
  /**
3
- * Render the generic Mapbox MCP App HTML — used by both the MCP Apps
4
- * resource (postMessage delivery) and any tool's inline MCP-UI rawHtml
5
- * block (initial-data baked in).
3
+ * Render the generic Mapbox MCP App HTML — served by the MCP Apps resource
4
+ * (`MapAppUIResource`) that `render_map_tool` targets exclusively via
5
+ * postMessage delivery.
6
6
  *
7
7
  * The iframe is a thin renderer over Mapbox GL JS. Tools produce a
8
8
  * `MapAppPayload` (see src/utils/mapAppPayload.ts) and the iframe
@@ -1 +1 @@
1
- {"version":3,"file":"mapAppHtml.d.ts","sourceRoot":"","sources":["../../../../src/resources/ui-apps/mapAppHtml.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE;;;;;;;;;GASG;AAMH,eAAO,MAAM,iBAAiB,WAAW,CAAC;AAE1C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,aAAa,CAAC;CAC7B,GAAG,MAAM,CA+jDT"}
1
+ {"version":3,"file":"mapAppHtml.d.ts","sourceRoot":"","sources":["../../../../src/resources/ui-apps/mapAppHtml.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE;;;;;;;;;GASG;AAMH,eAAO,MAAM,iBAAiB,WAAW,CAAC;AAE1C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,aAAa,CAAC;CAC7B,GAAG,MAAM,CA6kDT"}
@@ -1,9 +1,9 @@
1
1
  // Copyright (c) Mapbox, Inc.
2
2
  // Licensed under the MIT License.
3
3
  /**
4
- * Render the generic Mapbox MCP App HTML — used by both the MCP Apps
5
- * resource (postMessage delivery) and any tool's inline MCP-UI rawHtml
6
- * block (initial-data baked in).
4
+ * Render the generic Mapbox MCP App HTML — served by the MCP Apps resource
5
+ * (`MapAppUIResource`) that `render_map_tool` targets exclusively via
6
+ * postMessage delivery.
7
7
  *
8
8
  * The iframe is a thin renderer over Mapbox GL JS. Tools produce a
9
9
  * `MapAppPayload` (see src/utils/mapAppPayload.ts) and the iframe
@@ -622,6 +622,11 @@ ${initialDataScript}
622
622
  if (typeof params.exclude !== 'string') return false;
623
623
  if (!/^[A-Za-z0-9_,.() -]+$/.test(params.exclude)) return false;
624
624
  }
625
+ if (params.selectedRouteIndex !== undefined && params.selectedRouteIndex !== null) {
626
+ if (typeof params.selectedRouteIndex !== 'number') return false;
627
+ if (!isFinite(params.selectedRouteIndex) || params.selectedRouteIndex < 0) return false;
628
+ if (Math.floor(params.selectedRouteIndex) !== params.selectedRouteIndex) return false;
629
+ }
625
630
  return true;
626
631
  }
627
632
 
@@ -743,7 +748,16 @@ ${initialDataScript}
743
748
  return res.json();
744
749
  })
745
750
  .then(function(data) {
746
- var route = data && data.routes && data.routes[0];
751
+ var routes = (data && data.routes) || [];
752
+ // If elicitation resolved to a specific route server-side, draw that
753
+ // same one out of the freshly re-fetched alternatives — falling back
754
+ // to the first route if the index is out of range (e.g. the API
755
+ // returned fewer alternatives this time around), same fallback
756
+ // philosophy as selectedMapboxId in the search self-fetch.
757
+ var route =
758
+ (typeof params.selectedRouteIndex === 'number' &&
759
+ routes[params.selectedRouteIndex]) ||
760
+ routes[0];
747
761
  var coords = route ? pickRouteGeometryClient(route) : null;
748
762
  if (!coords) {
749
763
  showError('Directions API returned no route.');
@@ -1 +1 @@
1
- {"version":3,"file":"mapAppHtml.js","sourceRoot":"","sources":["../../../../src/resources/ui-apps/mapAppHtml.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mapAppHtml.js","sourceRoot":"","sources":["../../../../src/resources/ui-apps/mapAppHtml.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,22 @@ export declare class DirectionsTool extends MapboxApiBasedTool<typeof Directions
17
17
  constructor(params: {
18
18
  httpRequest: HttpRequest;
19
19
  });
20
+ private formatDuration;
21
+ private formatDistance;
22
+ /** One-line label for a route option in the Stage 2 elicitation form. */
23
+ private describeRoute;
24
+ /**
25
+ * When multiple route alternatives come back, let the user pick one via
26
+ * MCP elicitation rather than handing all of them to the model. Returns
27
+ * the selected route's index (to thread through the self-fetch ref so the
28
+ * map preview draws the same route) and mutates nothing — the caller
29
+ * applies the filtered `routes` array itself.
30
+ *
31
+ * Mirrors search_and_geocode_tool's disambiguation elicitation: silent,
32
+ * best-effort fallback to "return everything" on decline, on an
33
+ * unsupported client, or on any elicitation error.
34
+ */
35
+ private elicitRouteSelection;
20
36
  protected execute(input: z.infer<typeof DirectionsInputSchema>, accessToken: string): Promise<CallToolResult>;
21
37
  }
22
38
  //# sourceMappingURL=DirectionsTool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DirectionsTool.d.ts","sourceRoot":"","sources":["../../../../src/tools/directions-tool/DirectionsTool.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAGzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EACL,wBAAwB,EAEzB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAQzD,qBAAa,cAAe,SAAQ,kBAAkB,CACpD,OAAO,qBAAqB,EAC5B,OAAO,wBAAwB,CAChC;IACC,IAAI,SAAqB;IACzB,WAAW,SAMkE;IAC7E,WAAW;;;;;;MAMT;gBACU,MAAM,EAAE;QAAE,WAAW,EAAE,WAAW,CAAA;KAAE;cAOhC,OAAO,CACrB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,EAC5C,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,cAAc,CAAC;CA4Q3B"}
1
+ {"version":3,"file":"DirectionsTool.d.ts","sourceRoot":"","sources":["../../../../src/tools/directions-tool/DirectionsTool.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAGzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EACL,wBAAwB,EAGzB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAQzD,qBAAa,cAAe,SAAQ,kBAAkB,CACpD,OAAO,qBAAqB,EAC5B,OAAO,wBAAwB,CAChC;IACC,IAAI,SAAqB;IACzB,WAAW,SAMkE;IAC7E,WAAW;;;;;;MAMT;gBACU,MAAM,EAAE;QAAE,WAAW,EAAE,WAAW,CAAA;KAAE;IAQhD,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,cAAc;IAMtB,yEAAyE;IACzE,OAAO,CAAC,aAAa;IA6BrB;;;;;;;;;;OAUG;YACW,oBAAoB;cA6ClB,OAAO,CACrB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,EAC5C,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,cAAc,CAAC;CAkS3B"}
@@ -33,6 +33,91 @@ export class DirectionsTool extends MapboxApiBasedTool {
33
33
  httpRequest: params.httpRequest
34
34
  });
35
35
  }
36
+ formatDuration(seconds) {
37
+ const hours = Math.floor(seconds / 3600);
38
+ const minutes = Math.round((seconds % 3600) / 60);
39
+ return hours > 0 ? `${hours}h ${minutes}min` : `${minutes}min`;
40
+ }
41
+ formatDistance(meters) {
42
+ const km = (meters / 1000).toFixed(1);
43
+ const miles = (meters / 1609.34).toFixed(1);
44
+ return `${km}km (${miles}mi)`;
45
+ }
46
+ /** One-line label for a route option in the Stage 2 elicitation form. */
47
+ describeRoute(route) {
48
+ const duration = this.formatDuration(route.duration);
49
+ const distance = this.formatDistance(route.distance);
50
+ const roads = route.leg_summaries?.[0] || 'Route';
51
+ let traffic = '';
52
+ const c = route.congestion_information;
53
+ if (c) {
54
+ const total = c.length_low + c.length_moderate + c.length_heavy + c.length_severe;
55
+ const heavyPct = total > 0
56
+ ? Math.round(((c.length_heavy + c.length_severe) / total) * 100)
57
+ : 0;
58
+ traffic =
59
+ heavyPct > 20
60
+ ? ` ⚠️ Heavy traffic (${heavyPct}%)`
61
+ : c.length_moderate > 0
62
+ ? ' 🟡 Moderate traffic'
63
+ : ' ✅ Light traffic';
64
+ }
65
+ const incidentCount = route.incidents_summary?.length ?? 0;
66
+ const incidents = incidentCount > 0 ? ` • ${incidentCount} incident(s)` : '';
67
+ return `${duration} via ${roads} • ${distance}${traffic}${incidents}`;
68
+ }
69
+ /**
70
+ * When multiple route alternatives come back, let the user pick one via
71
+ * MCP elicitation rather than handing all of them to the model. Returns
72
+ * the selected route's index (to thread through the self-fetch ref so the
73
+ * map preview draws the same route) and mutates nothing — the caller
74
+ * applies the filtered `routes` array itself.
75
+ *
76
+ * Mirrors search_and_geocode_tool's disambiguation elicitation: silent,
77
+ * best-effort fallback to "return everything" on decline, on an
78
+ * unsupported client, or on any elicitation error.
79
+ */
80
+ async elicitRouteSelection(routes) {
81
+ if (!this.server || routes.length < 2)
82
+ return undefined;
83
+ try {
84
+ const options = routes.map((route, index) => ({
85
+ value: String(index),
86
+ label: this.describeRoute(route)
87
+ }));
88
+ const result = await this.server.server.elicitInput({
89
+ mode: 'form',
90
+ message: `Found ${routes.length} routes. Choose your preferred route:`,
91
+ requestedSchema: {
92
+ type: 'object',
93
+ properties: {
94
+ selectedIndex: {
95
+ type: 'string',
96
+ title: 'Select Route',
97
+ description: 'Choose the route that best fits your needs',
98
+ enum: options.map((o) => o.value),
99
+ enumNames: options.map((o) => o.label)
100
+ }
101
+ },
102
+ required: ['selectedIndex']
103
+ }
104
+ });
105
+ if (result.action === 'accept' && result.content?.selectedIndex) {
106
+ const index = parseInt(String(result.content.selectedIndex), 10);
107
+ if (Number.isInteger(index) && index >= 0 && index < routes.length) {
108
+ return index;
109
+ }
110
+ }
111
+ }
112
+ catch {
113
+ // Elicitation isn't supported by every MCP client (Claude Desktop
114
+ // doesn't, for example). Falling back to "return all routes" is the
115
+ // expected behavior — silent, since Claude Desktop's UI flags tool
116
+ // calls that emit notifications/message at any level as visually
117
+ // failed even when the JSON-RPC response is isError: false.
118
+ }
119
+ return undefined;
120
+ }
36
121
  async execute(input, accessToken) {
37
122
  // Validate exclude parameter against the actual routing_profile
38
123
  // This is needed because some exclusions are only driving specific
@@ -177,6 +262,21 @@ export class DirectionsTool extends MapboxApiBasedTool {
177
262
  this.log('warning', `DirectionsTool: Response validation failed: ${error}`);
178
263
  validatedData = cleanedData;
179
264
  }
265
+ // When the API returns multiple route alternatives, let the user pick
266
+ // one via elicitation rather than handing every option to the model.
267
+ // selectedRouteIndex (into the *original* routes array) is threaded
268
+ // through the self-fetch ref below so the map preview draws the same
269
+ // route the user picked, not just whichever the API returns first.
270
+ let selectedRouteIndex;
271
+ if (validatedData.routes && validatedData.routes.length >= 2) {
272
+ selectedRouteIndex = await this.elicitRouteSelection(validatedData.routes);
273
+ if (selectedRouteIndex !== undefined) {
274
+ validatedData = {
275
+ ...validatedData,
276
+ routes: [validatedData.routes[selectedRouteIndex]]
277
+ };
278
+ }
279
+ }
180
280
  // Check response size and conditionally create temporary resource
181
281
  const RESPONSE_SIZE_THRESHOLD = 50 * 1024; // 50KB
182
282
  const responseText = JSON.stringify(validatedData, null, 2);
@@ -188,10 +288,14 @@ export class DirectionsTool extends MapboxApiBasedTool {
188
288
  // (already visible to the LLM), so unlike a mapbox://temp/ ref there's
189
289
  // nothing server-side that a restart or a rehydrated conversation could
190
290
  // invalidate. Works regardless of input.geometries since the self-fetch
191
- // always forces geometries=geojson itself.
291
+ // always forces geometries=geojson itself. selectedRouteIndex (when
292
+ // elicitation resolved to one route) tells the client which of the
293
+ // freshly re-fetched alternatives to draw — see selectedMapboxId in
294
+ // search_and_geocode_tool for the equivalent pattern.
192
295
  const selfFetchRef = buildSelfFetchRef('directions', {
193
296
  coordinates: input.coordinates,
194
297
  routing_profile: input.routing_profile,
298
+ selectedRouteIndex,
195
299
  alternatives: input.alternatives,
196
300
  exclude: input.exclude,
197
301
  depart_at: input.depart_at,