@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.
- package/README.md +100 -14
- package/dist/commonjs/cli.d.ts.map +1 -1
- package/dist/commonjs/cli.js +5 -2
- package/dist/commonjs/cli.js.map +1 -1
- package/dist/commonjs/resources/resourceRegistry.d.ts +1 -2
- package/dist/commonjs/resources/resourceRegistry.d.ts.map +1 -1
- package/dist/commonjs/resources/resourceRegistry.js +0 -2
- package/dist/commonjs/resources/resourceRegistry.js.map +1 -1
- package/dist/commonjs/resources/ui-apps/mapAppHtml.d.ts +3 -3
- package/dist/commonjs/resources/ui-apps/mapAppHtml.d.ts.map +1 -1
- package/dist/commonjs/resources/ui-apps/mapAppHtml.js +18 -4
- package/dist/commonjs/resources/ui-apps/mapAppHtml.js.map +1 -1
- package/dist/commonjs/tools/directions-tool/DirectionsTool.d.ts +16 -0
- package/dist/commonjs/tools/directions-tool/DirectionsTool.d.ts.map +1 -1
- package/dist/commonjs/tools/directions-tool/DirectionsTool.js +105 -1
- package/dist/commonjs/tools/directions-tool/DirectionsTool.js.map +1 -1
- package/dist/commonjs/tools/place-details-tool/PlaceDetailsTool.d.ts.map +1 -1
- package/dist/commonjs/tools/place-details-tool/PlaceDetailsTool.input.schema.js +1 -1
- package/dist/commonjs/tools/place-details-tool/PlaceDetailsTool.input.schema.js.map +1 -1
- package/dist/commonjs/tools/place-details-tool/PlaceDetailsTool.js +7 -3
- package/dist/commonjs/tools/place-details-tool/PlaceDetailsTool.js.map +1 -1
- package/dist/commonjs/tools/search-and-geocode-tool/SearchAndGeocodeTool.d.ts.map +1 -1
- package/dist/commonjs/tools/search-and-geocode-tool/SearchAndGeocodeTool.js +2 -0
- package/dist/commonjs/tools/search-and-geocode-tool/SearchAndGeocodeTool.js.map +1 -1
- package/dist/commonjs/tools/static-map-image-tool/StaticMapImageTool.d.ts.map +1 -1
- package/dist/commonjs/tools/static-map-image-tool/StaticMapImageTool.input.schema.d.ts +3 -3
- package/dist/commonjs/tools/static-map-image-tool/StaticMapImageTool.input.schema.d.ts.map +1 -1
- package/dist/commonjs/tools/static-map-image-tool/StaticMapImageTool.input.schema.js +16 -2
- package/dist/commonjs/tools/static-map-image-tool/StaticMapImageTool.input.schema.js.map +1 -1
- package/dist/commonjs/tools/static-map-image-tool/StaticMapImageTool.js +15 -4
- package/dist/commonjs/tools/static-map-image-tool/StaticMapImageTool.js.map +1 -1
- package/dist/commonjs/utils/index.d.ts +2 -0
- package/dist/commonjs/utils/index.d.ts.map +1 -1
- package/dist/commonjs/utils/index.js +8 -1
- package/dist/commonjs/utils/index.js.map +1 -1
- package/dist/commonjs/utils/redactToken.d.ts +3 -0
- package/dist/commonjs/utils/redactToken.d.ts.map +1 -0
- package/dist/commonjs/utils/redactToken.js +55 -0
- package/dist/commonjs/utils/redactToken.js.map +1 -0
- package/dist/commonjs/utils/redactingSpanExporter.d.ts +24 -0
- package/dist/commonjs/utils/redactingSpanExporter.d.ts.map +1 -0
- package/dist/commonjs/utils/redactingSpanExporter.js +97 -0
- package/dist/commonjs/utils/redactingSpanExporter.js.map +1 -0
- package/dist/commonjs/utils/tracing.d.ts.map +1 -1
- package/dist/commonjs/utils/tracing.js +4 -1
- package/dist/commonjs/utils/tracing.js.map +1 -1
- package/dist/commonjs/utils/urlSafety.d.ts +23 -7
- package/dist/commonjs/utils/urlSafety.d.ts.map +1 -1
- package/dist/commonjs/utils/urlSafety.js +84 -66
- package/dist/commonjs/utils/urlSafety.js.map +1 -1
- package/dist/commonjs/version.json +3 -3
- package/dist/esm/cli.d.ts.map +1 -1
- package/dist/esm/cli.js +5 -2
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/resources/resourceRegistry.d.ts +1 -2
- package/dist/esm/resources/resourceRegistry.d.ts.map +1 -1
- package/dist/esm/resources/resourceRegistry.js +0 -2
- package/dist/esm/resources/resourceRegistry.js.map +1 -1
- package/dist/esm/resources/ui-apps/mapAppHtml.d.ts +3 -3
- package/dist/esm/resources/ui-apps/mapAppHtml.d.ts.map +1 -1
- package/dist/esm/resources/ui-apps/mapAppHtml.js +18 -4
- package/dist/esm/resources/ui-apps/mapAppHtml.js.map +1 -1
- package/dist/esm/tools/directions-tool/DirectionsTool.d.ts +16 -0
- package/dist/esm/tools/directions-tool/DirectionsTool.d.ts.map +1 -1
- package/dist/esm/tools/directions-tool/DirectionsTool.js +105 -1
- package/dist/esm/tools/directions-tool/DirectionsTool.js.map +1 -1
- package/dist/esm/tools/place-details-tool/PlaceDetailsTool.d.ts.map +1 -1
- package/dist/esm/tools/place-details-tool/PlaceDetailsTool.input.schema.js +1 -1
- package/dist/esm/tools/place-details-tool/PlaceDetailsTool.input.schema.js.map +1 -1
- package/dist/esm/tools/place-details-tool/PlaceDetailsTool.js +7 -3
- package/dist/esm/tools/place-details-tool/PlaceDetailsTool.js.map +1 -1
- package/dist/esm/tools/search-and-geocode-tool/SearchAndGeocodeTool.d.ts.map +1 -1
- package/dist/esm/tools/search-and-geocode-tool/SearchAndGeocodeTool.js +2 -0
- package/dist/esm/tools/search-and-geocode-tool/SearchAndGeocodeTool.js.map +1 -1
- package/dist/esm/tools/static-map-image-tool/StaticMapImageTool.d.ts.map +1 -1
- package/dist/esm/tools/static-map-image-tool/StaticMapImageTool.input.schema.d.ts +3 -3
- package/dist/esm/tools/static-map-image-tool/StaticMapImageTool.input.schema.d.ts.map +1 -1
- package/dist/esm/tools/static-map-image-tool/StaticMapImageTool.input.schema.js +17 -3
- package/dist/esm/tools/static-map-image-tool/StaticMapImageTool.input.schema.js.map +1 -1
- package/dist/esm/tools/static-map-image-tool/StaticMapImageTool.js +15 -4
- package/dist/esm/tools/static-map-image-tool/StaticMapImageTool.js.map +1 -1
- package/dist/esm/utils/index.d.ts +2 -0
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/esm/utils/index.js +5 -0
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/redactToken.d.ts +3 -0
- package/dist/esm/utils/redactToken.d.ts.map +1 -0
- package/dist/esm/utils/redactToken.js +52 -0
- package/dist/esm/utils/redactToken.js.map +1 -0
- package/dist/esm/utils/redactingSpanExporter.d.ts +24 -0
- package/dist/esm/utils/redactingSpanExporter.d.ts.map +1 -0
- package/dist/esm/utils/redactingSpanExporter.js +93 -0
- package/dist/esm/utils/redactingSpanExporter.js.map +1 -0
- package/dist/esm/utils/tracing.d.ts.map +1 -1
- package/dist/esm/utils/tracing.js +4 -1
- package/dist/esm/utils/tracing.js.map +1 -1
- package/dist/esm/utils/urlSafety.d.ts +23 -7
- package/dist/esm/utils/urlSafety.d.ts.map +1 -1
- package/dist/esm/utils/urlSafety.js +80 -66
- package/dist/esm/utils/urlSafety.js.map +1 -1
- package/dist/esm/version.json +3 -3
- package/package.json +2 -1
- package/dist/commonjs/resources/ui-apps/StaticMapUIResource.d.ts +0 -15
- package/dist/commonjs/resources/ui-apps/StaticMapUIResource.d.ts.map +0 -1
- package/dist/commonjs/resources/ui-apps/StaticMapUIResource.js +0 -262
- package/dist/commonjs/resources/ui-apps/StaticMapUIResource.js.map +0 -1
- package/dist/esm/resources/ui-apps/StaticMapUIResource.d.ts +0 -15
- package/dist/esm/resources/ui-apps/StaticMapUIResource.d.ts.map +0 -1
- package/dist/esm/resources/ui-apps/StaticMapUIResource.js +0 -258
- 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
|
-
* -
|
|
10
|
-
*
|
|
11
|
-
*
|
|
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
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
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":"
|
|
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
|
-
* -
|
|
15
|
-
*
|
|
16
|
-
*
|
|
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
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
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
|
|
52
|
+
return null;
|
|
30
53
|
}
|
|
31
54
|
if (parsed.protocol !== 'https:') {
|
|
32
|
-
return
|
|
55
|
+
return null;
|
|
33
56
|
}
|
|
34
|
-
// Strip optional surrounding brackets from IPv6 literals
|
|
35
|
-
|
|
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
|
|
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
|
-
|
|
47
|
-
|
|
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
|
-
//
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
// ::
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
//
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (
|
|
88
|
-
return
|
|
89
|
-
|
|
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
|
|
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":";AAAA,6BAA6B;AAC7B,kCAAkC
|
|
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"}
|
package/dist/esm/cli.d.ts.map
CHANGED
|
@@ -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;
|
|
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',
|
package/dist/esm/cli.js.map
CHANGED
|
@@ -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;
|
|
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,
|
|
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,
|
|
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,
|
|
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 —
|
|
4
|
-
*
|
|
5
|
-
*
|
|
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,
|
|
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 —
|
|
5
|
-
*
|
|
6
|
-
*
|
|
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
|
|
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":"AAAA,6BAA6B;AAC7B,kCAAkC;AAIlC;;;;;;;;;GASG;AAEH,yEAAyE;AACzE,wEAAwE;AACxE,6EAA6E;AAC7E,8CAA8C;AAC9C,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC;AAE1C,MAAM,UAAU,gBAAgB,CAAC,MAKhC;IACC,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC;IAC5C,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,yBAAyB,CAAC;IACpE,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,iBAAiB,CAAC;IAExD,MAAM,iBAAiB,GAAG,WAAW;QACnC,CAAC,CAAC,qDAAqD,eAAe,CAClE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAC5B,WAAW;QACd,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;;;;;;mDAM0C,SAAS;oDACR,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkD3D,iBAAiB;;;;gBAIH,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;uBACpB,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC
|
|
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,
|
|
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,
|