@frontmcp/plugin-dashboard 1.7.2 → 1.8.1
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/auth/dashboard-auth.d.ts +0 -10
- package/auth/dashboard-auth.d.ts.map +1 -1
- package/dashboard.config-store.d.ts +8 -1
- package/dashboard.config-store.d.ts.map +1 -1
- package/esm/index.mjs +98 -3
- package/esm/package.json +3 -3
- package/index.d.ts +1 -0
- package/index.d.ts.map +1 -1
- package/index.js +100 -4
- package/package.json +3 -3
package/auth/dashboard-auth.d.ts
CHANGED
|
@@ -18,15 +18,5 @@ export interface DashboardAuthResult {
|
|
|
18
18
|
status?: 401;
|
|
19
19
|
message?: string;
|
|
20
20
|
}
|
|
21
|
-
/**
|
|
22
|
-
* Create the dashboard's HTTP auth check.
|
|
23
|
-
*
|
|
24
|
-
* Returns `undefined` when authentication is not enabled, so the caller can skip
|
|
25
|
-
* the check entirely rather than branch on a permissive validator.
|
|
26
|
-
*
|
|
27
|
-
* A token may be presented as `Authorization: Bearer <token>` (preferred — a URL
|
|
28
|
-
* token lands in access logs, `Referer` headers and browser history) or as
|
|
29
|
-
* `?token=<token>`, which is what the documented dashboard link uses.
|
|
30
|
-
*/
|
|
31
21
|
export declare function createDashboardAuthValidator(auth: DashboardAuth | undefined): ((req: DashboardAuthRequest) => DashboardAuthResult) | undefined;
|
|
32
22
|
//# sourceMappingURL=dashboard-auth.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-auth.d.ts","sourceRoot":"","sources":["../../src/auth/dashboard-auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;;;;;;;;GASG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;CACnE;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;
|
|
1
|
+
{"version":3,"file":"dashboard-auth.d.ts","sourceRoot":"","sources":["../../src/auth/dashboard-auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;;;;;;;;GASG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;CACnE;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAyDD,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,aAAa,GAAG,SAAS,GAC9B,CAAC,CAAC,GAAG,EAAE,oBAAoB,KAAK,mBAAmB,CAAC,GAAG,SAAS,CAqBlE"}
|
|
@@ -20,6 +20,13 @@ export declare function publishDashboardOptions(options: DashboardPluginOptions)
|
|
|
20
20
|
* otherwise the defaults merged with whatever the caller supplied.
|
|
21
21
|
*/
|
|
22
22
|
export declare function resolveDashboardOptions(fallback?: DashboardPluginOptionsInput): DashboardPluginOptions;
|
|
23
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Clear the published options.
|
|
25
|
+
*
|
|
26
|
+
* Dashboard options are process-wide, and a second CONFLICTING auth
|
|
27
|
+
* configuration now throws rather than silently replacing the first (BC-036).
|
|
28
|
+
* A host that builds several servers serially — a test suite, a CLI that
|
|
29
|
+
* reconfigures between runs — calls this between constructions.
|
|
30
|
+
*/
|
|
24
31
|
export declare function resetDashboardOptions(): void;
|
|
25
32
|
//# sourceMappingURL=dashboard.config-store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard.config-store.d.ts","sourceRoot":"","sources":["../src/dashboard.config-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,sBAAsB,EAC3B,KAAK,2BAA2B,EACjC,MAAM,mBAAmB,CAAC;AAmB3B;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAuB7E;AAyBD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,GAAE,2BAAgC,GAAG,sBAAsB,CAG1G;AAED
|
|
1
|
+
{"version":3,"file":"dashboard.config-store.d.ts","sourceRoot":"","sources":["../src/dashboard.config-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,sBAAsB,EAC3B,KAAK,2BAA2B,EACjC,MAAM,mBAAmB,CAAC;AAmB3B;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAuB7E;AAyBD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,GAAE,2BAAgC,GAAG,sBAAsB,CAG1G;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C"}
|
package/esm/index.mjs
CHANGED
|
@@ -368,6 +368,9 @@ function resolveDashboardOptions(fallback = {}) {
|
|
|
368
368
|
if (publishedOptions) return publishedOptions;
|
|
369
369
|
return dashboardPluginOptionsSchema.parse({ ...defaultDashboardPluginOptions, ...fallback });
|
|
370
370
|
}
|
|
371
|
+
function resetDashboardOptions() {
|
|
372
|
+
publishedOptions = void 0;
|
|
373
|
+
}
|
|
371
374
|
|
|
372
375
|
// plugins/plugin-dashboard/src/dashboard.symbol.ts
|
|
373
376
|
var DashboardConfigToken = /* @__PURE__ */ Symbol("DashboardConfig");
|
|
@@ -3678,6 +3681,90 @@ var init_cloudflare_kv = __esm({
|
|
|
3678
3681
|
}
|
|
3679
3682
|
});
|
|
3680
3683
|
init_runtime();
|
|
3684
|
+
var IPV4_OCTET_PATTERN = /^(0|[1-9]\d{0,2})$/;
|
|
3685
|
+
var IPV6_GROUP_PATTERN = /^[0-9a-f]{1,4}$/;
|
|
3686
|
+
var IPV4_BLOCKS = compileBlocks(
|
|
3687
|
+
[
|
|
3688
|
+
["0.0.0.0/8", "this-network"],
|
|
3689
|
+
["10.0.0.0/8", "private"],
|
|
3690
|
+
["100.64.0.0/10", "carrier-grade-nat"],
|
|
3691
|
+
["127.0.0.0/8", "loopback"],
|
|
3692
|
+
["169.254.0.0/16", "link-local"],
|
|
3693
|
+
["172.16.0.0/12", "private"],
|
|
3694
|
+
["192.0.0.0/24", "ietf-protocol"],
|
|
3695
|
+
["192.168.0.0/16", "private"],
|
|
3696
|
+
["198.18.0.0/15", "benchmarking"],
|
|
3697
|
+
["224.0.0.0/4", "multicast"],
|
|
3698
|
+
["255.255.255.255/32", "reserved"],
|
|
3699
|
+
["240.0.0.0/4", "reserved"]
|
|
3700
|
+
],
|
|
3701
|
+
parseIpv4
|
|
3702
|
+
);
|
|
3703
|
+
var IPV6_BLOCKS = compileBlocks(
|
|
3704
|
+
[
|
|
3705
|
+
["::/128", "unspecified"],
|
|
3706
|
+
["::1/128", "loopback"],
|
|
3707
|
+
["fd00:ec2::254/128", "cloud-metadata"],
|
|
3708
|
+
["fc00::/7", "private"],
|
|
3709
|
+
["fe80::/10", "link-local"],
|
|
3710
|
+
["fec0::/10", "site-local"],
|
|
3711
|
+
// RFC 8215 local-use NAT64: where the IPv4 address sits depends on the operator's prefix length.
|
|
3712
|
+
["64:ff9b:1::/48", "local-use-nat64"],
|
|
3713
|
+
["ff00::/8", "multicast"]
|
|
3714
|
+
],
|
|
3715
|
+
expandIpv6
|
|
3716
|
+
);
|
|
3717
|
+
var IPV4_EMBEDDINGS = compileBlocks(
|
|
3718
|
+
[
|
|
3719
|
+
["::ffff:0:0/96", 6],
|
|
3720
|
+
["::ffff:0:0:0/96", 6],
|
|
3721
|
+
["::/96", 6],
|
|
3722
|
+
["64:ff9b::/96", 6],
|
|
3723
|
+
["2002::/16", 1]
|
|
3724
|
+
],
|
|
3725
|
+
expandIpv6
|
|
3726
|
+
);
|
|
3727
|
+
function parseIpv4(address) {
|
|
3728
|
+
const parts = address.split(".");
|
|
3729
|
+
if (parts.length !== 4 || !parts.every((part) => IPV4_OCTET_PATTERN.test(part))) return void 0;
|
|
3730
|
+
const octets = parts.map(Number);
|
|
3731
|
+
return octets.every((octet) => octet <= 255) ? octets : void 0;
|
|
3732
|
+
}
|
|
3733
|
+
function expandIpv6(address) {
|
|
3734
|
+
const zoneIndex = address.indexOf("%");
|
|
3735
|
+
let text = (zoneIndex === -1 ? address : address.slice(0, zoneIndex)).toLowerCase();
|
|
3736
|
+
const lastColonIndex = text.lastIndexOf(":");
|
|
3737
|
+
const trailingSegment = text.slice(lastColonIndex + 1);
|
|
3738
|
+
if (lastColonIndex !== -1 && trailingSegment.includes(".")) {
|
|
3739
|
+
const octets = parseIpv4(trailingSegment);
|
|
3740
|
+
if (!octets) return void 0;
|
|
3741
|
+
const highGroup = (octets[0] << 8 | octets[1]).toString(16);
|
|
3742
|
+
const lowGroup = (octets[2] << 8 | octets[3]).toString(16);
|
|
3743
|
+
text = `${text.slice(0, lastColonIndex + 1)}${highGroup}:${lowGroup}`;
|
|
3744
|
+
}
|
|
3745
|
+
const halves = text.split("::");
|
|
3746
|
+
if (halves.length > 2) return void 0;
|
|
3747
|
+
const head = parseIpv6Groups(halves[0]);
|
|
3748
|
+
if (!head) return void 0;
|
|
3749
|
+
if (halves.length === 1) return head.length === 8 ? head : void 0;
|
|
3750
|
+
const tail = parseIpv6Groups(halves[1]);
|
|
3751
|
+
if (!tail || head.length + tail.length > 7) return void 0;
|
|
3752
|
+
return [...head, ...new Array(8 - head.length - tail.length).fill(0), ...tail];
|
|
3753
|
+
}
|
|
3754
|
+
function parseIpv6Groups(part) {
|
|
3755
|
+
if (part === "") return [];
|
|
3756
|
+
const groups = part.split(":");
|
|
3757
|
+
if (!groups.every((group) => IPV6_GROUP_PATTERN.test(group))) return void 0;
|
|
3758
|
+
return groups.map((group) => parseInt(group, 16));
|
|
3759
|
+
}
|
|
3760
|
+
function compileBlocks(entries, parseNetwork) {
|
|
3761
|
+
return entries.map(([cidr, value]) => {
|
|
3762
|
+
const [networkText, prefixText] = cidr.split("/");
|
|
3763
|
+
const network = parseNetwork(networkText);
|
|
3764
|
+
if (!network) throw new Error(`Invalid network in address block "${cidr}"`);
|
|
3765
|
+
return { cidr, network, prefixLength: Number(prefixText), value };
|
|
3766
|
+
});
|
|
3767
|
+
}
|
|
3681
3768
|
init_fs2();
|
|
3682
3769
|
init_crypto();
|
|
3683
3770
|
var entryAvailabilitySchema = z3.object({
|
|
@@ -3724,6 +3811,14 @@ function tokenMatches(presented, expected) {
|
|
|
3724
3811
|
if (presented.length === 0 || expected.length === 0) return false;
|
|
3725
3812
|
return timingSafeEqual(sha256(presented), sha256(expected));
|
|
3726
3813
|
}
|
|
3814
|
+
function readBearerToken(header) {
|
|
3815
|
+
if (!header) return void 0;
|
|
3816
|
+
const separator = header.indexOf(" ");
|
|
3817
|
+
if (separator === -1) return void 0;
|
|
3818
|
+
if (header.slice(0, separator).toLowerCase() !== "bearer") return void 0;
|
|
3819
|
+
const token = header.slice(separator + 1).trim();
|
|
3820
|
+
return token.length > 0 ? token : void 0;
|
|
3821
|
+
}
|
|
3727
3822
|
function createDashboardAuthValidator(auth) {
|
|
3728
3823
|
if (!auth?.enabled) return void 0;
|
|
3729
3824
|
const expected = auth.token;
|
|
@@ -3731,8 +3826,7 @@ function createDashboardAuthValidator(auth) {
|
|
|
3731
3826
|
if (!expected) {
|
|
3732
3827
|
return { authorized: false, status: 401, message: "Dashboard authentication is misconfigured" };
|
|
3733
3828
|
}
|
|
3734
|
-
const
|
|
3735
|
-
const bearer = header?.startsWith("Bearer ") ? header.slice("Bearer ".length) : void 0;
|
|
3829
|
+
const bearer = readBearerToken(readHeader(req.headers, "authorization"));
|
|
3736
3830
|
if (bearer && tokenMatches(bearer, expected)) return AUTHORIZED;
|
|
3737
3831
|
const queryToken = readQuery(req.query, "token");
|
|
3738
3832
|
if (queryToken && tokenMatches(queryToken, expected)) return AUTHORIZED;
|
|
@@ -4915,5 +5009,6 @@ export {
|
|
|
4915
5009
|
dashboardPluginOptionsSchema,
|
|
4916
5010
|
DashboardPlugin as default,
|
|
4917
5011
|
defaultDashboardPluginOptions,
|
|
4918
|
-
isDashboardEnabled
|
|
5012
|
+
isDashboardEnabled,
|
|
5013
|
+
resetDashboardOptions
|
|
4919
5014
|
};
|
package/esm/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontmcp/plugin-dashboard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "Dashboard plugin for FrontMCP - visual monitoring and introspection of MCP servers",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -47,12 +47,12 @@
|
|
|
47
47
|
}
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@frontmcp/sdk": "1.
|
|
50
|
+
"@frontmcp/sdk": "1.8.1"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"reflect-metadata": "^0.2.2"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@frontmcp/lazy-zod": "1.
|
|
56
|
+
"@frontmcp/lazy-zod": "1.8.1"
|
|
57
57
|
}
|
|
58
58
|
}
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { default, default as DashboardPlugin } from './dashboard.plugin';
|
|
2
2
|
export { DashboardApp } from './app';
|
|
3
3
|
export { DashboardPluginOptions, DashboardPluginOptionsInput, dashboardPluginOptionsSchema, defaultDashboardPluginOptions, isDashboardEnabled, } from './dashboard.types';
|
|
4
|
+
export { resetDashboardOptions } from './dashboard.config-store';
|
|
4
5
|
export { DashboardConfigToken, GraphDataProviderToken, ParentScopeToken } from './dashboard.symbol';
|
|
5
6
|
export type { GraphData, GraphNode, GraphEdge, GraphMetadata } from './shared/types';
|
|
6
7
|
export { GraphDataProvider } from './providers';
|
package/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGzE,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAGrC,OAAO,EACL,sBAAsB,EACtB,2BAA2B,EAC3B,4BAA4B,EAC5B,6BAA6B,EAC7B,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGzE,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAGrC,OAAO,EACL,sBAAsB,EACtB,2BAA2B,EAC3B,4BAA4B,EAC5B,6BAA6B,EAC7B,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAI3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAGjE,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGpG,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,6BAA6B,CAAC"}
|
package/index.js
CHANGED
|
@@ -297,7 +297,8 @@ __export(index_exports, {
|
|
|
297
297
|
dashboardPluginOptionsSchema: () => dashboardPluginOptionsSchema,
|
|
298
298
|
default: () => DashboardPlugin,
|
|
299
299
|
defaultDashboardPluginOptions: () => defaultDashboardPluginOptions,
|
|
300
|
-
isDashboardEnabled: () => isDashboardEnabled
|
|
300
|
+
isDashboardEnabled: () => isDashboardEnabled,
|
|
301
|
+
resetDashboardOptions: () => resetDashboardOptions
|
|
301
302
|
});
|
|
302
303
|
module.exports = __toCommonJS(index_exports);
|
|
303
304
|
|
|
@@ -387,6 +388,9 @@ function resolveDashboardOptions(fallback = {}) {
|
|
|
387
388
|
if (publishedOptions) return publishedOptions;
|
|
388
389
|
return dashboardPluginOptionsSchema.parse({ ...defaultDashboardPluginOptions, ...fallback });
|
|
389
390
|
}
|
|
391
|
+
function resetDashboardOptions() {
|
|
392
|
+
publishedOptions = void 0;
|
|
393
|
+
}
|
|
390
394
|
|
|
391
395
|
// plugins/plugin-dashboard/src/dashboard.symbol.ts
|
|
392
396
|
var DashboardConfigToken = /* @__PURE__ */ Symbol("DashboardConfig");
|
|
@@ -3691,6 +3695,90 @@ var init_cloudflare_kv = __esm({
|
|
|
3691
3695
|
}
|
|
3692
3696
|
});
|
|
3693
3697
|
init_runtime();
|
|
3698
|
+
var IPV4_OCTET_PATTERN = /^(0|[1-9]\d{0,2})$/;
|
|
3699
|
+
var IPV6_GROUP_PATTERN = /^[0-9a-f]{1,4}$/;
|
|
3700
|
+
var IPV4_BLOCKS = compileBlocks(
|
|
3701
|
+
[
|
|
3702
|
+
["0.0.0.0/8", "this-network"],
|
|
3703
|
+
["10.0.0.0/8", "private"],
|
|
3704
|
+
["100.64.0.0/10", "carrier-grade-nat"],
|
|
3705
|
+
["127.0.0.0/8", "loopback"],
|
|
3706
|
+
["169.254.0.0/16", "link-local"],
|
|
3707
|
+
["172.16.0.0/12", "private"],
|
|
3708
|
+
["192.0.0.0/24", "ietf-protocol"],
|
|
3709
|
+
["192.168.0.0/16", "private"],
|
|
3710
|
+
["198.18.0.0/15", "benchmarking"],
|
|
3711
|
+
["224.0.0.0/4", "multicast"],
|
|
3712
|
+
["255.255.255.255/32", "reserved"],
|
|
3713
|
+
["240.0.0.0/4", "reserved"]
|
|
3714
|
+
],
|
|
3715
|
+
parseIpv4
|
|
3716
|
+
);
|
|
3717
|
+
var IPV6_BLOCKS = compileBlocks(
|
|
3718
|
+
[
|
|
3719
|
+
["::/128", "unspecified"],
|
|
3720
|
+
["::1/128", "loopback"],
|
|
3721
|
+
["fd00:ec2::254/128", "cloud-metadata"],
|
|
3722
|
+
["fc00::/7", "private"],
|
|
3723
|
+
["fe80::/10", "link-local"],
|
|
3724
|
+
["fec0::/10", "site-local"],
|
|
3725
|
+
// RFC 8215 local-use NAT64: where the IPv4 address sits depends on the operator's prefix length.
|
|
3726
|
+
["64:ff9b:1::/48", "local-use-nat64"],
|
|
3727
|
+
["ff00::/8", "multicast"]
|
|
3728
|
+
],
|
|
3729
|
+
expandIpv6
|
|
3730
|
+
);
|
|
3731
|
+
var IPV4_EMBEDDINGS = compileBlocks(
|
|
3732
|
+
[
|
|
3733
|
+
["::ffff:0:0/96", 6],
|
|
3734
|
+
["::ffff:0:0:0/96", 6],
|
|
3735
|
+
["::/96", 6],
|
|
3736
|
+
["64:ff9b::/96", 6],
|
|
3737
|
+
["2002::/16", 1]
|
|
3738
|
+
],
|
|
3739
|
+
expandIpv6
|
|
3740
|
+
);
|
|
3741
|
+
function parseIpv4(address) {
|
|
3742
|
+
const parts = address.split(".");
|
|
3743
|
+
if (parts.length !== 4 || !parts.every((part) => IPV4_OCTET_PATTERN.test(part))) return void 0;
|
|
3744
|
+
const octets = parts.map(Number);
|
|
3745
|
+
return octets.every((octet) => octet <= 255) ? octets : void 0;
|
|
3746
|
+
}
|
|
3747
|
+
function expandIpv6(address) {
|
|
3748
|
+
const zoneIndex = address.indexOf("%");
|
|
3749
|
+
let text = (zoneIndex === -1 ? address : address.slice(0, zoneIndex)).toLowerCase();
|
|
3750
|
+
const lastColonIndex = text.lastIndexOf(":");
|
|
3751
|
+
const trailingSegment = text.slice(lastColonIndex + 1);
|
|
3752
|
+
if (lastColonIndex !== -1 && trailingSegment.includes(".")) {
|
|
3753
|
+
const octets = parseIpv4(trailingSegment);
|
|
3754
|
+
if (!octets) return void 0;
|
|
3755
|
+
const highGroup = (octets[0] << 8 | octets[1]).toString(16);
|
|
3756
|
+
const lowGroup = (octets[2] << 8 | octets[3]).toString(16);
|
|
3757
|
+
text = `${text.slice(0, lastColonIndex + 1)}${highGroup}:${lowGroup}`;
|
|
3758
|
+
}
|
|
3759
|
+
const halves = text.split("::");
|
|
3760
|
+
if (halves.length > 2) return void 0;
|
|
3761
|
+
const head = parseIpv6Groups(halves[0]);
|
|
3762
|
+
if (!head) return void 0;
|
|
3763
|
+
if (halves.length === 1) return head.length === 8 ? head : void 0;
|
|
3764
|
+
const tail = parseIpv6Groups(halves[1]);
|
|
3765
|
+
if (!tail || head.length + tail.length > 7) return void 0;
|
|
3766
|
+
return [...head, ...new Array(8 - head.length - tail.length).fill(0), ...tail];
|
|
3767
|
+
}
|
|
3768
|
+
function parseIpv6Groups(part) {
|
|
3769
|
+
if (part === "") return [];
|
|
3770
|
+
const groups = part.split(":");
|
|
3771
|
+
if (!groups.every((group) => IPV6_GROUP_PATTERN.test(group))) return void 0;
|
|
3772
|
+
return groups.map((group) => parseInt(group, 16));
|
|
3773
|
+
}
|
|
3774
|
+
function compileBlocks(entries, parseNetwork) {
|
|
3775
|
+
return entries.map(([cidr, value]) => {
|
|
3776
|
+
const [networkText, prefixText] = cidr.split("/");
|
|
3777
|
+
const network = parseNetwork(networkText);
|
|
3778
|
+
if (!network) throw new Error(`Invalid network in address block "${cidr}"`);
|
|
3779
|
+
return { cidr, network, prefixLength: Number(prefixText), value };
|
|
3780
|
+
});
|
|
3781
|
+
}
|
|
3694
3782
|
init_fs2();
|
|
3695
3783
|
init_crypto();
|
|
3696
3784
|
var entryAvailabilitySchema = import_lazy_zod4.z.object({
|
|
@@ -3737,6 +3825,14 @@ function tokenMatches(presented, expected) {
|
|
|
3737
3825
|
if (presented.length === 0 || expected.length === 0) return false;
|
|
3738
3826
|
return timingSafeEqual(sha256(presented), sha256(expected));
|
|
3739
3827
|
}
|
|
3828
|
+
function readBearerToken(header) {
|
|
3829
|
+
if (!header) return void 0;
|
|
3830
|
+
const separator = header.indexOf(" ");
|
|
3831
|
+
if (separator === -1) return void 0;
|
|
3832
|
+
if (header.slice(0, separator).toLowerCase() !== "bearer") return void 0;
|
|
3833
|
+
const token = header.slice(separator + 1).trim();
|
|
3834
|
+
return token.length > 0 ? token : void 0;
|
|
3835
|
+
}
|
|
3740
3836
|
function createDashboardAuthValidator(auth) {
|
|
3741
3837
|
if (!auth?.enabled) return void 0;
|
|
3742
3838
|
const expected = auth.token;
|
|
@@ -3744,8 +3840,7 @@ function createDashboardAuthValidator(auth) {
|
|
|
3744
3840
|
if (!expected) {
|
|
3745
3841
|
return { authorized: false, status: 401, message: "Dashboard authentication is misconfigured" };
|
|
3746
3842
|
}
|
|
3747
|
-
const
|
|
3748
|
-
const bearer = header?.startsWith("Bearer ") ? header.slice("Bearer ".length) : void 0;
|
|
3843
|
+
const bearer = readBearerToken(readHeader(req.headers, "authorization"));
|
|
3749
3844
|
if (bearer && tokenMatches(bearer, expected)) return AUTHORIZED;
|
|
3750
3845
|
const queryToken = readQuery(req.query, "token");
|
|
3751
3846
|
if (queryToken && tokenMatches(queryToken, expected)) return AUTHORIZED;
|
|
@@ -4928,5 +5023,6 @@ DashboardApp = __decorateClass([
|
|
|
4928
5023
|
ParentScopeToken,
|
|
4929
5024
|
dashboardPluginOptionsSchema,
|
|
4930
5025
|
defaultDashboardPluginOptions,
|
|
4931
|
-
isDashboardEnabled
|
|
5026
|
+
isDashboardEnabled,
|
|
5027
|
+
resetDashboardOptions
|
|
4932
5028
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontmcp/plugin-dashboard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "Dashboard plugin for FrontMCP - visual monitoring and introspection of MCP servers",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -47,12 +47,12 @@
|
|
|
47
47
|
}
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@frontmcp/sdk": "1.
|
|
50
|
+
"@frontmcp/sdk": "1.8.1"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"reflect-metadata": "^0.2.2"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@frontmcp/lazy-zod": "1.
|
|
56
|
+
"@frontmcp/lazy-zod": "1.8.1"
|
|
57
57
|
}
|
|
58
58
|
}
|