@frontmcp/plugin-dashboard 1.8.7 → 1.9.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/esm/index.mjs +166 -113
- package/esm/package.json +3 -3
- package/index.js +163 -113
- package/package.json +3 -3
package/esm/index.mjs
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
var __frontmcpModule = typeof process !== "undefined" && typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("module") : undefined;
|
|
2
|
+
const require = __frontmcpModule ? __frontmcpModule.createRequire(import.meta.url || 'file:///') : undefined;
|
|
3
|
+
// __frontmcpCreateRequire
|
|
1
4
|
var __create = Object.create;
|
|
2
5
|
var __defProp = Object.defineProperty;
|
|
3
6
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -443,7 +446,6 @@ import { hkdf } from "@noble/hashes/hkdf.js";
|
|
|
443
446
|
import { randomBytes as nobleRandomBytes } from "@noble/hashes/utils.js";
|
|
444
447
|
import { gcm } from "@noble/ciphers/aes.js";
|
|
445
448
|
import { analyzeForReDoS, REDOS_THRESHOLDS } from "@enclave-vm/ast";
|
|
446
|
-
import { z as z3 } from "@frontmcp/lazy-zod";
|
|
447
449
|
var __frontmcpModule = typeof process !== "undefined" && typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("module") : void 0;
|
|
448
450
|
var require2 = __frontmcpModule ? __frontmcpModule.createRequire(import.meta.url || "file:///") : void 0;
|
|
449
451
|
var __defProp2 = Object.defineProperty;
|
|
@@ -781,8 +783,8 @@ var init_key_persistence = __esm({
|
|
|
781
783
|
*/
|
|
782
784
|
async get(kid) {
|
|
783
785
|
if (this.enableCache) {
|
|
784
|
-
const
|
|
785
|
-
if (
|
|
786
|
+
const cached = this.cache.get(kid);
|
|
787
|
+
if (cached) return cached;
|
|
786
788
|
}
|
|
787
789
|
const raw = await this.storage.get(kid);
|
|
788
790
|
if (!raw) return null;
|
|
@@ -1038,6 +1040,61 @@ var init_errors = __esm({
|
|
|
1038
1040
|
};
|
|
1039
1041
|
}
|
|
1040
1042
|
});
|
|
1043
|
+
function globToRegex(pattern) {
|
|
1044
|
+
if (pattern.length > MAX_PATTERN_LENGTH) {
|
|
1045
|
+
throw new StoragePatternError(
|
|
1046
|
+
pattern.substring(0, 50) + "...",
|
|
1047
|
+
`Pattern exceeds maximum length of ${MAX_PATTERN_LENGTH} characters`
|
|
1048
|
+
);
|
|
1049
|
+
}
|
|
1050
|
+
const wildcardCount = (pattern.match(/[*?]/g) || []).length;
|
|
1051
|
+
if (wildcardCount > MAX_WILDCARDS) {
|
|
1052
|
+
throw new StoragePatternError(pattern, `Pattern has too many wildcards (max: ${MAX_WILDCARDS})`);
|
|
1053
|
+
}
|
|
1054
|
+
if (pattern === "" || pattern === "*") {
|
|
1055
|
+
return /^.*$/;
|
|
1056
|
+
}
|
|
1057
|
+
let regexStr = "^";
|
|
1058
|
+
let prevChar = "";
|
|
1059
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
1060
|
+
const char = pattern[i];
|
|
1061
|
+
switch (char) {
|
|
1062
|
+
case "*":
|
|
1063
|
+
if (prevChar !== "*") {
|
|
1064
|
+
regexStr += ".*";
|
|
1065
|
+
}
|
|
1066
|
+
break;
|
|
1067
|
+
case "?":
|
|
1068
|
+
regexStr += ".";
|
|
1069
|
+
break;
|
|
1070
|
+
default:
|
|
1071
|
+
regexStr += char.replace(REGEX_SPECIAL_CHARS, "\\$&");
|
|
1072
|
+
}
|
|
1073
|
+
prevChar = char;
|
|
1074
|
+
}
|
|
1075
|
+
regexStr += "$";
|
|
1076
|
+
try {
|
|
1077
|
+
return new RegExp(regexStr);
|
|
1078
|
+
} catch {
|
|
1079
|
+
throw new StoragePatternError(pattern, "Failed to compile pattern to regex");
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
function matchesPattern(key, pattern) {
|
|
1083
|
+
const regex = globToRegex(pattern);
|
|
1084
|
+
return regex.test(key);
|
|
1085
|
+
}
|
|
1086
|
+
var MAX_PATTERN_LENGTH;
|
|
1087
|
+
var MAX_WILDCARDS;
|
|
1088
|
+
var REGEX_SPECIAL_CHARS;
|
|
1089
|
+
var init_pattern = __esm({
|
|
1090
|
+
"libs/utils/src/storage/utils/pattern.ts"() {
|
|
1091
|
+
"use strict";
|
|
1092
|
+
init_errors();
|
|
1093
|
+
MAX_PATTERN_LENGTH = 500;
|
|
1094
|
+
MAX_WILDCARDS = 20;
|
|
1095
|
+
REGEX_SPECIAL_CHARS = /[.+^${}()|[\]\\]/g;
|
|
1096
|
+
}
|
|
1097
|
+
});
|
|
1041
1098
|
function validateTTL(ttlSeconds) {
|
|
1042
1099
|
if (typeof ttlSeconds !== "number") {
|
|
1043
1100
|
throw new StorageTTLError(ttlSeconds, `TTL must be a number, got ${typeof ttlSeconds}`);
|
|
@@ -1146,6 +1203,17 @@ var init_base = __esm({
|
|
|
1146
1203
|
const matchedKeys = await this.keys(pattern);
|
|
1147
1204
|
return matchedKeys.length;
|
|
1148
1205
|
}
|
|
1206
|
+
/**
|
|
1207
|
+
* Default: not supported, since a read followed by a delete is not atomic.
|
|
1208
|
+
* Override in adapters whose backend can compare and delete in one step.
|
|
1209
|
+
*/
|
|
1210
|
+
async deleteIfEquals(_key, _expectedValue) {
|
|
1211
|
+
throw new StorageNotSupportedError(
|
|
1212
|
+
"deleteIfEquals",
|
|
1213
|
+
this.backendName,
|
|
1214
|
+
"Use the memory, Redis, Upstash or Vercel KV adapter for an atomic compare-and-delete."
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1149
1217
|
// ============================================
|
|
1150
1218
|
// Pub/Sub (default: not supported)
|
|
1151
1219
|
// ============================================
|
|
@@ -1193,71 +1261,16 @@ var init_base = __esm({
|
|
|
1193
1261
|
};
|
|
1194
1262
|
}
|
|
1195
1263
|
});
|
|
1196
|
-
function globToRegex(pattern) {
|
|
1197
|
-
if (pattern.length > MAX_PATTERN_LENGTH) {
|
|
1198
|
-
throw new StoragePatternError(
|
|
1199
|
-
pattern.substring(0, 50) + "...",
|
|
1200
|
-
`Pattern exceeds maximum length of ${MAX_PATTERN_LENGTH} characters`
|
|
1201
|
-
);
|
|
1202
|
-
}
|
|
1203
|
-
const wildcardCount = (pattern.match(/[*?]/g) || []).length;
|
|
1204
|
-
if (wildcardCount > MAX_WILDCARDS) {
|
|
1205
|
-
throw new StoragePatternError(pattern, `Pattern has too many wildcards (max: ${MAX_WILDCARDS})`);
|
|
1206
|
-
}
|
|
1207
|
-
if (pattern === "" || pattern === "*") {
|
|
1208
|
-
return /^.*$/;
|
|
1209
|
-
}
|
|
1210
|
-
let regexStr = "^";
|
|
1211
|
-
let prevChar = "";
|
|
1212
|
-
for (let i = 0; i < pattern.length; i++) {
|
|
1213
|
-
const char = pattern[i];
|
|
1214
|
-
switch (char) {
|
|
1215
|
-
case "*":
|
|
1216
|
-
if (prevChar !== "*") {
|
|
1217
|
-
regexStr += ".*";
|
|
1218
|
-
}
|
|
1219
|
-
break;
|
|
1220
|
-
case "?":
|
|
1221
|
-
regexStr += ".";
|
|
1222
|
-
break;
|
|
1223
|
-
default:
|
|
1224
|
-
regexStr += char.replace(REGEX_SPECIAL_CHARS, "\\$&");
|
|
1225
|
-
}
|
|
1226
|
-
prevChar = char;
|
|
1227
|
-
}
|
|
1228
|
-
regexStr += "$";
|
|
1229
|
-
try {
|
|
1230
|
-
return new RegExp(regexStr);
|
|
1231
|
-
} catch {
|
|
1232
|
-
throw new StoragePatternError(pattern, "Failed to compile pattern to regex");
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
function matchesPattern(key, pattern) {
|
|
1236
|
-
const regex = globToRegex(pattern);
|
|
1237
|
-
return regex.test(key);
|
|
1238
|
-
}
|
|
1239
|
-
var MAX_PATTERN_LENGTH;
|
|
1240
|
-
var MAX_WILDCARDS;
|
|
1241
|
-
var REGEX_SPECIAL_CHARS;
|
|
1242
|
-
var init_pattern = __esm({
|
|
1243
|
-
"libs/utils/src/storage/utils/pattern.ts"() {
|
|
1244
|
-
"use strict";
|
|
1245
|
-
init_errors();
|
|
1246
|
-
MAX_PATTERN_LENGTH = 500;
|
|
1247
|
-
MAX_WILDCARDS = 20;
|
|
1248
|
-
REGEX_SPECIAL_CHARS = /[.+^${}()|[\]\\]/g;
|
|
1249
|
-
}
|
|
1250
|
-
});
|
|
1251
1264
|
var DEFAULT_SWEEP_INTERVAL_SECONDS;
|
|
1252
1265
|
var MAX_TIMEOUT_MS;
|
|
1253
1266
|
var MemoryStorageAdapter;
|
|
1254
1267
|
var init_memory = __esm({
|
|
1255
1268
|
"libs/utils/src/storage/adapters/memory.ts"() {
|
|
1256
1269
|
"use strict";
|
|
1257
|
-
init_base();
|
|
1258
1270
|
init_errors();
|
|
1259
1271
|
init_pattern();
|
|
1260
1272
|
init_ttl();
|
|
1273
|
+
init_base();
|
|
1261
1274
|
DEFAULT_SWEEP_INTERVAL_SECONDS = 60;
|
|
1262
1275
|
MAX_TIMEOUT_MS = 2147483647;
|
|
1263
1276
|
MemoryStorageAdapter = class extends BaseStorageAdapter {
|
|
@@ -1349,6 +1362,12 @@ var init_memory = __esm({
|
|
|
1349
1362
|
this.ensureConnected();
|
|
1350
1363
|
return this.deleteEntry(key);
|
|
1351
1364
|
}
|
|
1365
|
+
async deleteIfEquals(key, expectedValue) {
|
|
1366
|
+
this.ensureConnected();
|
|
1367
|
+
const entry = this.store.get(key);
|
|
1368
|
+
if (!entry || isExpired(entry.expiresAt) || entry.value !== expectedValue) return false;
|
|
1369
|
+
return this.deleteEntry(key);
|
|
1370
|
+
}
|
|
1352
1371
|
async exists(key) {
|
|
1353
1372
|
this.ensureConnected();
|
|
1354
1373
|
const entry = this.store.get(key);
|
|
@@ -2726,6 +2745,13 @@ var init_utils = __esm({
|
|
|
2726
2745
|
init_ttl();
|
|
2727
2746
|
}
|
|
2728
2747
|
});
|
|
2748
|
+
var COMPARE_AND_DELETE_SCRIPT;
|
|
2749
|
+
var init_compare_and_delete = __esm({
|
|
2750
|
+
"libs/utils/src/storage/utils/compare-and-delete.ts"() {
|
|
2751
|
+
"use strict";
|
|
2752
|
+
COMPARE_AND_DELETE_SCRIPT = `if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) end return 0`;
|
|
2753
|
+
}
|
|
2754
|
+
});
|
|
2729
2755
|
var redis_exports = {};
|
|
2730
2756
|
__export(redis_exports, {
|
|
2731
2757
|
RedisStorageAdapter: () => RedisStorageAdapter,
|
|
@@ -2768,6 +2794,7 @@ var init_redis = __esm({
|
|
|
2768
2794
|
init_errors();
|
|
2769
2795
|
init_redis_error_listener();
|
|
2770
2796
|
init_utils();
|
|
2797
|
+
init_compare_and_delete();
|
|
2771
2798
|
init_base();
|
|
2772
2799
|
RedisStorageAdapter = class extends BaseStorageAdapter {
|
|
2773
2800
|
backendName = "redis";
|
|
@@ -2922,6 +2949,15 @@ var init_redis = __esm({
|
|
|
2922
2949
|
const result = await this.getConnectedClient().del(this.prefixKey(key));
|
|
2923
2950
|
return result > 0;
|
|
2924
2951
|
}
|
|
2952
|
+
async deleteIfEquals(key, expectedValue) {
|
|
2953
|
+
const deleted = await this.getConnectedClient().eval(
|
|
2954
|
+
COMPARE_AND_DELETE_SCRIPT,
|
|
2955
|
+
1,
|
|
2956
|
+
this.prefixKey(key),
|
|
2957
|
+
expectedValue
|
|
2958
|
+
);
|
|
2959
|
+
return deleted === 1;
|
|
2960
|
+
}
|
|
2925
2961
|
async exists(key) {
|
|
2926
2962
|
const result = await this.getConnectedClient().exists(this.prefixKey(key));
|
|
2927
2963
|
return result > 0;
|
|
@@ -3128,9 +3164,12 @@ var vercel_kv_exports = {};
|
|
|
3128
3164
|
__export(vercel_kv_exports, {
|
|
3129
3165
|
VercelKvStorageAdapter: () => VercelKvStorageAdapter
|
|
3130
3166
|
});
|
|
3131
|
-
function
|
|
3167
|
+
async function loadVercelKv() {
|
|
3132
3168
|
try {
|
|
3133
|
-
|
|
3169
|
+
const mod = await import("@vercel/kv");
|
|
3170
|
+
const resolved = typeof mod.createClient === "function" ? mod : mod.default;
|
|
3171
|
+
if (!resolved || typeof resolved.createClient !== "function") throw new Error("createClient missing");
|
|
3172
|
+
return resolved;
|
|
3134
3173
|
} catch {
|
|
3135
3174
|
throw new Error("@vercel/kv is required for Vercel KV storage adapter. Install it with: npm install @vercel/kv");
|
|
3136
3175
|
}
|
|
@@ -3139,9 +3178,10 @@ var VercelKvStorageAdapter;
|
|
|
3139
3178
|
var init_vercel_kv = __esm({
|
|
3140
3179
|
"libs/utils/src/storage/adapters/vercel-kv.ts"() {
|
|
3141
3180
|
"use strict";
|
|
3142
|
-
init_base();
|
|
3143
3181
|
init_errors();
|
|
3182
|
+
init_compare_and_delete();
|
|
3144
3183
|
init_ttl();
|
|
3184
|
+
init_base();
|
|
3145
3185
|
VercelKvStorageAdapter = class extends BaseStorageAdapter {
|
|
3146
3186
|
backendName = "vercel-kv";
|
|
3147
3187
|
client;
|
|
@@ -3166,17 +3206,13 @@ var init_vercel_kv = __esm({
|
|
|
3166
3206
|
async connect() {
|
|
3167
3207
|
if (this.connected) return;
|
|
3168
3208
|
try {
|
|
3169
|
-
const { createClient
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
const token = this.options.token;
|
|
3175
|
-
if (!url || !token) {
|
|
3176
|
-
throw new StorageConfigError("vercel-kv", "URL and token are required");
|
|
3177
|
-
}
|
|
3178
|
-
this.client = createClient({ url, token });
|
|
3209
|
+
const { createClient } = await loadVercelKv();
|
|
3210
|
+
const url = this.options.url;
|
|
3211
|
+
const token = this.options.token;
|
|
3212
|
+
if (!url || !token) {
|
|
3213
|
+
throw new StorageConfigError("vercel-kv", "URL and token are required");
|
|
3179
3214
|
}
|
|
3215
|
+
this.client = createClient({ url, token, cache: void 0 });
|
|
3180
3216
|
await this.client.exists("__healthcheck__");
|
|
3181
3217
|
this.connected = true;
|
|
3182
3218
|
} catch (e) {
|
|
@@ -3238,6 +3274,14 @@ var init_vercel_kv = __esm({
|
|
|
3238
3274
|
const result = await this.getConnectedClient().del(this.prefixKey(key));
|
|
3239
3275
|
return result > 0;
|
|
3240
3276
|
}
|
|
3277
|
+
async deleteIfEquals(key, expectedValue) {
|
|
3278
|
+
const deleted = await this.getConnectedClient().eval(
|
|
3279
|
+
COMPARE_AND_DELETE_SCRIPT,
|
|
3280
|
+
[this.prefixKey(key)],
|
|
3281
|
+
[expectedValue]
|
|
3282
|
+
);
|
|
3283
|
+
return deleted === 1;
|
|
3284
|
+
}
|
|
3241
3285
|
async exists(key) {
|
|
3242
3286
|
const result = await this.getConnectedClient().exists(this.prefixKey(key));
|
|
3243
3287
|
return result > 0;
|
|
@@ -3354,9 +3398,10 @@ var UpstashStorageAdapter;
|
|
|
3354
3398
|
var init_upstash = __esm({
|
|
3355
3399
|
"libs/utils/src/storage/adapters/upstash.ts"() {
|
|
3356
3400
|
"use strict";
|
|
3357
|
-
init_base();
|
|
3358
3401
|
init_errors();
|
|
3402
|
+
init_compare_and_delete();
|
|
3359
3403
|
init_ttl();
|
|
3404
|
+
init_base();
|
|
3360
3405
|
PUBSUB_POLL_INTERVAL_MS = 100;
|
|
3361
3406
|
UpstashStorageAdapter = class extends BaseStorageAdapter {
|
|
3362
3407
|
backendName = "upstash";
|
|
@@ -3461,6 +3506,14 @@ var init_upstash = __esm({
|
|
|
3461
3506
|
const result = await this.getConnectedClient().del(this.prefixKey(key));
|
|
3462
3507
|
return result > 0;
|
|
3463
3508
|
}
|
|
3509
|
+
async deleteIfEquals(key, expectedValue) {
|
|
3510
|
+
const deleted = await this.getConnectedClient().eval(
|
|
3511
|
+
COMPARE_AND_DELETE_SCRIPT,
|
|
3512
|
+
[this.prefixKey(key)],
|
|
3513
|
+
[expectedValue]
|
|
3514
|
+
);
|
|
3515
|
+
return deleted === 1;
|
|
3516
|
+
}
|
|
3464
3517
|
async exists(key) {
|
|
3465
3518
|
const result = await this.getConnectedClient().exists(this.prefixKey(key));
|
|
3466
3519
|
return result > 0;
|
|
@@ -3649,7 +3702,9 @@ var init_cloudflare_kv = __esm({
|
|
|
3649
3702
|
constructor(options) {
|
|
3650
3703
|
super();
|
|
3651
3704
|
if (!options?.namespace) {
|
|
3652
|
-
throw new Error(
|
|
3705
|
+
throw new Error(
|
|
3706
|
+
"CloudflareKvStorageAdapter: a bound KV `namespace` is required (resolve it from the Worker `env`)."
|
|
3707
|
+
);
|
|
3653
3708
|
}
|
|
3654
3709
|
this.kv = options.namespace;
|
|
3655
3710
|
this.keyPrefix = options.keyPrefix ?? "";
|
|
@@ -3743,6 +3798,13 @@ var init_cloudflare_kv = __esm({
|
|
|
3743
3798
|
"Cloudflare KV has no atomic increment (a get+put is racy under eventual consistency). Use a Durable Object for atomic counters."
|
|
3744
3799
|
);
|
|
3745
3800
|
}
|
|
3801
|
+
async deleteIfEquals(_key, _expectedValue) {
|
|
3802
|
+
throw new StorageNotSupportedError(
|
|
3803
|
+
"deleteIfEquals",
|
|
3804
|
+
this.backendName,
|
|
3805
|
+
"Cloudflare KV has no compare-and-set; use a Durable Object for an atomic compare-and-delete."
|
|
3806
|
+
);
|
|
3807
|
+
}
|
|
3746
3808
|
// ── Pub/Sub (unsupported) ────────────────────────────────────────────────
|
|
3747
3809
|
getPubSubSuggestion() {
|
|
3748
3810
|
return "Cloudflare KV does not support pub/sub. Use a Durable Object (or Queues) for fan-out.";
|
|
@@ -3856,16 +3918,7 @@ function compileBlocks(entries, parseNetwork) {
|
|
|
3856
3918
|
}
|
|
3857
3919
|
init_fs2();
|
|
3858
3920
|
init_crypto();
|
|
3859
|
-
|
|
3860
|
-
os: z3.array(z3.string().min(1)).optional(),
|
|
3861
|
-
platform: z3.array(z3.string().min(1)).optional(),
|
|
3862
|
-
runtime: z3.array(z3.string().min(1)).optional(),
|
|
3863
|
-
deployment: z3.array(z3.string().min(1)).optional(),
|
|
3864
|
-
provider: z3.array(z3.string().min(1)).optional(),
|
|
3865
|
-
target: z3.array(z3.string().min(1)).optional(),
|
|
3866
|
-
surface: z3.array(z3.enum(["mcp", "cli", "http-trigger", "job", "agent"])).optional(),
|
|
3867
|
-
env: z3.array(z3.string().min(1)).optional()
|
|
3868
|
-
}).strict();
|
|
3921
|
+
init_errors();
|
|
3869
3922
|
init_errors();
|
|
3870
3923
|
init_memory();
|
|
3871
3924
|
init_redis_error_listener();
|
|
@@ -4838,11 +4891,11 @@ GraphDataProvider = __decorateClass([
|
|
|
4838
4891
|
], GraphDataProvider);
|
|
4839
4892
|
|
|
4840
4893
|
// plugins/plugin-dashboard/src/tools/graph.tool.ts
|
|
4841
|
-
import { z as
|
|
4894
|
+
import { z as z3 } from "@frontmcp/lazy-zod";
|
|
4842
4895
|
import { Tool, ToolContext } from "@frontmcp/sdk";
|
|
4843
4896
|
var graphToolInputSchema = {
|
|
4844
|
-
includeSchemas:
|
|
4845
|
-
refresh:
|
|
4897
|
+
includeSchemas: z3.boolean().optional().default(false).describe("Include full input/output schemas in the response"),
|
|
4898
|
+
refresh: z3.boolean().optional().default(false).describe("Force refresh the graph data (bypass cache)")
|
|
4846
4899
|
};
|
|
4847
4900
|
var GraphTool = class extends ToolContext {
|
|
4848
4901
|
async execute(input) {
|
|
@@ -4880,7 +4933,7 @@ GraphTool = __decorateClass([
|
|
|
4880
4933
|
], GraphTool);
|
|
4881
4934
|
|
|
4882
4935
|
// plugins/plugin-dashboard/src/tools/list-resources.tool.ts
|
|
4883
|
-
import { z as
|
|
4936
|
+
import { z as z4 } from "@frontmcp/lazy-zod";
|
|
4884
4937
|
import { Tool as Tool2, ToolContext as ToolContext2 } from "@frontmcp/sdk";
|
|
4885
4938
|
|
|
4886
4939
|
// plugins/plugin-dashboard/src/shared/safe-regex.ts
|
|
@@ -4899,20 +4952,20 @@ function safeRegex(pattern) {
|
|
|
4899
4952
|
|
|
4900
4953
|
// plugins/plugin-dashboard/src/tools/list-resources.tool.ts
|
|
4901
4954
|
var listResourcesInputSchema = {
|
|
4902
|
-
filter:
|
|
4903
|
-
includeTemplates:
|
|
4955
|
+
filter: z4.string().optional().describe("Filter resources by name or URI pattern (regex supported)"),
|
|
4956
|
+
includeTemplates: z4.boolean().default(true).describe("Include resource templates in the response")
|
|
4904
4957
|
};
|
|
4905
|
-
var listResourcesOutputSchema =
|
|
4906
|
-
resources:
|
|
4907
|
-
|
|
4908
|
-
name:
|
|
4909
|
-
uri:
|
|
4910
|
-
description:
|
|
4911
|
-
mimeType:
|
|
4912
|
-
isTemplate:
|
|
4958
|
+
var listResourcesOutputSchema = z4.object({
|
|
4959
|
+
resources: z4.array(
|
|
4960
|
+
z4.object({
|
|
4961
|
+
name: z4.string(),
|
|
4962
|
+
uri: z4.string(),
|
|
4963
|
+
description: z4.string().optional(),
|
|
4964
|
+
mimeType: z4.string().optional(),
|
|
4965
|
+
isTemplate: z4.boolean()
|
|
4913
4966
|
})
|
|
4914
4967
|
),
|
|
4915
|
-
count:
|
|
4968
|
+
count: z4.number()
|
|
4916
4969
|
});
|
|
4917
4970
|
var ListResourcesTool = class extends ToolContext2 {
|
|
4918
4971
|
async execute(input) {
|
|
@@ -4974,25 +5027,25 @@ ListResourcesTool = __decorateClass([
|
|
|
4974
5027
|
], ListResourcesTool);
|
|
4975
5028
|
|
|
4976
5029
|
// plugins/plugin-dashboard/src/tools/list-tools.tool.ts
|
|
4977
|
-
import { z as
|
|
5030
|
+
import { z as z5 } from "@frontmcp/lazy-zod";
|
|
4978
5031
|
import { Tool as Tool3, ToolContext as ToolContext3 } from "@frontmcp/sdk";
|
|
4979
5032
|
var listToolsInputSchema = {
|
|
4980
|
-
filter:
|
|
4981
|
-
includePlugins:
|
|
4982
|
-
includeSchemas:
|
|
5033
|
+
filter: z5.string().optional().describe("Filter tools by name pattern (regex supported)"),
|
|
5034
|
+
includePlugins: z5.boolean().default(true).describe("Include tools from plugins"),
|
|
5035
|
+
includeSchemas: z5.boolean().default(false).describe("Include input/output schemas in the response")
|
|
4983
5036
|
};
|
|
4984
|
-
var listToolsOutputSchema =
|
|
4985
|
-
tools:
|
|
4986
|
-
|
|
4987
|
-
name:
|
|
4988
|
-
fullName:
|
|
4989
|
-
description:
|
|
4990
|
-
tags:
|
|
4991
|
-
inputSchema:
|
|
4992
|
-
outputSchema:
|
|
5037
|
+
var listToolsOutputSchema = z5.object({
|
|
5038
|
+
tools: z5.array(
|
|
5039
|
+
z5.object({
|
|
5040
|
+
name: z5.string(),
|
|
5041
|
+
fullName: z5.string(),
|
|
5042
|
+
description: z5.string().optional(),
|
|
5043
|
+
tags: z5.array(z5.string()).optional(),
|
|
5044
|
+
inputSchema: z5.unknown().optional(),
|
|
5045
|
+
outputSchema: z5.unknown().optional()
|
|
4993
5046
|
})
|
|
4994
5047
|
),
|
|
4995
|
-
count:
|
|
5048
|
+
count: z5.number()
|
|
4996
5049
|
});
|
|
4997
5050
|
var ListToolsTool = class extends ToolContext3 {
|
|
4998
5051
|
async execute(input) {
|
package/esm/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontmcp/plugin-dashboard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
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.9.0"
|
|
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.9.0"
|
|
57
57
|
}
|
|
58
58
|
}
|
package/index.js
CHANGED
|
@@ -454,7 +454,6 @@ var import_utils = require("@noble/hashes/utils.js");
|
|
|
454
454
|
var import_aes = require("@noble/ciphers/aes.js");
|
|
455
455
|
var import_crypto_provider = __toESM(require_node(), 1);
|
|
456
456
|
var import_ast = require("@enclave-vm/ast");
|
|
457
|
-
var import_lazy_zod4 = require("@frontmcp/lazy-zod");
|
|
458
457
|
var import_meta = {};
|
|
459
458
|
var __frontmcpModule = typeof process !== "undefined" && typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("module") : void 0;
|
|
460
459
|
var require2 = __frontmcpModule ? __frontmcpModule.createRequire(import_meta.url || "file:///") : void 0;
|
|
@@ -793,8 +792,8 @@ var init_key_persistence = __esm({
|
|
|
793
792
|
*/
|
|
794
793
|
async get(kid) {
|
|
795
794
|
if (this.enableCache) {
|
|
796
|
-
const
|
|
797
|
-
if (
|
|
795
|
+
const cached = this.cache.get(kid);
|
|
796
|
+
if (cached) return cached;
|
|
798
797
|
}
|
|
799
798
|
const raw = await this.storage.get(kid);
|
|
800
799
|
if (!raw) return null;
|
|
@@ -1050,6 +1049,61 @@ var init_errors = __esm({
|
|
|
1050
1049
|
};
|
|
1051
1050
|
}
|
|
1052
1051
|
});
|
|
1052
|
+
function globToRegex(pattern) {
|
|
1053
|
+
if (pattern.length > MAX_PATTERN_LENGTH) {
|
|
1054
|
+
throw new StoragePatternError(
|
|
1055
|
+
pattern.substring(0, 50) + "...",
|
|
1056
|
+
`Pattern exceeds maximum length of ${MAX_PATTERN_LENGTH} characters`
|
|
1057
|
+
);
|
|
1058
|
+
}
|
|
1059
|
+
const wildcardCount = (pattern.match(/[*?]/g) || []).length;
|
|
1060
|
+
if (wildcardCount > MAX_WILDCARDS) {
|
|
1061
|
+
throw new StoragePatternError(pattern, `Pattern has too many wildcards (max: ${MAX_WILDCARDS})`);
|
|
1062
|
+
}
|
|
1063
|
+
if (pattern === "" || pattern === "*") {
|
|
1064
|
+
return /^.*$/;
|
|
1065
|
+
}
|
|
1066
|
+
let regexStr = "^";
|
|
1067
|
+
let prevChar = "";
|
|
1068
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
1069
|
+
const char = pattern[i];
|
|
1070
|
+
switch (char) {
|
|
1071
|
+
case "*":
|
|
1072
|
+
if (prevChar !== "*") {
|
|
1073
|
+
regexStr += ".*";
|
|
1074
|
+
}
|
|
1075
|
+
break;
|
|
1076
|
+
case "?":
|
|
1077
|
+
regexStr += ".";
|
|
1078
|
+
break;
|
|
1079
|
+
default:
|
|
1080
|
+
regexStr += char.replace(REGEX_SPECIAL_CHARS, "\\$&");
|
|
1081
|
+
}
|
|
1082
|
+
prevChar = char;
|
|
1083
|
+
}
|
|
1084
|
+
regexStr += "$";
|
|
1085
|
+
try {
|
|
1086
|
+
return new RegExp(regexStr);
|
|
1087
|
+
} catch {
|
|
1088
|
+
throw new StoragePatternError(pattern, "Failed to compile pattern to regex");
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
function matchesPattern(key, pattern) {
|
|
1092
|
+
const regex = globToRegex(pattern);
|
|
1093
|
+
return regex.test(key);
|
|
1094
|
+
}
|
|
1095
|
+
var MAX_PATTERN_LENGTH;
|
|
1096
|
+
var MAX_WILDCARDS;
|
|
1097
|
+
var REGEX_SPECIAL_CHARS;
|
|
1098
|
+
var init_pattern = __esm({
|
|
1099
|
+
"libs/utils/src/storage/utils/pattern.ts"() {
|
|
1100
|
+
"use strict";
|
|
1101
|
+
init_errors();
|
|
1102
|
+
MAX_PATTERN_LENGTH = 500;
|
|
1103
|
+
MAX_WILDCARDS = 20;
|
|
1104
|
+
REGEX_SPECIAL_CHARS = /[.+^${}()|[\]\\]/g;
|
|
1105
|
+
}
|
|
1106
|
+
});
|
|
1053
1107
|
function validateTTL(ttlSeconds) {
|
|
1054
1108
|
if (typeof ttlSeconds !== "number") {
|
|
1055
1109
|
throw new StorageTTLError(ttlSeconds, `TTL must be a number, got ${typeof ttlSeconds}`);
|
|
@@ -1158,6 +1212,17 @@ var init_base = __esm({
|
|
|
1158
1212
|
const matchedKeys = await this.keys(pattern);
|
|
1159
1213
|
return matchedKeys.length;
|
|
1160
1214
|
}
|
|
1215
|
+
/**
|
|
1216
|
+
* Default: not supported, since a read followed by a delete is not atomic.
|
|
1217
|
+
* Override in adapters whose backend can compare and delete in one step.
|
|
1218
|
+
*/
|
|
1219
|
+
async deleteIfEquals(_key, _expectedValue) {
|
|
1220
|
+
throw new StorageNotSupportedError(
|
|
1221
|
+
"deleteIfEquals",
|
|
1222
|
+
this.backendName,
|
|
1223
|
+
"Use the memory, Redis, Upstash or Vercel KV adapter for an atomic compare-and-delete."
|
|
1224
|
+
);
|
|
1225
|
+
}
|
|
1161
1226
|
// ============================================
|
|
1162
1227
|
// Pub/Sub (default: not supported)
|
|
1163
1228
|
// ============================================
|
|
@@ -1205,71 +1270,16 @@ var init_base = __esm({
|
|
|
1205
1270
|
};
|
|
1206
1271
|
}
|
|
1207
1272
|
});
|
|
1208
|
-
function globToRegex(pattern) {
|
|
1209
|
-
if (pattern.length > MAX_PATTERN_LENGTH) {
|
|
1210
|
-
throw new StoragePatternError(
|
|
1211
|
-
pattern.substring(0, 50) + "...",
|
|
1212
|
-
`Pattern exceeds maximum length of ${MAX_PATTERN_LENGTH} characters`
|
|
1213
|
-
);
|
|
1214
|
-
}
|
|
1215
|
-
const wildcardCount = (pattern.match(/[*?]/g) || []).length;
|
|
1216
|
-
if (wildcardCount > MAX_WILDCARDS) {
|
|
1217
|
-
throw new StoragePatternError(pattern, `Pattern has too many wildcards (max: ${MAX_WILDCARDS})`);
|
|
1218
|
-
}
|
|
1219
|
-
if (pattern === "" || pattern === "*") {
|
|
1220
|
-
return /^.*$/;
|
|
1221
|
-
}
|
|
1222
|
-
let regexStr = "^";
|
|
1223
|
-
let prevChar = "";
|
|
1224
|
-
for (let i = 0; i < pattern.length; i++) {
|
|
1225
|
-
const char = pattern[i];
|
|
1226
|
-
switch (char) {
|
|
1227
|
-
case "*":
|
|
1228
|
-
if (prevChar !== "*") {
|
|
1229
|
-
regexStr += ".*";
|
|
1230
|
-
}
|
|
1231
|
-
break;
|
|
1232
|
-
case "?":
|
|
1233
|
-
regexStr += ".";
|
|
1234
|
-
break;
|
|
1235
|
-
default:
|
|
1236
|
-
regexStr += char.replace(REGEX_SPECIAL_CHARS, "\\$&");
|
|
1237
|
-
}
|
|
1238
|
-
prevChar = char;
|
|
1239
|
-
}
|
|
1240
|
-
regexStr += "$";
|
|
1241
|
-
try {
|
|
1242
|
-
return new RegExp(regexStr);
|
|
1243
|
-
} catch {
|
|
1244
|
-
throw new StoragePatternError(pattern, "Failed to compile pattern to regex");
|
|
1245
|
-
}
|
|
1246
|
-
}
|
|
1247
|
-
function matchesPattern(key, pattern) {
|
|
1248
|
-
const regex = globToRegex(pattern);
|
|
1249
|
-
return regex.test(key);
|
|
1250
|
-
}
|
|
1251
|
-
var MAX_PATTERN_LENGTH;
|
|
1252
|
-
var MAX_WILDCARDS;
|
|
1253
|
-
var REGEX_SPECIAL_CHARS;
|
|
1254
|
-
var init_pattern = __esm({
|
|
1255
|
-
"libs/utils/src/storage/utils/pattern.ts"() {
|
|
1256
|
-
"use strict";
|
|
1257
|
-
init_errors();
|
|
1258
|
-
MAX_PATTERN_LENGTH = 500;
|
|
1259
|
-
MAX_WILDCARDS = 20;
|
|
1260
|
-
REGEX_SPECIAL_CHARS = /[.+^${}()|[\]\\]/g;
|
|
1261
|
-
}
|
|
1262
|
-
});
|
|
1263
1273
|
var DEFAULT_SWEEP_INTERVAL_SECONDS;
|
|
1264
1274
|
var MAX_TIMEOUT_MS;
|
|
1265
1275
|
var MemoryStorageAdapter;
|
|
1266
1276
|
var init_memory = __esm({
|
|
1267
1277
|
"libs/utils/src/storage/adapters/memory.ts"() {
|
|
1268
1278
|
"use strict";
|
|
1269
|
-
init_base();
|
|
1270
1279
|
init_errors();
|
|
1271
1280
|
init_pattern();
|
|
1272
1281
|
init_ttl();
|
|
1282
|
+
init_base();
|
|
1273
1283
|
DEFAULT_SWEEP_INTERVAL_SECONDS = 60;
|
|
1274
1284
|
MAX_TIMEOUT_MS = 2147483647;
|
|
1275
1285
|
MemoryStorageAdapter = class extends BaseStorageAdapter {
|
|
@@ -1361,6 +1371,12 @@ var init_memory = __esm({
|
|
|
1361
1371
|
this.ensureConnected();
|
|
1362
1372
|
return this.deleteEntry(key);
|
|
1363
1373
|
}
|
|
1374
|
+
async deleteIfEquals(key, expectedValue) {
|
|
1375
|
+
this.ensureConnected();
|
|
1376
|
+
const entry = this.store.get(key);
|
|
1377
|
+
if (!entry || isExpired(entry.expiresAt) || entry.value !== expectedValue) return false;
|
|
1378
|
+
return this.deleteEntry(key);
|
|
1379
|
+
}
|
|
1364
1380
|
async exists(key) {
|
|
1365
1381
|
this.ensureConnected();
|
|
1366
1382
|
const entry = this.store.get(key);
|
|
@@ -2738,6 +2754,13 @@ var init_utils = __esm({
|
|
|
2738
2754
|
init_ttl();
|
|
2739
2755
|
}
|
|
2740
2756
|
});
|
|
2757
|
+
var COMPARE_AND_DELETE_SCRIPT;
|
|
2758
|
+
var init_compare_and_delete = __esm({
|
|
2759
|
+
"libs/utils/src/storage/utils/compare-and-delete.ts"() {
|
|
2760
|
+
"use strict";
|
|
2761
|
+
COMPARE_AND_DELETE_SCRIPT = `if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) end return 0`;
|
|
2762
|
+
}
|
|
2763
|
+
});
|
|
2741
2764
|
var redis_exports = {};
|
|
2742
2765
|
__export2(redis_exports, {
|
|
2743
2766
|
RedisStorageAdapter: () => RedisStorageAdapter,
|
|
@@ -2780,6 +2803,7 @@ var init_redis = __esm({
|
|
|
2780
2803
|
init_errors();
|
|
2781
2804
|
init_redis_error_listener();
|
|
2782
2805
|
init_utils();
|
|
2806
|
+
init_compare_and_delete();
|
|
2783
2807
|
init_base();
|
|
2784
2808
|
RedisStorageAdapter = class extends BaseStorageAdapter {
|
|
2785
2809
|
backendName = "redis";
|
|
@@ -2934,6 +2958,15 @@ var init_redis = __esm({
|
|
|
2934
2958
|
const result = await this.getConnectedClient().del(this.prefixKey(key));
|
|
2935
2959
|
return result > 0;
|
|
2936
2960
|
}
|
|
2961
|
+
async deleteIfEquals(key, expectedValue) {
|
|
2962
|
+
const deleted = await this.getConnectedClient().eval(
|
|
2963
|
+
COMPARE_AND_DELETE_SCRIPT,
|
|
2964
|
+
1,
|
|
2965
|
+
this.prefixKey(key),
|
|
2966
|
+
expectedValue
|
|
2967
|
+
);
|
|
2968
|
+
return deleted === 1;
|
|
2969
|
+
}
|
|
2937
2970
|
async exists(key) {
|
|
2938
2971
|
const result = await this.getConnectedClient().exists(this.prefixKey(key));
|
|
2939
2972
|
return result > 0;
|
|
@@ -3140,9 +3173,12 @@ var vercel_kv_exports = {};
|
|
|
3140
3173
|
__export2(vercel_kv_exports, {
|
|
3141
3174
|
VercelKvStorageAdapter: () => VercelKvStorageAdapter
|
|
3142
3175
|
});
|
|
3143
|
-
function
|
|
3176
|
+
async function loadVercelKv() {
|
|
3144
3177
|
try {
|
|
3145
|
-
|
|
3178
|
+
const mod = await import("@vercel/kv");
|
|
3179
|
+
const resolved = typeof mod.createClient === "function" ? mod : mod.default;
|
|
3180
|
+
if (!resolved || typeof resolved.createClient !== "function") throw new Error("createClient missing");
|
|
3181
|
+
return resolved;
|
|
3146
3182
|
} catch {
|
|
3147
3183
|
throw new Error("@vercel/kv is required for Vercel KV storage adapter. Install it with: npm install @vercel/kv");
|
|
3148
3184
|
}
|
|
@@ -3151,9 +3187,10 @@ var VercelKvStorageAdapter;
|
|
|
3151
3187
|
var init_vercel_kv = __esm({
|
|
3152
3188
|
"libs/utils/src/storage/adapters/vercel-kv.ts"() {
|
|
3153
3189
|
"use strict";
|
|
3154
|
-
init_base();
|
|
3155
3190
|
init_errors();
|
|
3191
|
+
init_compare_and_delete();
|
|
3156
3192
|
init_ttl();
|
|
3193
|
+
init_base();
|
|
3157
3194
|
VercelKvStorageAdapter = class extends BaseStorageAdapter {
|
|
3158
3195
|
backendName = "vercel-kv";
|
|
3159
3196
|
client;
|
|
@@ -3178,17 +3215,13 @@ var init_vercel_kv = __esm({
|
|
|
3178
3215
|
async connect() {
|
|
3179
3216
|
if (this.connected) return;
|
|
3180
3217
|
try {
|
|
3181
|
-
const { createClient
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
const token = this.options.token;
|
|
3187
|
-
if (!url || !token) {
|
|
3188
|
-
throw new StorageConfigError("vercel-kv", "URL and token are required");
|
|
3189
|
-
}
|
|
3190
|
-
this.client = createClient({ url, token });
|
|
3218
|
+
const { createClient } = await loadVercelKv();
|
|
3219
|
+
const url = this.options.url;
|
|
3220
|
+
const token = this.options.token;
|
|
3221
|
+
if (!url || !token) {
|
|
3222
|
+
throw new StorageConfigError("vercel-kv", "URL and token are required");
|
|
3191
3223
|
}
|
|
3224
|
+
this.client = createClient({ url, token, cache: void 0 });
|
|
3192
3225
|
await this.client.exists("__healthcheck__");
|
|
3193
3226
|
this.connected = true;
|
|
3194
3227
|
} catch (e) {
|
|
@@ -3250,6 +3283,14 @@ var init_vercel_kv = __esm({
|
|
|
3250
3283
|
const result = await this.getConnectedClient().del(this.prefixKey(key));
|
|
3251
3284
|
return result > 0;
|
|
3252
3285
|
}
|
|
3286
|
+
async deleteIfEquals(key, expectedValue) {
|
|
3287
|
+
const deleted = await this.getConnectedClient().eval(
|
|
3288
|
+
COMPARE_AND_DELETE_SCRIPT,
|
|
3289
|
+
[this.prefixKey(key)],
|
|
3290
|
+
[expectedValue]
|
|
3291
|
+
);
|
|
3292
|
+
return deleted === 1;
|
|
3293
|
+
}
|
|
3253
3294
|
async exists(key) {
|
|
3254
3295
|
const result = await this.getConnectedClient().exists(this.prefixKey(key));
|
|
3255
3296
|
return result > 0;
|
|
@@ -3366,9 +3407,10 @@ var UpstashStorageAdapter;
|
|
|
3366
3407
|
var init_upstash = __esm({
|
|
3367
3408
|
"libs/utils/src/storage/adapters/upstash.ts"() {
|
|
3368
3409
|
"use strict";
|
|
3369
|
-
init_base();
|
|
3370
3410
|
init_errors();
|
|
3411
|
+
init_compare_and_delete();
|
|
3371
3412
|
init_ttl();
|
|
3413
|
+
init_base();
|
|
3372
3414
|
PUBSUB_POLL_INTERVAL_MS = 100;
|
|
3373
3415
|
UpstashStorageAdapter = class extends BaseStorageAdapter {
|
|
3374
3416
|
backendName = "upstash";
|
|
@@ -3473,6 +3515,14 @@ var init_upstash = __esm({
|
|
|
3473
3515
|
const result = await this.getConnectedClient().del(this.prefixKey(key));
|
|
3474
3516
|
return result > 0;
|
|
3475
3517
|
}
|
|
3518
|
+
async deleteIfEquals(key, expectedValue) {
|
|
3519
|
+
const deleted = await this.getConnectedClient().eval(
|
|
3520
|
+
COMPARE_AND_DELETE_SCRIPT,
|
|
3521
|
+
[this.prefixKey(key)],
|
|
3522
|
+
[expectedValue]
|
|
3523
|
+
);
|
|
3524
|
+
return deleted === 1;
|
|
3525
|
+
}
|
|
3476
3526
|
async exists(key) {
|
|
3477
3527
|
const result = await this.getConnectedClient().exists(this.prefixKey(key));
|
|
3478
3528
|
return result > 0;
|
|
@@ -3661,7 +3711,9 @@ var init_cloudflare_kv = __esm({
|
|
|
3661
3711
|
constructor(options) {
|
|
3662
3712
|
super();
|
|
3663
3713
|
if (!options?.namespace) {
|
|
3664
|
-
throw new Error(
|
|
3714
|
+
throw new Error(
|
|
3715
|
+
"CloudflareKvStorageAdapter: a bound KV `namespace` is required (resolve it from the Worker `env`)."
|
|
3716
|
+
);
|
|
3665
3717
|
}
|
|
3666
3718
|
this.kv = options.namespace;
|
|
3667
3719
|
this.keyPrefix = options.keyPrefix ?? "";
|
|
@@ -3755,6 +3807,13 @@ var init_cloudflare_kv = __esm({
|
|
|
3755
3807
|
"Cloudflare KV has no atomic increment (a get+put is racy under eventual consistency). Use a Durable Object for atomic counters."
|
|
3756
3808
|
);
|
|
3757
3809
|
}
|
|
3810
|
+
async deleteIfEquals(_key, _expectedValue) {
|
|
3811
|
+
throw new StorageNotSupportedError(
|
|
3812
|
+
"deleteIfEquals",
|
|
3813
|
+
this.backendName,
|
|
3814
|
+
"Cloudflare KV has no compare-and-set; use a Durable Object for an atomic compare-and-delete."
|
|
3815
|
+
);
|
|
3816
|
+
}
|
|
3758
3817
|
// ── Pub/Sub (unsupported) ────────────────────────────────────────────────
|
|
3759
3818
|
getPubSubSuggestion() {
|
|
3760
3819
|
return "Cloudflare KV does not support pub/sub. Use a Durable Object (or Queues) for fan-out.";
|
|
@@ -3868,16 +3927,7 @@ function compileBlocks(entries, parseNetwork) {
|
|
|
3868
3927
|
}
|
|
3869
3928
|
init_fs2();
|
|
3870
3929
|
init_crypto();
|
|
3871
|
-
|
|
3872
|
-
os: import_lazy_zod4.z.array(import_lazy_zod4.z.string().min(1)).optional(),
|
|
3873
|
-
platform: import_lazy_zod4.z.array(import_lazy_zod4.z.string().min(1)).optional(),
|
|
3874
|
-
runtime: import_lazy_zod4.z.array(import_lazy_zod4.z.string().min(1)).optional(),
|
|
3875
|
-
deployment: import_lazy_zod4.z.array(import_lazy_zod4.z.string().min(1)).optional(),
|
|
3876
|
-
provider: import_lazy_zod4.z.array(import_lazy_zod4.z.string().min(1)).optional(),
|
|
3877
|
-
target: import_lazy_zod4.z.array(import_lazy_zod4.z.string().min(1)).optional(),
|
|
3878
|
-
surface: import_lazy_zod4.z.array(import_lazy_zod4.z.enum(["mcp", "cli", "http-trigger", "job", "agent"])).optional(),
|
|
3879
|
-
env: import_lazy_zod4.z.array(import_lazy_zod4.z.string().min(1)).optional()
|
|
3880
|
-
}).strict();
|
|
3930
|
+
init_errors();
|
|
3881
3931
|
init_errors();
|
|
3882
3932
|
init_memory();
|
|
3883
3933
|
init_redis_error_listener();
|
|
@@ -4850,11 +4900,11 @@ GraphDataProvider = __decorateClass([
|
|
|
4850
4900
|
], GraphDataProvider);
|
|
4851
4901
|
|
|
4852
4902
|
// plugins/plugin-dashboard/src/tools/graph.tool.ts
|
|
4853
|
-
var
|
|
4903
|
+
var import_lazy_zod4 = require("@frontmcp/lazy-zod");
|
|
4854
4904
|
var import_sdk4 = require("@frontmcp/sdk");
|
|
4855
4905
|
var graphToolInputSchema = {
|
|
4856
|
-
includeSchemas:
|
|
4857
|
-
refresh:
|
|
4906
|
+
includeSchemas: import_lazy_zod4.z.boolean().optional().default(false).describe("Include full input/output schemas in the response"),
|
|
4907
|
+
refresh: import_lazy_zod4.z.boolean().optional().default(false).describe("Force refresh the graph data (bypass cache)")
|
|
4858
4908
|
};
|
|
4859
4909
|
var GraphTool = class extends import_sdk4.ToolContext {
|
|
4860
4910
|
async execute(input) {
|
|
@@ -4892,7 +4942,7 @@ GraphTool = __decorateClass([
|
|
|
4892
4942
|
], GraphTool);
|
|
4893
4943
|
|
|
4894
4944
|
// plugins/plugin-dashboard/src/tools/list-resources.tool.ts
|
|
4895
|
-
var
|
|
4945
|
+
var import_lazy_zod5 = require("@frontmcp/lazy-zod");
|
|
4896
4946
|
var import_sdk5 = require("@frontmcp/sdk");
|
|
4897
4947
|
|
|
4898
4948
|
// plugins/plugin-dashboard/src/shared/safe-regex.ts
|
|
@@ -4911,20 +4961,20 @@ function safeRegex(pattern) {
|
|
|
4911
4961
|
|
|
4912
4962
|
// plugins/plugin-dashboard/src/tools/list-resources.tool.ts
|
|
4913
4963
|
var listResourcesInputSchema = {
|
|
4914
|
-
filter:
|
|
4915
|
-
includeTemplates:
|
|
4964
|
+
filter: import_lazy_zod5.z.string().optional().describe("Filter resources by name or URI pattern (regex supported)"),
|
|
4965
|
+
includeTemplates: import_lazy_zod5.z.boolean().default(true).describe("Include resource templates in the response")
|
|
4916
4966
|
};
|
|
4917
|
-
var listResourcesOutputSchema =
|
|
4918
|
-
resources:
|
|
4919
|
-
|
|
4920
|
-
name:
|
|
4921
|
-
uri:
|
|
4922
|
-
description:
|
|
4923
|
-
mimeType:
|
|
4924
|
-
isTemplate:
|
|
4967
|
+
var listResourcesOutputSchema = import_lazy_zod5.z.object({
|
|
4968
|
+
resources: import_lazy_zod5.z.array(
|
|
4969
|
+
import_lazy_zod5.z.object({
|
|
4970
|
+
name: import_lazy_zod5.z.string(),
|
|
4971
|
+
uri: import_lazy_zod5.z.string(),
|
|
4972
|
+
description: import_lazy_zod5.z.string().optional(),
|
|
4973
|
+
mimeType: import_lazy_zod5.z.string().optional(),
|
|
4974
|
+
isTemplate: import_lazy_zod5.z.boolean()
|
|
4925
4975
|
})
|
|
4926
4976
|
),
|
|
4927
|
-
count:
|
|
4977
|
+
count: import_lazy_zod5.z.number()
|
|
4928
4978
|
});
|
|
4929
4979
|
var ListResourcesTool = class extends import_sdk5.ToolContext {
|
|
4930
4980
|
async execute(input) {
|
|
@@ -4986,25 +5036,25 @@ ListResourcesTool = __decorateClass([
|
|
|
4986
5036
|
], ListResourcesTool);
|
|
4987
5037
|
|
|
4988
5038
|
// plugins/plugin-dashboard/src/tools/list-tools.tool.ts
|
|
4989
|
-
var
|
|
5039
|
+
var import_lazy_zod6 = require("@frontmcp/lazy-zod");
|
|
4990
5040
|
var import_sdk6 = require("@frontmcp/sdk");
|
|
4991
5041
|
var listToolsInputSchema = {
|
|
4992
|
-
filter:
|
|
4993
|
-
includePlugins:
|
|
4994
|
-
includeSchemas:
|
|
5042
|
+
filter: import_lazy_zod6.z.string().optional().describe("Filter tools by name pattern (regex supported)"),
|
|
5043
|
+
includePlugins: import_lazy_zod6.z.boolean().default(true).describe("Include tools from plugins"),
|
|
5044
|
+
includeSchemas: import_lazy_zod6.z.boolean().default(false).describe("Include input/output schemas in the response")
|
|
4995
5045
|
};
|
|
4996
|
-
var listToolsOutputSchema =
|
|
4997
|
-
tools:
|
|
4998
|
-
|
|
4999
|
-
name:
|
|
5000
|
-
fullName:
|
|
5001
|
-
description:
|
|
5002
|
-
tags:
|
|
5003
|
-
inputSchema:
|
|
5004
|
-
outputSchema:
|
|
5046
|
+
var listToolsOutputSchema = import_lazy_zod6.z.object({
|
|
5047
|
+
tools: import_lazy_zod6.z.array(
|
|
5048
|
+
import_lazy_zod6.z.object({
|
|
5049
|
+
name: import_lazy_zod6.z.string(),
|
|
5050
|
+
fullName: import_lazy_zod6.z.string(),
|
|
5051
|
+
description: import_lazy_zod6.z.string().optional(),
|
|
5052
|
+
tags: import_lazy_zod6.z.array(import_lazy_zod6.z.string()).optional(),
|
|
5053
|
+
inputSchema: import_lazy_zod6.z.unknown().optional(),
|
|
5054
|
+
outputSchema: import_lazy_zod6.z.unknown().optional()
|
|
5005
5055
|
})
|
|
5006
5056
|
),
|
|
5007
|
-
count:
|
|
5057
|
+
count: import_lazy_zod6.z.number()
|
|
5008
5058
|
});
|
|
5009
5059
|
var ListToolsTool = class extends import_sdk6.ToolContext {
|
|
5010
5060
|
async execute(input) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontmcp/plugin-dashboard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
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.9.0"
|
|
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.9.0"
|
|
57
57
|
}
|
|
58
58
|
}
|