@modelcontextprotocol/inspector 2.7.0 → 2.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/LICENSE +216 -0
- package/README.md +13 -6
- package/clients/cli/build/index.js +1834 -280
- package/clients/tui/build/index.js +1987 -593
- package/clients/web/build/index.js +2596 -1168
- package/clients/web/dist/assets/index-DgXruQhz.js +1598 -0
- package/clients/web/dist/assets/{prism-light-CoQfbOXL.js → prism-light-leP1dqtE.js} +1 -1
- package/clients/web/dist/index.html +1 -1
- package/package.json +10 -8
- package/clients/web/dist/assets/index-DZkZ6KYt.js +0 -1598
|
@@ -165,6 +165,10 @@ var ModernListSkillsResultSchema = ListSkillsResultSchema.extend({
|
|
|
165
165
|
var GetSkillEnvelopeSchema = z.looseObject({
|
|
166
166
|
skill: SkillEntrySchema
|
|
167
167
|
});
|
|
168
|
+
var ModernGetSkillEnvelopeSchema = GetSkillEnvelopeSchema.extend({
|
|
169
|
+
ttlMs: z.int().min(0),
|
|
170
|
+
cacheScope: z.enum(["public", "private"])
|
|
171
|
+
});
|
|
168
172
|
var GetSkillResultSchema = GetSkillEnvelopeSchema.transform(
|
|
169
173
|
(result) => result.skill
|
|
170
174
|
);
|
|
@@ -788,6 +792,176 @@ var SECRET_FIELD_OAUTH_CLIENT_SECRET = "oauth-client-secret";
|
|
|
788
792
|
var SECRET_FIELD_IDP_CLIENT_SECRET = "idp-client-secret";
|
|
789
793
|
var envSecretField = (envKey) => `env:${envKey}`;
|
|
790
794
|
|
|
795
|
+
// ../../core/json/localRefs.ts
|
|
796
|
+
var SUBSCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
|
|
797
|
+
"items",
|
|
798
|
+
"contains",
|
|
799
|
+
"not",
|
|
800
|
+
"propertyNames",
|
|
801
|
+
"if",
|
|
802
|
+
"then",
|
|
803
|
+
"else",
|
|
804
|
+
"additionalProperties",
|
|
805
|
+
"unevaluatedProperties",
|
|
806
|
+
"additionalItems",
|
|
807
|
+
"unevaluatedItems",
|
|
808
|
+
"contentSchema"
|
|
809
|
+
]);
|
|
810
|
+
var SUBSCHEMA_ARRAY_KEYWORDS = /* @__PURE__ */ new Set([
|
|
811
|
+
"allOf",
|
|
812
|
+
"anyOf",
|
|
813
|
+
"oneOf",
|
|
814
|
+
"prefixItems"
|
|
815
|
+
]);
|
|
816
|
+
var SUBSCHEMA_MAP_KEYWORDS = /* @__PURE__ */ new Set([
|
|
817
|
+
"properties",
|
|
818
|
+
"patternProperties",
|
|
819
|
+
"dependentSchemas",
|
|
820
|
+
// Pre-2019 spelling of `dependentSchemas`; its array values are property
|
|
821
|
+
// name lists, which are not schemas and pass through untouched.
|
|
822
|
+
"dependencies",
|
|
823
|
+
"$defs",
|
|
824
|
+
"definitions"
|
|
825
|
+
]);
|
|
826
|
+
var NON_CONSTRAINT_SIBLINGS = /* @__PURE__ */ new Set([
|
|
827
|
+
"title",
|
|
828
|
+
"description",
|
|
829
|
+
"default",
|
|
830
|
+
"examples",
|
|
831
|
+
"deprecated",
|
|
832
|
+
"readOnly",
|
|
833
|
+
"writeOnly",
|
|
834
|
+
// Non-standard labels for `enum` values, read by both form builders.
|
|
835
|
+
"enumNames",
|
|
836
|
+
"$comment",
|
|
837
|
+
"$schema",
|
|
838
|
+
"$id",
|
|
839
|
+
"$defs",
|
|
840
|
+
"definitions"
|
|
841
|
+
]);
|
|
842
|
+
var EXPANSION_BUDGET = 1e4;
|
|
843
|
+
var MAX_DEPTH = 64;
|
|
844
|
+
var Bail = class extends Error {
|
|
845
|
+
};
|
|
846
|
+
function spend(traversal) {
|
|
847
|
+
traversal.remaining -= 1;
|
|
848
|
+
if (traversal.remaining < 0) throw new Bail();
|
|
849
|
+
}
|
|
850
|
+
function mapSubschemas(node, visit) {
|
|
851
|
+
const result = {};
|
|
852
|
+
for (const [key, value] of Object.entries(node)) {
|
|
853
|
+
let next = value;
|
|
854
|
+
if (SUBSCHEMA_KEYWORDS.has(key)) {
|
|
855
|
+
next = Array.isArray(value) ? value.map(visit) : visit(value);
|
|
856
|
+
} else if (SUBSCHEMA_ARRAY_KEYWORDS.has(key) && Array.isArray(value)) {
|
|
857
|
+
next = value.map(visit);
|
|
858
|
+
} else if (SUBSCHEMA_MAP_KEYWORDS.has(key) && isRecord(value)) {
|
|
859
|
+
next = mapNames(value, visit);
|
|
860
|
+
}
|
|
861
|
+
define(result, key, next);
|
|
862
|
+
}
|
|
863
|
+
return result;
|
|
864
|
+
}
|
|
865
|
+
function mapNames(map, visit) {
|
|
866
|
+
const result = {};
|
|
867
|
+
for (const [name, value] of Object.entries(map)) {
|
|
868
|
+
define(result, name, Array.isArray(value) ? value : visit(value));
|
|
869
|
+
}
|
|
870
|
+
return result;
|
|
871
|
+
}
|
|
872
|
+
function define(target, key, value) {
|
|
873
|
+
Object.defineProperty(target, key, {
|
|
874
|
+
value,
|
|
875
|
+
writable: true,
|
|
876
|
+
enumerable: true,
|
|
877
|
+
configurable: true
|
|
878
|
+
});
|
|
879
|
+
}
|
|
880
|
+
function isRecord(value) {
|
|
881
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
882
|
+
}
|
|
883
|
+
function resolvePointer(root, ref) {
|
|
884
|
+
if (!ref.startsWith("#")) return void 0;
|
|
885
|
+
let pointer;
|
|
886
|
+
try {
|
|
887
|
+
pointer = decodeURIComponent(ref.slice(1));
|
|
888
|
+
} catch {
|
|
889
|
+
return void 0;
|
|
890
|
+
}
|
|
891
|
+
if (pointer === "") return root;
|
|
892
|
+
if (!pointer.startsWith("/")) return void 0;
|
|
893
|
+
let current = root;
|
|
894
|
+
for (const token of pointer.slice(1).split("/")) {
|
|
895
|
+
if (/~(?![01])/.test(token)) return void 0;
|
|
896
|
+
const segment = token.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
897
|
+
if (Array.isArray(current)) {
|
|
898
|
+
const index = Number(segment);
|
|
899
|
+
if (!/^(0|[1-9]\d*)$/.test(segment) || index >= current.length) {
|
|
900
|
+
return void 0;
|
|
901
|
+
}
|
|
902
|
+
current = current[index];
|
|
903
|
+
} else if (isRecord(current) && Object.hasOwn(current, segment)) {
|
|
904
|
+
current = current[segment];
|
|
905
|
+
} else {
|
|
906
|
+
return void 0;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
return current;
|
|
910
|
+
}
|
|
911
|
+
function containsRef(node, depth) {
|
|
912
|
+
if (depth > MAX_DEPTH) throw new Bail();
|
|
913
|
+
if (!isRecord(node)) return false;
|
|
914
|
+
if (typeof node.$ref === "string") return true;
|
|
915
|
+
let found = false;
|
|
916
|
+
mapSubschemas(node, (child) => {
|
|
917
|
+
found ||= containsRef(child, depth + 1);
|
|
918
|
+
return child;
|
|
919
|
+
});
|
|
920
|
+
return found;
|
|
921
|
+
}
|
|
922
|
+
function inline(node, traversal, depth) {
|
|
923
|
+
if (depth > MAX_DEPTH) throw new Bail();
|
|
924
|
+
if (!isRecord(node)) return node;
|
|
925
|
+
if (node !== traversal.root && typeof node.$id === "string") return node;
|
|
926
|
+
spend(traversal);
|
|
927
|
+
const visit = (child) => inline(child, traversal, depth + 1);
|
|
928
|
+
const ref = node.$ref;
|
|
929
|
+
const siblingsConstrain = Object.keys(node).some(
|
|
930
|
+
(key) => key !== "$ref" && !NON_CONSTRAINT_SIBLINGS.has(key)
|
|
931
|
+
);
|
|
932
|
+
if (typeof ref === "string" && !siblingsConstrain && !traversal.active.has(ref)) {
|
|
933
|
+
const target = resolvePointer(traversal.root, ref);
|
|
934
|
+
if (isRecord(target)) {
|
|
935
|
+
traversal.active.add(ref);
|
|
936
|
+
const resolved2 = visit(target);
|
|
937
|
+
traversal.active.delete(ref);
|
|
938
|
+
const siblings = { ...node };
|
|
939
|
+
delete siblings.$ref;
|
|
940
|
+
return { ...resolved2, ...mapSubschemas(siblings, visit) };
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
return mapSubschemas(node, visit);
|
|
944
|
+
}
|
|
945
|
+
var cache = /* @__PURE__ */ new WeakMap();
|
|
946
|
+
function inlineLocalRefs(schema) {
|
|
947
|
+
if (!isRecord(schema)) return schema;
|
|
948
|
+
const cached = cache.get(schema);
|
|
949
|
+
if (cached !== void 0) return cached;
|
|
950
|
+
let resolved2;
|
|
951
|
+
try {
|
|
952
|
+
resolved2 = containsRef(schema, 0) ? inline(
|
|
953
|
+
schema,
|
|
954
|
+
{ root: schema, active: /* @__PURE__ */ new Set(), remaining: EXPANSION_BUDGET },
|
|
955
|
+
0
|
|
956
|
+
) : schema;
|
|
957
|
+
} catch (error) {
|
|
958
|
+
if (!(error instanceof Bail)) throw error;
|
|
959
|
+
resolved2 = schema;
|
|
960
|
+
}
|
|
961
|
+
cache.set(schema, resolved2);
|
|
962
|
+
return resolved2;
|
|
963
|
+
}
|
|
964
|
+
|
|
791
965
|
// ../../core/json/nullableUnion.ts
|
|
792
966
|
var RENDERABLE_TYPES = [
|
|
793
967
|
"string",
|
|
@@ -1386,7 +1560,7 @@ function convertToolParameters(tool, params) {
|
|
|
1386
1560
|
function convertParametersForSchema(inputSchema, params) {
|
|
1387
1561
|
const result = {};
|
|
1388
1562
|
const { base, branches } = resolveRootUnion(
|
|
1389
|
-
inputSchema ?? {}
|
|
1563
|
+
inlineLocalRefs(inputSchema ?? {})
|
|
1390
1564
|
);
|
|
1391
1565
|
const properties = coercionProperties(base, branches, params);
|
|
1392
1566
|
for (const [key, value] of Object.entries(params)) {
|
|
@@ -1578,7 +1752,7 @@ function oauthEndpointOverridesFromSettings(settings) {
|
|
|
1578
1752
|
};
|
|
1579
1753
|
}
|
|
1580
1754
|
function storedFieldsToInspectorSettings(stored) {
|
|
1581
|
-
const hasAny = stored.headers !== void 0 || stored.metadata !== void 0 || stored.connectionTimeout !== void 0 || stored.requestTimeout !== void 0 || stored.taskTtl !== void 0 || stored.autoRefreshOnListChanged !== void 0 || stored.paginatedLists !== void 0 || stored.advertisedExtensions !== void 0 || stored.maxFetchRequests !== void 0 || stored.skillCatalogMaxSkills !== void 0 || stored.skillCatalogMaxBytes !== void 0 || stored.oauth !== void 0 || stored.roots !== void 0 || stored.protocolEra !== void 0 || stored.modernLogLevel !== void 0 || stored.env !== void 0 || stored.cwd !== void 0;
|
|
1755
|
+
const hasAny = stored.headers !== void 0 || stored.metadata !== void 0 || stored.connectionTimeout !== void 0 || stored.requestTimeout !== void 0 || stored.taskTtl !== void 0 || stored.autoRefreshOnListChanged !== void 0 || stored.paginatedLists !== void 0 || stored.suppressNotificationStream !== void 0 || stored.advertisedExtensions !== void 0 || stored.maxFetchRequests !== void 0 || stored.skillCatalogMaxSkills !== void 0 || stored.skillCatalogMaxBytes !== void 0 || stored.oauth !== void 0 || stored.roots !== void 0 || stored.protocolEra !== void 0 || stored.modernLogLevel !== void 0 || stored.env !== void 0 || stored.cwd !== void 0;
|
|
1582
1756
|
if (!hasAny) return void 0;
|
|
1583
1757
|
const headersPairs = stored.headers ? Object.entries(stored.headers).map(([key, value]) => ({ key, value })) : [];
|
|
1584
1758
|
const settings = {
|
|
@@ -1610,6 +1784,9 @@ function storedFieldsToInspectorSettings(stored) {
|
|
|
1610
1784
|
if (isSkillCatalogLimit(stored.skillCatalogMaxBytes)) {
|
|
1611
1785
|
settings.skillCatalogMaxBytes = stored.skillCatalogMaxBytes;
|
|
1612
1786
|
}
|
|
1787
|
+
if (stored.suppressNotificationStream === true) {
|
|
1788
|
+
settings.suppressNotificationStream = true;
|
|
1789
|
+
}
|
|
1613
1790
|
if (isProtocolEra(stored.protocolEra)) {
|
|
1614
1791
|
settings.protocolEra = stored.protocolEra;
|
|
1615
1792
|
}
|
|
@@ -1661,6 +1838,7 @@ var INSPECTOR_FIELD_KEY_MAP = {
|
|
|
1661
1838
|
taskTtl: true,
|
|
1662
1839
|
autoRefreshOnListChanged: true,
|
|
1663
1840
|
paginatedLists: true,
|
|
1841
|
+
suppressNotificationStream: true,
|
|
1664
1842
|
advertisedExtensions: true,
|
|
1665
1843
|
maxFetchRequests: true,
|
|
1666
1844
|
skillCatalogMaxSkills: true,
|
|
@@ -2015,7 +2193,7 @@ function secretStorageCaveat(info) {
|
|
|
2015
2193
|
return `The secrets file could not be read (${info.encryptionUnknown}). Saving a secret will fail rather than overwrite it.`;
|
|
2016
2194
|
}
|
|
2017
2195
|
if (info.plaintext) {
|
|
2018
|
-
return info.pendingEncryption ? "Existing secrets in this file are still unencrypted (file mode 0600). They are re-encrypted the next time a secret is saved." : "Secrets are stored unencrypted (file mode 0600). Set MCP_INSPECTOR_SECRET_KEY to encrypt them.";
|
|
2196
|
+
return info.pendingEncryption ? "Existing secrets in this file are still unencrypted (file mode 0600). They are re-encrypted the next time a secret is saved." : "Secrets are stored unencrypted (file mode 0600). Set MCP_INSPECTOR_SECRET_KEY or MCP_INSPECTOR_SECRET_KEY_FILE to encrypt them.";
|
|
2019
2197
|
}
|
|
2020
2198
|
return void 0;
|
|
2021
2199
|
}
|
|
@@ -2030,9 +2208,23 @@ function secretStorageSummary(info) {
|
|
|
2030
2208
|
|
|
2031
2209
|
// ../../core/auth/node/file-secret-store.ts
|
|
2032
2210
|
import * as crypto2 from "crypto";
|
|
2211
|
+
import { readFileSync as readFileSync2, statSync as statSync2 } from "fs";
|
|
2033
2212
|
import * as fs3 from "fs/promises";
|
|
2034
2213
|
import * as path3 from "path";
|
|
2035
2214
|
|
|
2215
|
+
// ../../core/storage/own-entry.ts
|
|
2216
|
+
function setOwnEntry(map, key, value) {
|
|
2217
|
+
Object.defineProperty(map, key, {
|
|
2218
|
+
value,
|
|
2219
|
+
enumerable: true,
|
|
2220
|
+
writable: true,
|
|
2221
|
+
configurable: true
|
|
2222
|
+
});
|
|
2223
|
+
}
|
|
2224
|
+
function getOwnEntry(map, key) {
|
|
2225
|
+
return map !== void 0 && Object.hasOwn(map, key) ? map[key] : void 0;
|
|
2226
|
+
}
|
|
2227
|
+
|
|
2036
2228
|
// ../../core/auth/node/file-lock.ts
|
|
2037
2229
|
import nodeFs, { statSync, rmdirSync } from "fs";
|
|
2038
2230
|
import * as fs2 from "fs/promises";
|
|
@@ -2091,6 +2283,12 @@ var SecretStoreUnavailableError = class extends Error {
|
|
|
2091
2283
|
this.name = "SecretStoreUnavailableError";
|
|
2092
2284
|
}
|
|
2093
2285
|
};
|
|
2286
|
+
var SecretFileLockHeldError = class extends SecretStoreUnavailableError {
|
|
2287
|
+
constructor(message, options) {
|
|
2288
|
+
super(message, options);
|
|
2289
|
+
this.name = "SecretFileLockHeldError";
|
|
2290
|
+
}
|
|
2291
|
+
};
|
|
2094
2292
|
var KeychainUnavailableError = class extends SecretStoreUnavailableError {
|
|
2095
2293
|
constructor(cause) {
|
|
2096
2294
|
const message = cause instanceof Error ? cause.message : String(cause);
|
|
@@ -2121,6 +2319,7 @@ async function probeKeyringAvailable() {
|
|
|
2121
2319
|
try {
|
|
2122
2320
|
const entry = new keyring.mod.AsyncEntry(SERVICE_NAME, PROBE_ACCOUNT);
|
|
2123
2321
|
await entry.getPassword();
|
|
2322
|
+
await keyring.mod.findCredentialsAsync(SERVICE_NAME);
|
|
2124
2323
|
return { available: true };
|
|
2125
2324
|
} catch (err) {
|
|
2126
2325
|
return {
|
|
@@ -2130,6 +2329,7 @@ async function probeKeyringAvailable() {
|
|
|
2130
2329
|
}
|
|
2131
2330
|
}
|
|
2132
2331
|
var PROBE_ACCOUNT = "__inspector:probe";
|
|
2332
|
+
var isNoEntryError = (err) => err instanceof Error && /no (matching )?entry/i.test(err.message);
|
|
2133
2333
|
var KeyringSecretStore = class {
|
|
2134
2334
|
/**
|
|
2135
2335
|
* The intolerant read. Same lookup as {@link get}, minus the catch — a
|
|
@@ -2181,23 +2381,27 @@ var KeyringSecretStore = class {
|
|
|
2181
2381
|
async delete(serverId, field) {
|
|
2182
2382
|
try {
|
|
2183
2383
|
const keyring = await loadKeyring();
|
|
2184
|
-
if (!keyring.ok)
|
|
2384
|
+
if (!keyring.ok) throw new KeychainUnavailableError(keyring.err);
|
|
2185
2385
|
const entry = new keyring.mod.AsyncEntry(
|
|
2186
2386
|
SERVICE_NAME,
|
|
2187
2387
|
buildAccount(serverId, field)
|
|
2188
2388
|
);
|
|
2189
2389
|
await entry.deleteCredential();
|
|
2190
|
-
} catch {
|
|
2390
|
+
} catch (err) {
|
|
2391
|
+
if (isNoEntryError(err)) return;
|
|
2392
|
+
if (err instanceof KeychainUnavailableError) throw err;
|
|
2393
|
+
throw new KeychainUnavailableError(err);
|
|
2191
2394
|
}
|
|
2192
2395
|
}
|
|
2193
2396
|
async deleteAllForServer(serverId) {
|
|
2194
2397
|
let creds;
|
|
2195
2398
|
try {
|
|
2196
2399
|
const keyring = await loadKeyring();
|
|
2197
|
-
if (!keyring.ok)
|
|
2400
|
+
if (!keyring.ok) throw new KeychainUnavailableError(keyring.err);
|
|
2198
2401
|
creds = await keyring.mod.findCredentialsAsync(SERVICE_NAME);
|
|
2199
|
-
} catch {
|
|
2200
|
-
|
|
2402
|
+
} catch (err) {
|
|
2403
|
+
if (err instanceof KeychainUnavailableError) throw err;
|
|
2404
|
+
throw new KeychainUnavailableError(err);
|
|
2201
2405
|
}
|
|
2202
2406
|
const prefix = `${serverId}:`;
|
|
2203
2407
|
for (const c of creds) {
|
|
@@ -2211,6 +2415,25 @@ var KeyringSecretStore = class {
|
|
|
2211
2415
|
async function secretStoreGetStrict(store, serverId, field) {
|
|
2212
2416
|
return store.getStrict ? store.getStrict(serverId, field) : store.get(serverId, field);
|
|
2213
2417
|
}
|
|
2418
|
+
async function snapshotSecretFields(store, serverId, fields) {
|
|
2419
|
+
return Promise.all(
|
|
2420
|
+
fields.map(async (field) => ({
|
|
2421
|
+
serverId,
|
|
2422
|
+
field,
|
|
2423
|
+
value: await secretStoreGetStrict(store, serverId, field)
|
|
2424
|
+
}))
|
|
2425
|
+
);
|
|
2426
|
+
}
|
|
2427
|
+
async function restoreSecretFields(store, snapshot, onRestoreFailure) {
|
|
2428
|
+
for (const { serverId, field, value } of snapshot) {
|
|
2429
|
+
try {
|
|
2430
|
+
if (value === null) await store.delete(serverId, field);
|
|
2431
|
+
else await store.set(serverId, field, value);
|
|
2432
|
+
} catch (error) {
|
|
2433
|
+
onRestoreFailure(error);
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2214
2437
|
async function secretStoreGetMany(store, requests) {
|
|
2215
2438
|
if (store.getMany) return store.getMany(requests);
|
|
2216
2439
|
const out = {};
|
|
@@ -2223,16 +2446,44 @@ async function secretStoreGetMany(store, requests) {
|
|
|
2223
2446
|
);
|
|
2224
2447
|
const found = {};
|
|
2225
2448
|
for (const [field, value] of entries) {
|
|
2226
|
-
if (value !== null) found
|
|
2449
|
+
if (value !== null) setOwnEntry(found, field, value);
|
|
2450
|
+
}
|
|
2451
|
+
setOwnEntry(out, serverId, found);
|
|
2452
|
+
})
|
|
2453
|
+
);
|
|
2454
|
+
return out;
|
|
2455
|
+
}
|
|
2456
|
+
async function secretStoreGetManyStrict(store, requests) {
|
|
2457
|
+
if (store.getManyStrict) return store.getManyStrict(requests);
|
|
2458
|
+
const out = {};
|
|
2459
|
+
await Promise.all(
|
|
2460
|
+
requests.map(async ({ serverId, fields }) => {
|
|
2461
|
+
const entries = await Promise.all(
|
|
2462
|
+
fields.map(
|
|
2463
|
+
async (field) => [
|
|
2464
|
+
field,
|
|
2465
|
+
await secretStoreGetStrict(store, serverId, field)
|
|
2466
|
+
]
|
|
2467
|
+
)
|
|
2468
|
+
);
|
|
2469
|
+
const found = {};
|
|
2470
|
+
for (const [field, value] of entries) {
|
|
2471
|
+
if (value !== null) setOwnEntry(found, field, value);
|
|
2227
2472
|
}
|
|
2228
|
-
out
|
|
2473
|
+
setOwnEntry(out, serverId, found);
|
|
2229
2474
|
})
|
|
2230
2475
|
);
|
|
2231
2476
|
return out;
|
|
2232
2477
|
}
|
|
2478
|
+
async function settleStoreMutations(mutations) {
|
|
2479
|
+
const results = await Promise.allSettled(mutations);
|
|
2480
|
+
for (const result of results) {
|
|
2481
|
+
if (result.status === "rejected") throw result.reason;
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2233
2484
|
async function secretStoreSetMany(store, serverId, values) {
|
|
2234
2485
|
if (store.setMany) return store.setMany(serverId, values);
|
|
2235
|
-
await
|
|
2486
|
+
await settleStoreMutations(
|
|
2236
2487
|
Object.entries(values).map(
|
|
2237
2488
|
([field, value]) => store.set(serverId, field, value)
|
|
2238
2489
|
)
|
|
@@ -2401,7 +2652,7 @@ async function openSecretFileLock(filePath) {
|
|
|
2401
2652
|
});
|
|
2402
2653
|
} catch (err) {
|
|
2403
2654
|
if (isStuckOrHeld(err, lockPathOf(target))) {
|
|
2404
|
-
throw new
|
|
2655
|
+
throw new SecretFileLockHeldError(
|
|
2405
2656
|
`Could not save to the secrets file at ${target}: its lock (${lockPathOf(target)}) was still held after the ${Math.round(RETRY_BUDGET_MS / 1e3)} seconds this save waited. Its secrets are intact; the value you just entered was not saved. If no other Inspector is running, remove that lock and try again.`
|
|
2406
2657
|
);
|
|
2407
2658
|
}
|
|
@@ -2460,7 +2711,63 @@ var SCRYPT_N = 16384;
|
|
|
2460
2711
|
var SCRYPT_R = 8;
|
|
2461
2712
|
var SCRYPT_P = 1;
|
|
2462
2713
|
var SECRET_KEY_ENV = "MCP_INSPECTOR_SECRET_KEY";
|
|
2714
|
+
var SECRET_KEY_FILE_ENV = "MCP_INSPECTOR_SECRET_KEY_FILE";
|
|
2715
|
+
function isSameFile(a, b) {
|
|
2716
|
+
if (path3.resolve(a) === path3.resolve(b)) return true;
|
|
2717
|
+
try {
|
|
2718
|
+
const sa = statSync2(a);
|
|
2719
|
+
const sb = statSync2(b);
|
|
2720
|
+
return sa.dev === sb.dev && sa.ino === sb.ino;
|
|
2721
|
+
} catch {
|
|
2722
|
+
return false;
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
function resolveSecretPassphrase(env2 = process.env, secretFilePath) {
|
|
2726
|
+
const direct = env2[SECRET_KEY_ENV];
|
|
2727
|
+
const hasDirect = direct !== void 0 && direct.trim() !== "";
|
|
2728
|
+
const rawKeyFile = env2[SECRET_KEY_FILE_ENV];
|
|
2729
|
+
const wantsKeyFile = rawKeyFile !== void 0;
|
|
2730
|
+
const keyFile = rawKeyFile?.trim();
|
|
2731
|
+
if (hasDirect && wantsKeyFile) {
|
|
2732
|
+
return {
|
|
2733
|
+
problem: `both ${SECRET_KEY_ENV} and ${SECRET_KEY_FILE_ENV} are set; set only one`
|
|
2734
|
+
};
|
|
2735
|
+
}
|
|
2736
|
+
if (hasDirect) return { passphrase: direct };
|
|
2737
|
+
if (!wantsKeyFile) return {};
|
|
2738
|
+
if (!keyFile) {
|
|
2739
|
+
return { problem: `${SECRET_KEY_FILE_ENV} is set but empty` };
|
|
2740
|
+
}
|
|
2741
|
+
const resolved2 = path3.resolve(keyFile);
|
|
2742
|
+
if (secretFilePath !== void 0 && isSameFile(resolved2, secretFilePath)) {
|
|
2743
|
+
return {
|
|
2744
|
+
problem: `${SECRET_KEY_FILE_ENV} (${resolved2}) is the secrets file itself; point it at a separate key file`
|
|
2745
|
+
};
|
|
2746
|
+
}
|
|
2747
|
+
let contents;
|
|
2748
|
+
try {
|
|
2749
|
+
contents = readFileSync2(resolved2, "utf-8");
|
|
2750
|
+
} catch (err) {
|
|
2751
|
+
return {
|
|
2752
|
+
// `String(err)` rather than `.message`: `readFileSync` only ever throws
|
|
2753
|
+
// an `Error`, so an `instanceof` guard would be a branch no test can take.
|
|
2754
|
+
problem: `${SECRET_KEY_FILE_ENV} (${resolved2}) could not be read: ${String(err)}`
|
|
2755
|
+
};
|
|
2756
|
+
}
|
|
2757
|
+
const passphrase = contents.replace(/[\r\n]+$/, "");
|
|
2758
|
+
if (passphrase.trim() === "") {
|
|
2759
|
+
return { problem: `${SECRET_KEY_FILE_ENV} (${resolved2}) is empty` };
|
|
2760
|
+
}
|
|
2761
|
+
return { passphrase };
|
|
2762
|
+
}
|
|
2463
2763
|
var buildAccount2 = (serverId, field) => `${serverId}:${field}`;
|
|
2764
|
+
function assertSecretString(field, value) {
|
|
2765
|
+
if (typeof value !== "string") {
|
|
2766
|
+
throw new TypeError(
|
|
2767
|
+
`Refusing to store a non-string secret value (${typeof value}) for "${field}": the secrets file holds only strings, and writing this would make the whole file unreadable.`
|
|
2768
|
+
);
|
|
2769
|
+
}
|
|
2770
|
+
}
|
|
2464
2771
|
function asSecretMap(value, filePath) {
|
|
2465
2772
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
2466
2773
|
throw new SecretStoreUnavailableError(
|
|
@@ -2479,7 +2786,7 @@ function asSecretMap(value, filePath) {
|
|
|
2479
2786
|
var SecretFileKeyMismatchError = class extends SecretStoreUnavailableError {
|
|
2480
2787
|
constructor(filePath, hasKey) {
|
|
2481
2788
|
super(
|
|
2482
|
-
hasKey ? `The secrets file at ${filePath} could not be decrypted with the current ${SECRET_KEY_ENV}. Refusing to write, which would overwrite the existing secrets. Restore the original passphrase, or delete the file to start over.` : `The secrets file at ${filePath} is encrypted but ${SECRET_KEY_ENV} is not set. Refusing to write, which would overwrite the existing secrets. Set the passphrase this file was written with, or delete the file to start over.`
|
|
2789
|
+
hasKey ? `The secrets file at ${filePath} could not be decrypted with the current ${SECRET_KEY_ENV} (or ${SECRET_KEY_FILE_ENV}). Refusing to write, which would overwrite the existing secrets. Restore the original passphrase, or delete the file to start over.` : `The secrets file at ${filePath} is encrypted but ${SECRET_KEY_ENV} is not set (nor ${SECRET_KEY_FILE_ENV}). Refusing to write, which would overwrite the existing secrets. Set the passphrase this file was written with, or delete the file to start over.`
|
|
2483
2790
|
);
|
|
2484
2791
|
this.name = "SecretFileKeyMismatchError";
|
|
2485
2792
|
}
|
|
@@ -2537,10 +2844,17 @@ function encryptedEnvelopeProblem(parsed) {
|
|
|
2537
2844
|
var FileSecretStore = class {
|
|
2538
2845
|
filePath;
|
|
2539
2846
|
passphrase;
|
|
2847
|
+
/**
|
|
2848
|
+
* Why a configured key could not be obtained. While set, every read throws
|
|
2849
|
+
* and every write refuses — see {@link SecretPassphrase}.
|
|
2850
|
+
*/
|
|
2851
|
+
keyProblem;
|
|
2540
2852
|
constructor(options) {
|
|
2541
2853
|
this.filePath = options.filePath;
|
|
2542
|
-
const
|
|
2854
|
+
const resolved2 = options.passphrase !== void 0 ? { passphrase: options.passphrase } : resolveSecretPassphrase(process.env, this.filePath);
|
|
2855
|
+
const raw = resolved2.passphrase;
|
|
2543
2856
|
this.passphrase = raw && raw.trim() ? raw : void 0;
|
|
2857
|
+
this.keyProblem = resolved2.problem;
|
|
2544
2858
|
}
|
|
2545
2859
|
/**
|
|
2546
2860
|
* True when the *next write* will encrypt. This is the configured policy,
|
|
@@ -2555,7 +2869,8 @@ var FileSecretStore = class {
|
|
|
2555
2869
|
* no file yet, or when it cannot be read or parsed.
|
|
2556
2870
|
*
|
|
2557
2871
|
* Separate from {@link encrypted} because the two genuinely disagree for a
|
|
2558
|
-
* whole session: adding `MCP_INSPECTOR_SECRET_KEY`
|
|
2872
|
+
* whole session: adding a passphrase (`MCP_INSPECTOR_SECRET_KEY` or
|
|
2873
|
+
* `MCP_INSPECTOR_SECRET_KEY_FILE`) to an install that
|
|
2559
2874
|
* already has a plaintext file flips `encrypted` to true immediately,
|
|
2560
2875
|
* while the bytes stay readable until the next `set`. A descriptor built
|
|
2561
2876
|
* from the policy would tell that user "File (encrypted)" while their
|
|
@@ -2579,6 +2894,9 @@ var FileSecretStore = class {
|
|
|
2579
2894
|
* `set` is in fact about to refuse.
|
|
2580
2895
|
*/
|
|
2581
2896
|
async readOnDiskEncryption() {
|
|
2897
|
+
if (this.keyProblem !== void 0) {
|
|
2898
|
+
return { state: "unreadable", detail: this.keyProblem };
|
|
2899
|
+
}
|
|
2582
2900
|
let raw;
|
|
2583
2901
|
try {
|
|
2584
2902
|
raw = await readStoreFile(this.filePath);
|
|
@@ -2616,7 +2934,7 @@ var FileSecretStore = class {
|
|
|
2616
2934
|
} catch (err) {
|
|
2617
2935
|
return {
|
|
2618
2936
|
state: "unreadable",
|
|
2619
|
-
detail: err instanceof SecretFileKeyMismatchError ? `it cannot be decrypted with the current ${SECRET_KEY_ENV}` : err instanceof Error ? err.message : String(err)
|
|
2937
|
+
detail: err instanceof SecretFileKeyMismatchError ? `it cannot be decrypted with the current ${SECRET_KEY_ENV} (or ${SECRET_KEY_FILE_ENV})` : err instanceof Error ? err.message : String(err)
|
|
2620
2938
|
};
|
|
2621
2939
|
}
|
|
2622
2940
|
return { state: "encrypted" };
|
|
@@ -2667,6 +2985,11 @@ var FileSecretStore = class {
|
|
|
2667
2985
|
return this.serialize(() => this.readMap());
|
|
2668
2986
|
}
|
|
2669
2987
|
async readMap() {
|
|
2988
|
+
if (this.keyProblem !== void 0) {
|
|
2989
|
+
throw new SecretStoreUnavailableError(
|
|
2990
|
+
`The secrets file at ${this.filePath} cannot be used: ${this.keyProblem}. Refusing to read or write it rather than store secrets unencrypted.`
|
|
2991
|
+
);
|
|
2992
|
+
}
|
|
2670
2993
|
const raw = await readStoreFile(this.filePath);
|
|
2671
2994
|
if (raw === null) return null;
|
|
2672
2995
|
let parsed;
|
|
@@ -2703,7 +3026,9 @@ var FileSecretStore = class {
|
|
|
2703
3026
|
let plain;
|
|
2704
3027
|
try {
|
|
2705
3028
|
const key = await this.deriveKey(parsed.kdf);
|
|
2706
|
-
const decipher = crypto2.createDecipheriv(CIPHER, key, parts.iv
|
|
3029
|
+
const decipher = crypto2.createDecipheriv(CIPHER, key, parts.iv, {
|
|
3030
|
+
authTagLength: GCM_TAG_BYTES
|
|
3031
|
+
});
|
|
2707
3032
|
decipher.setAuthTag(parts.tag);
|
|
2708
3033
|
plain = Buffer.concat([
|
|
2709
3034
|
decipher.update(parts.body),
|
|
@@ -2737,7 +3062,9 @@ var FileSecretStore = class {
|
|
|
2737
3062
|
};
|
|
2738
3063
|
const key = await this.deriveKey(kdf);
|
|
2739
3064
|
const iv = crypto2.randomBytes(IV_BYTES);
|
|
2740
|
-
const cipher = crypto2.createCipheriv(CIPHER, key, iv
|
|
3065
|
+
const cipher = crypto2.createCipheriv(CIPHER, key, iv, {
|
|
3066
|
+
authTagLength: GCM_TAG_BYTES
|
|
3067
|
+
});
|
|
2741
3068
|
const body = Buffer.concat([
|
|
2742
3069
|
cipher.update(JSON.stringify(map), "utf-8"),
|
|
2743
3070
|
cipher.final()
|
|
@@ -2902,9 +3229,36 @@ var FileSecretStore = class {
|
|
|
2902
3229
|
const found = {};
|
|
2903
3230
|
for (const field of fields) {
|
|
2904
3231
|
const value = map?.[buildAccount2(serverId, field)];
|
|
2905
|
-
if (value !== void 0) found
|
|
3232
|
+
if (value !== void 0) setOwnEntry(found, field, value);
|
|
2906
3233
|
}
|
|
2907
|
-
out
|
|
3234
|
+
setOwnEntry(out, serverId, found);
|
|
3235
|
+
}
|
|
3236
|
+
return out;
|
|
3237
|
+
}
|
|
3238
|
+
/**
|
|
3239
|
+
* Bulk twin of {@link getStrict}: the same single-pass read as
|
|
3240
|
+
* {@link getMany}, but an unreadable store throws (with the typed advice
|
|
3241
|
+
* {@link getStrict} attaches) instead of yielding no fields — required by
|
|
3242
|
+
* OAuth read hydration, whose result later drives store deletions.
|
|
3243
|
+
*/
|
|
3244
|
+
async getManyStrict(requests) {
|
|
3245
|
+
let map;
|
|
3246
|
+
try {
|
|
3247
|
+
map = await this.serialize(() => this.readMap());
|
|
3248
|
+
} catch (err) {
|
|
3249
|
+
if (err instanceof SecretStoreUnavailableError) throw err;
|
|
3250
|
+
throw new SecretStoreUnavailableError(
|
|
3251
|
+
`Could not read the secrets file at ${this.filePath}: ${err instanceof Error ? err.message : String(err)}`
|
|
3252
|
+
);
|
|
3253
|
+
}
|
|
3254
|
+
const out = {};
|
|
3255
|
+
for (const { serverId, fields } of requests) {
|
|
3256
|
+
const found = {};
|
|
3257
|
+
for (const field of fields) {
|
|
3258
|
+
const value = map?.[buildAccount2(serverId, field)];
|
|
3259
|
+
if (value !== void 0) setOwnEntry(found, field, value);
|
|
3260
|
+
}
|
|
3261
|
+
setOwnEntry(out, serverId, found);
|
|
2908
3262
|
}
|
|
2909
3263
|
return out;
|
|
2910
3264
|
}
|
|
@@ -2948,6 +3302,9 @@ var FileSecretStore = class {
|
|
|
2948
3302
|
*/
|
|
2949
3303
|
async setMany(serverId, values) {
|
|
2950
3304
|
if (Object.keys(values).length === 0) return;
|
|
3305
|
+
for (const [field, value] of Object.entries(values)) {
|
|
3306
|
+
assertSecretString(field, value);
|
|
3307
|
+
}
|
|
2951
3308
|
await this.serialize(
|
|
2952
3309
|
() => this.mutate((map) => {
|
|
2953
3310
|
const next = { ...map };
|
|
@@ -2959,6 +3316,7 @@ var FileSecretStore = class {
|
|
|
2959
3316
|
);
|
|
2960
3317
|
}
|
|
2961
3318
|
async set(serverId, field, value) {
|
|
3319
|
+
assertSecretString(field, value);
|
|
2962
3320
|
await this.serialize(
|
|
2963
3321
|
() => this.mutate((map) => ({
|
|
2964
3322
|
...map,
|
|
@@ -2974,9 +3332,11 @@ var FileSecretStore = class {
|
|
|
2974
3332
|
await this.deleteWhere((key) => key.startsWith(prefix));
|
|
2975
3333
|
}
|
|
2976
3334
|
/**
|
|
2977
|
-
* Shared delete body.
|
|
2978
|
-
*
|
|
2979
|
-
*
|
|
3335
|
+
* Shared delete body. Same confirmed-delete contract as the keyring
|
|
3336
|
+
* store: a deletion that cannot be confirmed (unreadable file, failed
|
|
3337
|
+
* decrypt, failed write) must escape, because reporting success would
|
|
3338
|
+
* let a caller commit state that assumes the entry is gone — once the
|
|
3339
|
+
* file becomes readable again, a later read would resurrect it.
|
|
2980
3340
|
*/
|
|
2981
3341
|
async deleteWhere(match) {
|
|
2982
3342
|
try {
|
|
@@ -2989,7 +3349,12 @@ var FileSecretStore = class {
|
|
|
2989
3349
|
return next;
|
|
2990
3350
|
})
|
|
2991
3351
|
);
|
|
2992
|
-
} catch {
|
|
3352
|
+
} catch (err) {
|
|
3353
|
+
if (err instanceof SecretStoreUnavailableError) throw err;
|
|
3354
|
+
throw new SecretStoreUnavailableError(
|
|
3355
|
+
`Could not delete from the secrets file: ${err instanceof Error ? err.message : String(err)}`,
|
|
3356
|
+
{ cause: err }
|
|
3357
|
+
);
|
|
2993
3358
|
}
|
|
2994
3359
|
}
|
|
2995
3360
|
};
|
|
@@ -3022,6 +3387,7 @@ async function readSecretFilePermissions(filePath) {
|
|
|
3022
3387
|
var SECRET_STORE_ENV = "MCP_INSPECTOR_SECRET_STORE";
|
|
3023
3388
|
var SECRET_FILE_ENV = "MCP_INSPECTOR_SECRET_FILE";
|
|
3024
3389
|
var STORAGE_DIR_ENV = "MCP_STORAGE_DIR";
|
|
3390
|
+
var SECRET_STORAGE_DOCS_URL = "https://github.com/modelcontextprotocol/inspector/blob/main/docs/secret-storage.md";
|
|
3025
3391
|
var KINDS = ["keyring", "file", "memory"];
|
|
3026
3392
|
function parseSecretStoreEnv(raw) {
|
|
3027
3393
|
const value = raw?.trim().toLowerCase();
|
|
@@ -3164,6 +3530,11 @@ function warnAboutSecretStorage(info) {
|
|
|
3164
3530
|
}
|
|
3165
3531
|
const caveat = secretStorageCaveat(info);
|
|
3166
3532
|
if (caveat) console.warn(`[mcp-inspector] ${caveat}`);
|
|
3533
|
+
if (info.reason === "fallback" || caveat) {
|
|
3534
|
+
console.warn(
|
|
3535
|
+
`[mcp-inspector] How the secret store is chosen, and how to secure it: ${SECRET_STORAGE_DOCS_URL}`
|
|
3536
|
+
);
|
|
3537
|
+
}
|
|
3167
3538
|
}
|
|
3168
3539
|
var resolved;
|
|
3169
3540
|
function resolveSecretStore() {
|
|
@@ -3359,6 +3730,9 @@ var DeferredSecretStore = class {
|
|
|
3359
3730
|
async getMany(requests) {
|
|
3360
3731
|
return secretStoreGetMany(await this.target(), requests);
|
|
3361
3732
|
}
|
|
3733
|
+
async getManyStrict(requests) {
|
|
3734
|
+
return secretStoreGetManyStrict(await this.target(), requests);
|
|
3735
|
+
}
|
|
3362
3736
|
async get(serverId, field) {
|
|
3363
3737
|
return (await this.target()).get(serverId, field);
|
|
3364
3738
|
}
|
|
@@ -3576,12 +3950,31 @@ function redactJsonValue(value) {
|
|
|
3576
3950
|
}
|
|
3577
3951
|
return value;
|
|
3578
3952
|
}
|
|
3953
|
+
function joinSensitiveContinuations(body) {
|
|
3954
|
+
const out = [];
|
|
3955
|
+
let sensitiveAt = -1;
|
|
3956
|
+
for (const pair of body.split("&")) {
|
|
3957
|
+
const eq = pair.indexOf("=");
|
|
3958
|
+
if (eq === -1) {
|
|
3959
|
+
if (sensitiveAt !== -1 && pair.length > 0) {
|
|
3960
|
+
out[sensitiveAt] += `%26${pair}`;
|
|
3961
|
+
} else {
|
|
3962
|
+
out.push(pair);
|
|
3963
|
+
}
|
|
3964
|
+
continue;
|
|
3965
|
+
}
|
|
3966
|
+
const [key] = new URLSearchParams(pair).keys();
|
|
3967
|
+
sensitiveAt = isSensitiveField(key) && eq < pair.length - 1 ? out.length : -1;
|
|
3968
|
+
out.push(pair);
|
|
3969
|
+
}
|
|
3970
|
+
return out.join("&");
|
|
3971
|
+
}
|
|
3579
3972
|
function redactBody(body, contentType) {
|
|
3580
3973
|
if (!body) return body;
|
|
3581
3974
|
const type = (contentType ?? "").toLowerCase();
|
|
3582
3975
|
if (type.includes("application/x-www-form-urlencoded")) {
|
|
3583
3976
|
try {
|
|
3584
|
-
const params = new URLSearchParams(body);
|
|
3977
|
+
const params = new URLSearchParams(joinSensitiveContinuations(body));
|
|
3585
3978
|
let changed = false;
|
|
3586
3979
|
for (const key of new Set(params.keys())) {
|
|
3587
3980
|
if (isSensitiveField(key)) {
|
|
@@ -4305,6 +4698,73 @@ function createProxyFetch() {
|
|
|
4305
4698
|
};
|
|
4306
4699
|
}
|
|
4307
4700
|
|
|
4701
|
+
// ../../core/mcp/node/notificationHeadersFetch.ts
|
|
4702
|
+
import { PROTOCOL_VERSION_META_KEY } from "@modelcontextprotocol/client";
|
|
4703
|
+
function createNotificationHeadersFetch(baseFetch) {
|
|
4704
|
+
return (input, init) => {
|
|
4705
|
+
const method = modernNotificationMethod(init);
|
|
4706
|
+
if (method === void 0) return baseFetch(input, init);
|
|
4707
|
+
const headers = new Headers(init?.headers);
|
|
4708
|
+
headers.set("mcp-protocol-version", method.version);
|
|
4709
|
+
headers.set("mcp-method", method.method);
|
|
4710
|
+
return baseFetch(input, { ...init, headers });
|
|
4711
|
+
};
|
|
4712
|
+
}
|
|
4713
|
+
function modernNotificationMethod(init) {
|
|
4714
|
+
if (init?.method?.toUpperCase() !== "POST") return void 0;
|
|
4715
|
+
if (typeof init.body !== "string") return void 0;
|
|
4716
|
+
let message;
|
|
4717
|
+
try {
|
|
4718
|
+
message = JSON.parse(init.body);
|
|
4719
|
+
} catch {
|
|
4720
|
+
return void 0;
|
|
4721
|
+
}
|
|
4722
|
+
if (!isRecord2(message) || "id" in message) return void 0;
|
|
4723
|
+
if (typeof message.method !== "string") return void 0;
|
|
4724
|
+
const meta = isRecord2(message.params) ? message.params._meta : void 0;
|
|
4725
|
+
const version = isRecord2(meta) ? meta[PROTOCOL_VERSION_META_KEY] : void 0;
|
|
4726
|
+
if (typeof version !== "string" || version < MODERN_PROTOCOL_VERSION) {
|
|
4727
|
+
return void 0;
|
|
4728
|
+
}
|
|
4729
|
+
return { method: message.method, version };
|
|
4730
|
+
}
|
|
4731
|
+
function isRecord2(value) {
|
|
4732
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4733
|
+
}
|
|
4734
|
+
|
|
4735
|
+
// ../../core/mcp/node/suppressNotificationStreamFetch.ts
|
|
4736
|
+
function createSuppressNotificationStreamFetch(baseFetch, endpoint) {
|
|
4737
|
+
return async (input, init) => {
|
|
4738
|
+
if (isStandaloneStreamRequest(input, init, endpoint)) {
|
|
4739
|
+
return new Response(null, {
|
|
4740
|
+
status: 405,
|
|
4741
|
+
statusText: "Method Not Allowed"
|
|
4742
|
+
});
|
|
4743
|
+
}
|
|
4744
|
+
return baseFetch(input, init);
|
|
4745
|
+
};
|
|
4746
|
+
}
|
|
4747
|
+
function requestUrl(input) {
|
|
4748
|
+
const raw = input instanceof Request ? input.url : input instanceof URL ? input.href : input;
|
|
4749
|
+
try {
|
|
4750
|
+
return new URL(raw);
|
|
4751
|
+
} catch {
|
|
4752
|
+
return void 0;
|
|
4753
|
+
}
|
|
4754
|
+
}
|
|
4755
|
+
function isStandaloneStreamRequest(input, init, endpoint) {
|
|
4756
|
+
const request = input instanceof Request ? input : void 0;
|
|
4757
|
+
const method = (init?.method ?? request?.method ?? "GET").toUpperCase();
|
|
4758
|
+
if (method !== "GET") return false;
|
|
4759
|
+
const url = requestUrl(input);
|
|
4760
|
+
if (!url || url.origin !== endpoint.origin || url.pathname !== endpoint.pathname || url.search !== endpoint.search) {
|
|
4761
|
+
return false;
|
|
4762
|
+
}
|
|
4763
|
+
const headers = new Headers(init?.headers ?? request?.headers);
|
|
4764
|
+
const accept = headers.get("accept")?.toLowerCase() ?? "";
|
|
4765
|
+
return accept.includes("text/event-stream") && !headers.has("last-event-id");
|
|
4766
|
+
}
|
|
4767
|
+
|
|
4308
4768
|
// ../../core/mcp/node/transport.ts
|
|
4309
4769
|
function headersFromSettings(settings) {
|
|
4310
4770
|
if (!settings || settings.headers.length === 0) return void 0;
|
|
@@ -4392,10 +4852,14 @@ function createTransportNode(config, options = {}) {
|
|
|
4392
4852
|
...httpConfig.requestInit,
|
|
4393
4853
|
...headers && { headers }
|
|
4394
4854
|
};
|
|
4855
|
+
const stampedFetch = createNotificationHeadersFetch(
|
|
4856
|
+
fetchWithOptionalAuthIntercept
|
|
4857
|
+
);
|
|
4858
|
+
const httpFetch = settings?.suppressNotificationStream === true ? createSuppressNotificationStreamFetch(stampedFetch, url) : stampedFetch;
|
|
4395
4859
|
const transport = new StreamableHTTPClientTransport(url, {
|
|
4396
4860
|
authProvider,
|
|
4397
4861
|
requestInit,
|
|
4398
|
-
fetch:
|
|
4862
|
+
fetch: httpFetch,
|
|
4399
4863
|
// SEP-2350: how the transport reacts to a `403 insufficient_scope`
|
|
4400
4864
|
// challenge. Defaults to the SDK's `reauthorize` when unset.
|
|
4401
4865
|
...settings?.oauthOnInsufficientScope && {
|
|
@@ -4544,6 +5008,23 @@ function mergeSecretsIntoClientConfig(config, secrets) {
|
|
|
4544
5008
|
}
|
|
4545
5009
|
|
|
4546
5010
|
// ../../core/client/node-persistence.ts
|
|
5011
|
+
async function withClientConfigLock(filePath, action, body) {
|
|
5012
|
+
let entered = false;
|
|
5013
|
+
try {
|
|
5014
|
+
return await withSecretFileLock(filePath, async () => {
|
|
5015
|
+
entered = true;
|
|
5016
|
+
return body();
|
|
5017
|
+
});
|
|
5018
|
+
} catch (error) {
|
|
5019
|
+
if (!entered && error instanceof SecretFileLockHeldError) {
|
|
5020
|
+
throw new SecretFileLockHeldError(
|
|
5021
|
+
`Could not ${action} the client configuration: the file at ${filePath} is locked by another Inspector process and did not become available.`,
|
|
5022
|
+
{ cause: error }
|
|
5023
|
+
);
|
|
5024
|
+
}
|
|
5025
|
+
throw error;
|
|
5026
|
+
}
|
|
5027
|
+
}
|
|
4547
5028
|
async function readIdpSecretFromKeychain(secretStore) {
|
|
4548
5029
|
const secret = await secretStore.get(
|
|
4549
5030
|
CLIENT_KEYCHAIN_ID,
|
|
@@ -4553,29 +5034,39 @@ async function readIdpSecretFromKeychain(secretStore) {
|
|
|
4553
5034
|
return { [SECRET_FIELD_IDP_CLIENT_SECRET]: secret };
|
|
4554
5035
|
}
|
|
4555
5036
|
async function migrateClientPlaintextSecret(filePath, config, secretStore) {
|
|
4556
|
-
const { stripped, secrets } = extractSecretsFromClientConfig(config);
|
|
4557
|
-
const value = secrets[SECRET_FIELD_IDP_CLIENT_SECRET];
|
|
4558
|
-
if (!value) return config;
|
|
4559
5037
|
try {
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
5038
|
+
return await withClientConfigLock(filePath, "migrate", async () => {
|
|
5039
|
+
const raw = await readStoreFile(filePath);
|
|
5040
|
+
if (raw === null) return {};
|
|
5041
|
+
const fresh = parseClientConfig(parseStore(raw));
|
|
5042
|
+
const { stripped, secrets } = extractSecretsFromClientConfig(fresh);
|
|
5043
|
+
const value = secrets[SECRET_FIELD_IDP_CLIENT_SECRET];
|
|
5044
|
+
if (!value) return fresh;
|
|
5045
|
+
try {
|
|
5046
|
+
const existing = await secretStoreGetStrict(
|
|
5047
|
+
secretStore,
|
|
5048
|
+
CLIENT_KEYCHAIN_ID,
|
|
5049
|
+
SECRET_FIELD_IDP_CLIENT_SECRET
|
|
5050
|
+
);
|
|
5051
|
+
if (existing === null) {
|
|
5052
|
+
await secretStore.set(
|
|
5053
|
+
CLIENT_KEYCHAIN_ID,
|
|
5054
|
+
SECRET_FIELD_IDP_CLIENT_SECRET,
|
|
5055
|
+
value
|
|
5056
|
+
);
|
|
5057
|
+
}
|
|
5058
|
+
if (!await secretStoreIsDurable(secretStore)) return fresh;
|
|
5059
|
+
await writeStoreFile(filePath, serializeStore(stripped));
|
|
5060
|
+
return stripped;
|
|
5061
|
+
} catch (err) {
|
|
5062
|
+
if (err instanceof SecretStoreUnavailableError) {
|
|
5063
|
+
return fresh;
|
|
5064
|
+
}
|
|
5065
|
+
throw err;
|
|
5066
|
+
}
|
|
5067
|
+
});
|
|
4575
5068
|
} catch (err) {
|
|
4576
|
-
if (err instanceof
|
|
4577
|
-
return config;
|
|
4578
|
-
}
|
|
5069
|
+
if (err instanceof SecretFileLockHeldError) return config;
|
|
4579
5070
|
throw err;
|
|
4580
5071
|
}
|
|
4581
5072
|
}
|
|
@@ -4778,7 +5269,7 @@ import {
|
|
|
4778
5269
|
useCallback as useCallback14,
|
|
4779
5270
|
useRef as useRef15
|
|
4780
5271
|
} from "react";
|
|
4781
|
-
import { Box as
|
|
5272
|
+
import { Box as Box29, Text as Text26, useInput as useInput22, useApp } from "ink";
|
|
4782
5273
|
|
|
4783
5274
|
// ../../core/mcp/inspectorClient.ts
|
|
4784
5275
|
import { Client } from "@modelcontextprotocol/client";
|
|
@@ -4826,14 +5317,14 @@ var OBJECT_VALUED_SUBSCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
4826
5317
|
function pathName(path6) {
|
|
4827
5318
|
return path6.length === 0 ? "<root>" : path6.join(".");
|
|
4828
5319
|
}
|
|
4829
|
-
function
|
|
5320
|
+
function isRecord3(node) {
|
|
4830
5321
|
return node !== null && typeof node === "object";
|
|
4831
5322
|
}
|
|
4832
5323
|
function scanXMcpHeaderDeclarations(inputSchema) {
|
|
4833
5324
|
const declarations = [];
|
|
4834
5325
|
const seenLower = /* @__PURE__ */ new Map();
|
|
4835
5326
|
const visit = (node, path6, reachable) => {
|
|
4836
|
-
if (!
|
|
5327
|
+
if (!isRecord3(node)) return void 0;
|
|
4837
5328
|
const schema = node;
|
|
4838
5329
|
if (X_MCP_HEADER_KEY in schema) {
|
|
4839
5330
|
if (!reachable || path6.length === 0) {
|
|
@@ -4859,7 +5350,7 @@ function scanXMcpHeaderDeclarations(inputSchema) {
|
|
|
4859
5350
|
declarations.push({ path: path6, headerName: raw, type });
|
|
4860
5351
|
}
|
|
4861
5352
|
const properties = schema.properties;
|
|
4862
|
-
if (
|
|
5353
|
+
if (isRecord3(properties)) {
|
|
4863
5354
|
for (const [key, child] of Object.entries(properties)) {
|
|
4864
5355
|
const fault2 = visit(child, [...path6, key], reachable);
|
|
4865
5356
|
if (fault2 !== void 0) return fault2;
|
|
@@ -4868,7 +5359,7 @@ function scanXMcpHeaderDeclarations(inputSchema) {
|
|
|
4868
5359
|
for (const k of NON_REACHABLE_SUBSCHEMA_KEYWORDS) {
|
|
4869
5360
|
const sub = schema[k];
|
|
4870
5361
|
if (sub === void 0) continue;
|
|
4871
|
-
const branches = Array.isArray(sub) ? sub :
|
|
5362
|
+
const branches = Array.isArray(sub) ? sub : isRecord3(sub) && OBJECT_VALUED_SUBSCHEMA_KEYWORDS.has(k) ? Object.values(sub) : [sub];
|
|
4872
5363
|
for (const branch of branches) {
|
|
4873
5364
|
const fault2 = visit(branch, [...path6, `<${k}>`], false);
|
|
4874
5365
|
if (fault2 !== void 0) return fault2;
|
|
@@ -5100,7 +5591,7 @@ import {
|
|
|
5100
5591
|
LOG_LEVEL_META_KEY,
|
|
5101
5592
|
CLIENT_CAPABILITIES_META_KEY,
|
|
5102
5593
|
CLIENT_INFO_META_KEY,
|
|
5103
|
-
PROTOCOL_VERSION_META_KEY,
|
|
5594
|
+
PROTOCOL_VERSION_META_KEY as PROTOCOL_VERSION_META_KEY2,
|
|
5104
5595
|
RELATED_TASK_META_KEY as RELATED_TASK_META_KEY3
|
|
5105
5596
|
} from "@modelcontextprotocol/client";
|
|
5106
5597
|
|
|
@@ -5169,10 +5660,13 @@ var ADVERTISABLE_EXTENSIONS = [
|
|
|
5169
5660
|
{
|
|
5170
5661
|
key: UI_EXTENSION_KEY,
|
|
5171
5662
|
label: "MCP Apps UI (io.modelcontextprotocol/ui)",
|
|
5172
|
-
// The MCP Apps UI extension
|
|
5173
|
-
//
|
|
5174
|
-
// a
|
|
5663
|
+
// The MCP Apps UI extension, advertised with the App resource MIME type the
|
|
5664
|
+
// Inspector renders — a conforming server checks the `mimeTypes` before
|
|
5665
|
+
// serving a UI resource. Default-on only where Apps can actually be
|
|
5666
|
+
// rendered (the web client); the CLI and TUI cannot, so they leave it off
|
|
5667
|
+
// unless explicitly overridden (#2403).
|
|
5175
5668
|
defaultAdvertised: true,
|
|
5669
|
+
requiresAppRenderer: true,
|
|
5176
5670
|
advertisement: { mimeTypes: [MCP_APP_MIME_TYPE] }
|
|
5177
5671
|
},
|
|
5178
5672
|
{
|
|
@@ -5188,10 +5682,13 @@ var ADVERTISABLE_EXTENSIONS = [
|
|
|
5188
5682
|
defaultAdvertised: true
|
|
5189
5683
|
}
|
|
5190
5684
|
];
|
|
5685
|
+
function isAdvertisedByDefault(ext, rendersApps) {
|
|
5686
|
+
return ext.defaultAdvertised && (!ext.requiresAppRenderer || rendersApps);
|
|
5687
|
+
}
|
|
5191
5688
|
function buildClientExtensions(input) {
|
|
5192
5689
|
const map = {};
|
|
5193
5690
|
for (const ext of ADVERTISABLE_EXTENSIONS) {
|
|
5194
|
-
const advertised = input.advertised?.[ext.key] ?? ext.
|
|
5691
|
+
const advertised = input.advertised?.[ext.key] ?? isAdvertisedByDefault(ext, input.rendersApps === true);
|
|
5195
5692
|
if (advertised) {
|
|
5196
5693
|
map[ext.key] = ext.advertisement ? structuredClone(ext.advertisement) : {};
|
|
5197
5694
|
}
|
|
@@ -6180,7 +6677,15 @@ function exemptMcpEndpoint(getServerUrl, negotiatesEndpoint) {
|
|
|
6180
6677
|
}
|
|
6181
6678
|
};
|
|
6182
6679
|
}
|
|
6183
|
-
var REQUEST_DEADLINES = /* @__PURE__ */ new WeakMap();
|
|
6680
|
+
var REQUEST_DEADLINES = /* @__PURE__ */ new WeakMap();
|
|
6681
|
+
function stampRequestDeadline(init, budget) {
|
|
6682
|
+
if (REQUEST_DEADLINES.has(init)) {
|
|
6683
|
+
throw new Error(
|
|
6684
|
+
"stampRequestDeadline: this RequestInit already carries a deadline \u2014 withOAuthRequestTimeout must build a fresh init per call (#2418)"
|
|
6685
|
+
);
|
|
6686
|
+
}
|
|
6687
|
+
REQUEST_DEADLINES.set(init, budget);
|
|
6688
|
+
}
|
|
6184
6689
|
function requestHeadersOf(input, init) {
|
|
6185
6690
|
if (init?.headers) return new Headers(init.headers);
|
|
6186
6691
|
if (typeof input !== "string" && !(input instanceof URL)) {
|
|
@@ -6238,7 +6743,7 @@ function withOAuthRequestTimeout(fetchFn, timeoutMs = DEFAULT_OAUTH_REQUEST_TIME
|
|
|
6238
6743
|
}
|
|
6239
6744
|
});
|
|
6240
6745
|
const nextInit = { ...init, signal };
|
|
6241
|
-
|
|
6746
|
+
stampRequestDeadline(nextInit, budget);
|
|
6242
6747
|
let settled;
|
|
6243
6748
|
let drainReader;
|
|
6244
6749
|
try {
|
|
@@ -6351,7 +6856,7 @@ function withRfc8414OidcCompat(fetchFn) {
|
|
|
6351
6856
|
return response;
|
|
6352
6857
|
}
|
|
6353
6858
|
if (!probe.ok) {
|
|
6354
|
-
|
|
6859
|
+
releaseBodyDetached(probe);
|
|
6355
6860
|
if (callerSignal?.aborted) {
|
|
6356
6861
|
releaseBodyDetached(response);
|
|
6357
6862
|
throw callerSignal.reason;
|
|
@@ -6375,7 +6880,7 @@ function withRfc8414OidcCompat(fetchFn) {
|
|
|
6375
6880
|
return response;
|
|
6376
6881
|
}
|
|
6377
6882
|
const source = probe.url || candidate;
|
|
6378
|
-
|
|
6883
|
+
releaseBodyDetached(response);
|
|
6379
6884
|
console.warn(
|
|
6380
6885
|
`[oauth] ${source} returned RFC 8414 OAuth 2.0 authorization server metadata, not an OpenID provider document. The MCP TypeScript SDK validates that path as OpenID Connect Discovery and would reject it (modelcontextprotocol/typescript-sdk#2733), so the Inspector is handing it to discovery as the RFC 8414 document it is.`
|
|
6381
6886
|
);
|
|
@@ -7165,7 +7670,7 @@ async function collectGrants(snapshot) {
|
|
|
7165
7670
|
return { grants, failures };
|
|
7166
7671
|
}
|
|
7167
7672
|
async function parseTokens(raw) {
|
|
7168
|
-
return raw === void 0 || raw === null ? void 0 : await OAuthTokensSchema.parseAsync(raw);
|
|
7673
|
+
return raw === void 0 || raw === null ? void 0 : await OAuthTokensSchema.partial().parseAsync(raw);
|
|
7169
7674
|
}
|
|
7170
7675
|
async function parseClient(raw) {
|
|
7171
7676
|
return raw === void 0 || raw === null ? void 0 : await OAuthClientInformationSchema.parseAsync(raw);
|
|
@@ -8946,6 +9451,14 @@ function progressTokenOf(message) {
|
|
|
8946
9451
|
}
|
|
8947
9452
|
return void 0;
|
|
8948
9453
|
}
|
|
9454
|
+
function waitForProgressToken(waits, token) {
|
|
9455
|
+
const exact = waits.get(token);
|
|
9456
|
+
if (exact !== void 0 || typeof token === "number") {
|
|
9457
|
+
return exact;
|
|
9458
|
+
}
|
|
9459
|
+
const numeric = Number(token);
|
|
9460
|
+
return Number.isSafeInteger(numeric) ? waits.get(numeric) : void 0;
|
|
9461
|
+
}
|
|
8949
9462
|
|
|
8950
9463
|
// ../../core/mcp/remote/remoteClientTransport.ts
|
|
8951
9464
|
var DEFAULT_SSE_RESPONSE_TIMEOUT_MS = 6e4;
|
|
@@ -9422,8 +9935,8 @@ var RemoteClientTransport = class {
|
|
|
9422
9935
|
});
|
|
9423
9936
|
}
|
|
9424
9937
|
/** Re-arm a pending request's SSE wait timeout on a matching progress note. */
|
|
9425
|
-
resetSseResponseWait(
|
|
9426
|
-
this.sseResponseWaits
|
|
9938
|
+
resetSseResponseWait(progressToken) {
|
|
9939
|
+
waitForProgressToken(this.sseResponseWaits, progressToken)?.resetTimeout();
|
|
9427
9940
|
}
|
|
9428
9941
|
async postSend(message, options, retryCount) {
|
|
9429
9942
|
const requestId = requestIdForMessage(message);
|
|
@@ -9628,6 +10141,11 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
9628
10141
|
requestTimeout;
|
|
9629
10142
|
defaultMetadata;
|
|
9630
10143
|
serverSettings;
|
|
10144
|
+
// The settings the current transport was built from. `serverSettings` is
|
|
10145
|
+
// replaced live on every settings save (#1444), but transport-level inputs
|
|
10146
|
+
// such as custom headers are fixed when the transport is created, so this
|
|
10147
|
+
// is what the open connection actually sends (#2460).
|
|
10148
|
+
transportSettings;
|
|
9631
10149
|
versionNegotiation;
|
|
9632
10150
|
status = "disconnected";
|
|
9633
10151
|
// True only while an explicit disconnect() owns the teardown. close() can
|
|
@@ -9982,6 +10500,10 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
9982
10500
|
const advertisedExtensions = buildClientExtensions({
|
|
9983
10501
|
enterpriseManaged: options.oauth?.enterpriseManaged ?? false,
|
|
9984
10502
|
advertised: this.advertisedExtensions,
|
|
10503
|
+
// Only a client that can render Apps claims the UI extension by default
|
|
10504
|
+
// (#2403). An app-elicitation renderer is itself a claim to host an App,
|
|
10505
|
+
// so supplying one implies it.
|
|
10506
|
+
rendersApps: options.rendersApps === true || this.appElicitationRenderer !== void 0,
|
|
9985
10507
|
// Read off the built `capabilities.elicitation.form` rather than
|
|
9986
10508
|
// re-deriving from `options.elicit`: the nested MCP Apps `elicitation`
|
|
9987
10509
|
// setting must never be advertised without the core form capability it
|
|
@@ -10407,6 +10929,7 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
10407
10929
|
}
|
|
10408
10930
|
this.baseTransport = null;
|
|
10409
10931
|
this.transport = null;
|
|
10932
|
+
this.transportSettings = void 0;
|
|
10410
10933
|
this.transportHasAuthProvider = false;
|
|
10411
10934
|
}
|
|
10412
10935
|
/**
|
|
@@ -10880,6 +11403,7 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
10880
11403
|
transportOptions
|
|
10881
11404
|
);
|
|
10882
11405
|
this.baseTransport = baseTransport;
|
|
11406
|
+
this.transportSettings = transportOptions.settings;
|
|
10883
11407
|
if (this.directAuthRecovery) {
|
|
10884
11408
|
this.directAuthRecoveryActive = !(baseTransport instanceof RemoteClientTransport);
|
|
10885
11409
|
}
|
|
@@ -11081,6 +11605,7 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
11081
11605
|
}
|
|
11082
11606
|
this.baseTransport = null;
|
|
11083
11607
|
this.transport = null;
|
|
11608
|
+
this.transportSettings = void 0;
|
|
11084
11609
|
this.transportHasAuthProvider = false;
|
|
11085
11610
|
this.clearPendingPeerRequests();
|
|
11086
11611
|
if (this.status !== "disconnected") {
|
|
@@ -11237,7 +11762,7 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
11237
11762
|
...params,
|
|
11238
11763
|
_meta: {
|
|
11239
11764
|
...existingMeta,
|
|
11240
|
-
[
|
|
11765
|
+
[PROTOCOL_VERSION_META_KEY2]: protocolVersion,
|
|
11241
11766
|
[CLIENT_INFO_META_KEY]: this.clientInfo,
|
|
11242
11767
|
[CLIENT_CAPABILITIES_META_KEY]: clientCapabilities
|
|
11243
11768
|
}
|
|
@@ -11813,6 +12338,13 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
11813
12338
|
getClientCapabilities() {
|
|
11814
12339
|
return this.clientCapabilities;
|
|
11815
12340
|
}
|
|
12341
|
+
/**
|
|
12342
|
+
* Get the client identity (name, version) this client reports to servers —
|
|
12343
|
+
* the caller's `clientIdentity`, or core's neutral fallback without one.
|
|
12344
|
+
*/
|
|
12345
|
+
getClientInfo() {
|
|
12346
|
+
return this.clientInfo;
|
|
12347
|
+
}
|
|
11816
12348
|
/**
|
|
11817
12349
|
* Get server info (name, version)
|
|
11818
12350
|
*/
|
|
@@ -11864,6 +12396,16 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
11864
12396
|
getServerSettings() {
|
|
11865
12397
|
return this.serverSettings;
|
|
11866
12398
|
}
|
|
12399
|
+
/**
|
|
12400
|
+
* The settings the current transport was built from, or `undefined` when no
|
|
12401
|
+
* transport exists. Unlike {@link getServerSettings}, a live settings edit
|
|
12402
|
+
* does not change this: transport-level inputs (custom headers) apply only
|
|
12403
|
+
* when the next transport is created, so comparing the two tells a caller
|
|
12404
|
+
* whether an edit is still waiting on a reconnect (#2460).
|
|
12405
|
+
*/
|
|
12406
|
+
getTransportSettings() {
|
|
12407
|
+
return this.transportSettings;
|
|
12408
|
+
}
|
|
11867
12409
|
/**
|
|
11868
12410
|
* Replace the in-memory per-server settings on a live client. Lets a settings
|
|
11869
12411
|
* edit (e.g. toggling auto-refresh-on-list-changed) take effect on the
|
|
@@ -13385,10 +13927,9 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
13385
13927
|
* removes it before the result gets here (#2373).
|
|
13386
13928
|
*
|
|
13387
13929
|
* Separate from {@link getSkill} because the callers differ: the UIs want the
|
|
13388
|
-
* entry, while the CLI prints the result and must not reshape it.
|
|
13389
|
-
*
|
|
13390
|
-
*
|
|
13391
|
-
* those (Copilot).
|
|
13930
|
+
* entry, while the CLI prints the result and must not reshape it. A modern
|
|
13931
|
+
* result carries `ttlMs` / `cacheScope` (#2404), and unwrapping to the entry
|
|
13932
|
+
* discards exactly those (Copilot).
|
|
13392
13933
|
*/
|
|
13393
13934
|
async getSkillResult(uri, metadata) {
|
|
13394
13935
|
if (!this.client) {
|
|
@@ -13399,11 +13940,12 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
13399
13940
|
uri,
|
|
13400
13941
|
...effectiveMeta ? { _meta: effectiveMeta } : {}
|
|
13401
13942
|
};
|
|
13943
|
+
const resultSchema = this.isModernEra() ? ModernGetSkillEnvelopeSchema : GetSkillEnvelopeSchema;
|
|
13402
13944
|
try {
|
|
13403
13945
|
return await this.invokeMcpClient(
|
|
13404
13946
|
() => this.client.request(
|
|
13405
13947
|
{ method: SKILLS_GET_METHOD, params },
|
|
13406
|
-
|
|
13948
|
+
resultSchema,
|
|
13407
13949
|
this.getRequestOptions(this.progressTokenOf(metadata))
|
|
13408
13950
|
),
|
|
13409
13951
|
{ method: SKILLS_GET_METHOD }
|
|
@@ -15275,7 +15817,7 @@ import { useCallback as useCallback2, useEffect, useState } from "react";
|
|
|
15275
15817
|
// ../../core/react/useStoreSnapshot.ts
|
|
15276
15818
|
import { useCallback, useRef, useSyncExternalStore } from "react";
|
|
15277
15819
|
function useStoreSnapshot(store, event, read, whenAbsent) {
|
|
15278
|
-
const
|
|
15820
|
+
const cache2 = useRef(null);
|
|
15279
15821
|
const subscribe = useCallback(
|
|
15280
15822
|
(onStoreChange) => {
|
|
15281
15823
|
if (!store) return () => {
|
|
@@ -15289,12 +15831,12 @@ function useStoreSnapshot(store, event, read, whenAbsent) {
|
|
|
15289
15831
|
);
|
|
15290
15832
|
const getSnapshot = useCallback(() => {
|
|
15291
15833
|
const revision = store ? store.getEventRevision(event) : 0;
|
|
15292
|
-
const cached =
|
|
15834
|
+
const cached = cache2.current;
|
|
15293
15835
|
if (cached && Object.is(cached.store, store) && cached.event === event && cached.read === read && Object.is(cached.whenAbsent, whenAbsent) && cached.revision === revision) {
|
|
15294
15836
|
return cached.value;
|
|
15295
15837
|
}
|
|
15296
15838
|
const value = store ? read(store) : whenAbsent;
|
|
15297
|
-
|
|
15839
|
+
cache2.current = { store, event, read, whenAbsent, revision, value };
|
|
15298
15840
|
return value;
|
|
15299
15841
|
}, [store, event, read, whenAbsent]);
|
|
15300
15842
|
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
@@ -15699,7 +16241,7 @@ function classifyAuthorizationServerMismatch(err) {
|
|
|
15699
16241
|
}
|
|
15700
16242
|
|
|
15701
16243
|
// ../../core/node/version.ts
|
|
15702
|
-
import { readFileSync as
|
|
16244
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
15703
16245
|
import { dirname as dirname5, join as join3, parse } from "path";
|
|
15704
16246
|
import { fileURLToPath } from "url";
|
|
15705
16247
|
var ROOT_PACKAGE_NAME = "@modelcontextprotocol/inspector";
|
|
@@ -15711,7 +16253,7 @@ function readInspectorVersion(callerUrl) {
|
|
|
15711
16253
|
let manifest;
|
|
15712
16254
|
try {
|
|
15713
16255
|
manifest = JSON.parse(
|
|
15714
|
-
|
|
16256
|
+
readFileSync4(join3(dir, "package.json"), "utf-8")
|
|
15715
16257
|
);
|
|
15716
16258
|
} catch {
|
|
15717
16259
|
}
|
|
@@ -15734,42 +16276,57 @@ import {
|
|
|
15734
16276
|
function withIssuer(value, issuer) {
|
|
15735
16277
|
return issuer === void 0 ? value : { ...value, issuer };
|
|
15736
16278
|
}
|
|
15737
|
-
var
|
|
16279
|
+
var OAuthStorageCoordination = class {
|
|
15738
16280
|
loaded = false;
|
|
15739
16281
|
loadPromise;
|
|
15740
16282
|
/** Serializes persist writes so concurrent mutators cannot reorder POSTs. */
|
|
15741
16283
|
persistQueue = Promise.resolve();
|
|
16284
|
+
};
|
|
16285
|
+
var OAuthStorageBase = class {
|
|
16286
|
+
coordination;
|
|
15742
16287
|
memory;
|
|
15743
16288
|
backend;
|
|
15744
|
-
constructor(memory, backend) {
|
|
16289
|
+
constructor(memory, backend, coordination = new OAuthStorageCoordination()) {
|
|
15745
16290
|
this.memory = memory;
|
|
15746
16291
|
this.backend = backend;
|
|
16292
|
+
this.coordination = coordination;
|
|
15747
16293
|
}
|
|
15748
16294
|
load() {
|
|
15749
|
-
|
|
15750
|
-
|
|
16295
|
+
const coordination = this.coordination;
|
|
16296
|
+
if (!coordination.loadPromise) {
|
|
16297
|
+
coordination.loadPromise = this.doLoad().catch((error) => {
|
|
16298
|
+
coordination.loadPromise = void 0;
|
|
16299
|
+
throw error;
|
|
16300
|
+
});
|
|
15751
16301
|
}
|
|
15752
|
-
return
|
|
16302
|
+
return coordination.loadPromise;
|
|
15753
16303
|
}
|
|
15754
16304
|
async doLoad() {
|
|
15755
|
-
if (this.loaded) {
|
|
16305
|
+
if (this.coordination.loaded) {
|
|
15756
16306
|
return;
|
|
15757
16307
|
}
|
|
15758
16308
|
const snapshot = await this.backend.read();
|
|
15759
16309
|
if (snapshot) {
|
|
15760
16310
|
this.memory.replace(snapshot);
|
|
15761
16311
|
}
|
|
15762
|
-
this.loaded = true;
|
|
16312
|
+
this.coordination.loaded = true;
|
|
15763
16313
|
}
|
|
15764
16314
|
async ensureLoaded() {
|
|
15765
16315
|
await this.load();
|
|
15766
16316
|
}
|
|
15767
|
-
|
|
15768
|
-
|
|
15769
|
-
|
|
16317
|
+
/**
|
|
16318
|
+
* Flush memory to the backend, naming the sections the calling mutation
|
|
16319
|
+
* touched so shared-store backends can merge just those entries over a
|
|
16320
|
+
* fresh read (the clobber fix — see {@link OAuthPersistSections}). The
|
|
16321
|
+
* snapshot is taken *inside* the queued closure, so a write that waited in
|
|
16322
|
+
* the queue carries the state as of when it actually runs, coalescing with
|
|
16323
|
+
* any mutations that landed in memory while it waited.
|
|
16324
|
+
*/
|
|
16325
|
+
async persist(sections) {
|
|
16326
|
+
const prior = this.coordination.persistQueue;
|
|
15770
16327
|
const tracked = prior.catch(() => {
|
|
15771
|
-
}).then(() => this.backend.write(snapshot));
|
|
15772
|
-
this.persistQueue = tracked;
|
|
16328
|
+
}).then(() => this.backend.write(this.memory.snapshot(), sections));
|
|
16329
|
+
this.coordination.persistQueue = tracked;
|
|
15773
16330
|
await tracked;
|
|
15774
16331
|
}
|
|
15775
16332
|
/**
|
|
@@ -15783,7 +16340,7 @@ var OAuthStorageBase = class {
|
|
|
15783
16340
|
/** Read the issuer-bound slot for a read, if one exists. */
|
|
15784
16341
|
issuerSlot(state, issuer) {
|
|
15785
16342
|
const key = this.resolveReadIssuer(state, issuer);
|
|
15786
|
-
return key ? state.byIssuer
|
|
16343
|
+
return key ? getOwnEntry(state.byIssuer, key) : void 0;
|
|
15787
16344
|
}
|
|
15788
16345
|
/**
|
|
15789
16346
|
* Read-modify-write the `byIssuer[issuer]` slot, set `activeIssuer`, and clear
|
|
@@ -15794,7 +16351,9 @@ var OAuthStorageBase = class {
|
|
|
15794
16351
|
const state = this.memory.getState().getServerState(serverUrl);
|
|
15795
16352
|
const byIssuer = {
|
|
15796
16353
|
...state.byIssuer,
|
|
15797
|
-
|
|
16354
|
+
// The computed key defines an own property; the merge-base read needs
|
|
16355
|
+
// the own guard so an absent `__proto__` slot reads as undefined.
|
|
16356
|
+
[issuer]: { ...getOwnEntry(state.byIssuer, issuer), ...updates }
|
|
15798
16357
|
};
|
|
15799
16358
|
this.memory.getState().setServerState(serverUrl, {
|
|
15800
16359
|
byIssuer,
|
|
@@ -15806,7 +16365,7 @@ var OAuthStorageBase = class {
|
|
|
15806
16365
|
mapIssuerSlots(state, fn) {
|
|
15807
16366
|
const byIssuer = {};
|
|
15808
16367
|
for (const [key, slot] of Object.entries(state.byIssuer ?? {})) {
|
|
15809
|
-
byIssuer
|
|
16368
|
+
setOwnEntry(byIssuer, key, { ...slot, ...fn(slot) });
|
|
15810
16369
|
}
|
|
15811
16370
|
return byIssuer;
|
|
15812
16371
|
}
|
|
@@ -15852,7 +16411,7 @@ var OAuthStorageBase = class {
|
|
|
15852
16411
|
clientRegistrationKind: options.registrationKind
|
|
15853
16412
|
});
|
|
15854
16413
|
}
|
|
15855
|
-
await this.persist();
|
|
16414
|
+
await this.persist({ servers: [serverUrl] });
|
|
15856
16415
|
}
|
|
15857
16416
|
async savePreregisteredClientInformation(serverUrl, clientInformation) {
|
|
15858
16417
|
await this.ensureLoaded();
|
|
@@ -15860,7 +16419,7 @@ var OAuthStorageBase = class {
|
|
|
15860
16419
|
preregisteredClientInformation: clientInformation,
|
|
15861
16420
|
clientRegistrationKind: "static"
|
|
15862
16421
|
});
|
|
15863
|
-
await this.persist();
|
|
16422
|
+
await this.persist({ servers: [serverUrl] });
|
|
15864
16423
|
}
|
|
15865
16424
|
async clearClientInformation(serverUrl, isPreregistered, issuer) {
|
|
15866
16425
|
await this.ensureLoaded();
|
|
@@ -15868,7 +16427,7 @@ var OAuthStorageBase = class {
|
|
|
15868
16427
|
this.memory.getState().setServerState(serverUrl, {
|
|
15869
16428
|
preregisteredClientInformation: void 0
|
|
15870
16429
|
});
|
|
15871
|
-
await this.persist();
|
|
16430
|
+
await this.persist({ servers: [serverUrl] });
|
|
15872
16431
|
return;
|
|
15873
16432
|
}
|
|
15874
16433
|
if (issuer !== void 0) {
|
|
@@ -15891,7 +16450,7 @@ var OAuthStorageBase = class {
|
|
|
15891
16450
|
clientRegistrationKind: void 0
|
|
15892
16451
|
});
|
|
15893
16452
|
}
|
|
15894
|
-
await this.persist();
|
|
16453
|
+
await this.persist({ servers: [serverUrl] });
|
|
15895
16454
|
}
|
|
15896
16455
|
async getTokens(serverUrl, issuer) {
|
|
15897
16456
|
await this.ensureLoaded();
|
|
@@ -15902,9 +16461,12 @@ var OAuthStorageBase = class {
|
|
|
15902
16461
|
if (!tokens) {
|
|
15903
16462
|
return void 0;
|
|
15904
16463
|
}
|
|
15905
|
-
const
|
|
16464
|
+
const result = await OAuthTokensSchema3.safeParseAsync(tokens);
|
|
16465
|
+
if (!result.success) {
|
|
16466
|
+
return void 0;
|
|
16467
|
+
}
|
|
15906
16468
|
return withIssuer(
|
|
15907
|
-
|
|
16469
|
+
result.data,
|
|
15908
16470
|
fromSlot ? this.resolveReadIssuer(state, issuer) : void 0
|
|
15909
16471
|
);
|
|
15910
16472
|
}
|
|
@@ -15928,7 +16490,7 @@ var OAuthStorageBase = class {
|
|
|
15928
16490
|
...options?.enterpriseManaged === true && { enterpriseManaged: true }
|
|
15929
16491
|
});
|
|
15930
16492
|
}
|
|
15931
|
-
await this.persist();
|
|
16493
|
+
await this.persist({ servers: [serverUrl] });
|
|
15932
16494
|
}
|
|
15933
16495
|
async clearTokens(serverUrl, issuer) {
|
|
15934
16496
|
await this.ensureLoaded();
|
|
@@ -15947,7 +16509,7 @@ var OAuthStorageBase = class {
|
|
|
15947
16509
|
}));
|
|
15948
16510
|
this.memory.getState().setServerState(serverUrl, { byIssuer, tokens: void 0 });
|
|
15949
16511
|
}
|
|
15950
|
-
await this.persist();
|
|
16512
|
+
await this.persist({ servers: [serverUrl] });
|
|
15951
16513
|
}
|
|
15952
16514
|
async getCodeVerifier(serverUrl) {
|
|
15953
16515
|
await this.ensureLoaded();
|
|
@@ -15957,12 +16519,12 @@ var OAuthStorageBase = class {
|
|
|
15957
16519
|
async saveCodeVerifier(serverUrl, codeVerifier) {
|
|
15958
16520
|
await this.ensureLoaded();
|
|
15959
16521
|
this.memory.getState().setServerState(serverUrl, { codeVerifier });
|
|
15960
|
-
await this.persist();
|
|
16522
|
+
await this.persist({ servers: [serverUrl] });
|
|
15961
16523
|
}
|
|
15962
16524
|
async clearCodeVerifier(serverUrl) {
|
|
15963
16525
|
await this.ensureLoaded();
|
|
15964
16526
|
this.memory.getState().setServerState(serverUrl, { codeVerifier: void 0 });
|
|
15965
|
-
await this.persist();
|
|
16527
|
+
await this.persist({ servers: [serverUrl] });
|
|
15966
16528
|
}
|
|
15967
16529
|
async getScope(serverUrl) {
|
|
15968
16530
|
await this.ensureLoaded();
|
|
@@ -15972,12 +16534,12 @@ var OAuthStorageBase = class {
|
|
|
15972
16534
|
async saveScope(serverUrl, scope) {
|
|
15973
16535
|
await this.ensureLoaded();
|
|
15974
16536
|
this.memory.getState().setServerState(serverUrl, { scope });
|
|
15975
|
-
await this.persist();
|
|
16537
|
+
await this.persist({ servers: [serverUrl] });
|
|
15976
16538
|
}
|
|
15977
16539
|
async clearScope(serverUrl) {
|
|
15978
16540
|
await this.ensureLoaded();
|
|
15979
16541
|
this.memory.getState().setServerState(serverUrl, { scope: void 0 });
|
|
15980
|
-
await this.persist();
|
|
16542
|
+
await this.persist({ servers: [serverUrl] });
|
|
15981
16543
|
}
|
|
15982
16544
|
async getServerMetadata(serverUrl) {
|
|
15983
16545
|
await this.ensureLoaded();
|
|
@@ -15987,12 +16549,12 @@ var OAuthStorageBase = class {
|
|
|
15987
16549
|
async saveServerMetadata(serverUrl, metadata) {
|
|
15988
16550
|
await this.ensureLoaded();
|
|
15989
16551
|
this.memory.getState().setServerState(serverUrl, { serverMetadata: metadata });
|
|
15990
|
-
await this.persist();
|
|
16552
|
+
await this.persist({ servers: [serverUrl] });
|
|
15991
16553
|
}
|
|
15992
16554
|
async clearServerMetadata(serverUrl) {
|
|
15993
16555
|
await this.ensureLoaded();
|
|
15994
16556
|
this.memory.getState().setServerState(serverUrl, { serverMetadata: void 0 });
|
|
15995
|
-
await this.persist();
|
|
16557
|
+
await this.persist({ servers: [serverUrl] });
|
|
15996
16558
|
}
|
|
15997
16559
|
async getDiscoveryState(serverUrl) {
|
|
15998
16560
|
await this.ensureLoaded();
|
|
@@ -16001,12 +16563,12 @@ var OAuthStorageBase = class {
|
|
|
16001
16563
|
async saveDiscoveryState(serverUrl, state) {
|
|
16002
16564
|
await this.ensureLoaded();
|
|
16003
16565
|
this.memory.getState().setServerState(serverUrl, { discoveryState: state });
|
|
16004
|
-
await this.persist();
|
|
16566
|
+
await this.persist({ servers: [serverUrl] });
|
|
16005
16567
|
}
|
|
16006
16568
|
async clearDiscoveryState(serverUrl) {
|
|
16007
16569
|
await this.ensureLoaded();
|
|
16008
16570
|
this.memory.getState().setServerState(serverUrl, { discoveryState: void 0 });
|
|
16009
|
-
await this.persist();
|
|
16571
|
+
await this.persist({ servers: [serverUrl] });
|
|
16010
16572
|
}
|
|
16011
16573
|
async takeRevocationSnapshot(serverUrl) {
|
|
16012
16574
|
await this.ensureLoaded();
|
|
@@ -16024,13 +16586,13 @@ var OAuthStorageBase = class {
|
|
|
16024
16586
|
serverMetadata: state.serverMetadata
|
|
16025
16587
|
};
|
|
16026
16588
|
this.memory.getState().clearServerState(serverUrl);
|
|
16027
|
-
await this.persist();
|
|
16589
|
+
await this.persist({ servers: [serverUrl] });
|
|
16028
16590
|
return snapshot;
|
|
16029
16591
|
}
|
|
16030
16592
|
async clear(serverUrl) {
|
|
16031
16593
|
await this.ensureLoaded();
|
|
16032
16594
|
this.memory.getState().clearServerState(serverUrl);
|
|
16033
|
-
await this.persist();
|
|
16595
|
+
await this.persist({ servers: [serverUrl] });
|
|
16034
16596
|
}
|
|
16035
16597
|
async getIdpSession(issuer) {
|
|
16036
16598
|
await this.ensureLoaded();
|
|
@@ -16043,17 +16605,18 @@ var OAuthStorageBase = class {
|
|
|
16043
16605
|
async saveIdpSession(issuer, session) {
|
|
16044
16606
|
await this.ensureLoaded();
|
|
16045
16607
|
this.memory.getState().setIdpSession(issuer, session);
|
|
16046
|
-
await this.persist();
|
|
16608
|
+
await this.persist({ idpSessions: [issuer] });
|
|
16047
16609
|
}
|
|
16048
16610
|
async clearIdpSession(issuer) {
|
|
16049
16611
|
await this.ensureLoaded();
|
|
16050
16612
|
this.memory.getState().clearIdpSession(issuer);
|
|
16051
|
-
await this.persist();
|
|
16613
|
+
await this.persist({ idpSessions: [issuer] });
|
|
16052
16614
|
}
|
|
16053
16615
|
async clearEnterpriseManagedResourceServers() {
|
|
16054
16616
|
await this.ensureLoaded();
|
|
16617
|
+
const servers = Object.entries(this.memory.getState().servers).filter(([, state]) => state.enterpriseManaged === true).map(([url]) => url);
|
|
16055
16618
|
this.memory.getState().clearEnterpriseManagedResourceServers();
|
|
16056
|
-
await this.persist();
|
|
16619
|
+
await this.persist({ servers });
|
|
16057
16620
|
}
|
|
16058
16621
|
};
|
|
16059
16622
|
|
|
@@ -16071,13 +16634,15 @@ var OAuthMemoryStore = class {
|
|
|
16071
16634
|
servers: this.servers,
|
|
16072
16635
|
idpSessions: this.idpSessions,
|
|
16073
16636
|
getServerState: (serverUrl) => {
|
|
16074
|
-
return this.servers
|
|
16637
|
+
return getOwnEntry(this.servers, serverUrl) || {};
|
|
16075
16638
|
},
|
|
16076
16639
|
setServerState: (serverUrl, updates) => {
|
|
16077
16640
|
this.servers = {
|
|
16078
16641
|
...this.servers,
|
|
16642
|
+
// Computed keys define own properties, so this write is safe for
|
|
16643
|
+
// `__proto__`; only the merge-base read needs the own guard.
|
|
16079
16644
|
[serverUrl]: {
|
|
16080
|
-
...this.servers
|
|
16645
|
+
...getOwnEntry(this.servers, serverUrl),
|
|
16081
16646
|
...updates
|
|
16082
16647
|
}
|
|
16083
16648
|
};
|
|
@@ -16088,13 +16653,13 @@ var OAuthMemoryStore = class {
|
|
|
16088
16653
|
this.servers = rest;
|
|
16089
16654
|
},
|
|
16090
16655
|
getIdpSession: (issuer) => {
|
|
16091
|
-
return this.idpSessions
|
|
16656
|
+
return getOwnEntry(this.idpSessions, issuer) || {};
|
|
16092
16657
|
},
|
|
16093
16658
|
setIdpSession: (issuer, updates) => {
|
|
16094
16659
|
this.idpSessions = {
|
|
16095
16660
|
...this.idpSessions,
|
|
16096
16661
|
[issuer]: {
|
|
16097
|
-
...this.idpSessions
|
|
16662
|
+
...getOwnEntry(this.idpSessions, issuer),
|
|
16098
16663
|
...updates
|
|
16099
16664
|
}
|
|
16100
16665
|
};
|
|
@@ -16111,67 +16676,877 @@ var OAuthMemoryStore = class {
|
|
|
16111
16676
|
delete rest[url];
|
|
16112
16677
|
}
|
|
16113
16678
|
}
|
|
16114
|
-
this.servers = rest;
|
|
16679
|
+
this.servers = rest;
|
|
16680
|
+
}
|
|
16681
|
+
};
|
|
16682
|
+
}
|
|
16683
|
+
snapshot() {
|
|
16684
|
+
return {
|
|
16685
|
+
servers: { ...this.servers },
|
|
16686
|
+
idpSessions: { ...this.idpSessions }
|
|
16687
|
+
};
|
|
16688
|
+
}
|
|
16689
|
+
replace(snapshot) {
|
|
16690
|
+
this.servers = { ...snapshot.servers ?? {} };
|
|
16691
|
+
this.idpSessions = { ...snapshot.idpSessions ?? {} };
|
|
16692
|
+
}
|
|
16693
|
+
};
|
|
16694
|
+
|
|
16695
|
+
// ../../core/auth/oauth-persist.ts
|
|
16696
|
+
import { OAuthTokensSchema as OAuthTokensSchema4 } from "@modelcontextprotocol/core";
|
|
16697
|
+
function mergeOAuthSections(disk, snapshot, sections) {
|
|
16698
|
+
const merged = {
|
|
16699
|
+
servers: { ...disk?.servers },
|
|
16700
|
+
idpSessions: { ...disk?.idpSessions }
|
|
16701
|
+
};
|
|
16702
|
+
for (const url of sections.servers ?? []) {
|
|
16703
|
+
const value = getOwnEntry(snapshot.servers, url);
|
|
16704
|
+
if (value === void 0) {
|
|
16705
|
+
delete merged.servers[url];
|
|
16706
|
+
} else {
|
|
16707
|
+
setOwnEntry(merged.servers, url, value);
|
|
16708
|
+
}
|
|
16709
|
+
}
|
|
16710
|
+
for (const issuer of sections.idpSessions ?? []) {
|
|
16711
|
+
const value = getOwnEntry(snapshot.idpSessions, issuer);
|
|
16712
|
+
if (value === void 0) {
|
|
16713
|
+
delete merged.idpSessions[issuer];
|
|
16714
|
+
} else {
|
|
16715
|
+
setOwnEntry(merged.idpSessions, issuer, value);
|
|
16716
|
+
}
|
|
16717
|
+
}
|
|
16718
|
+
return merged;
|
|
16719
|
+
}
|
|
16720
|
+
function isRecord4(value) {
|
|
16721
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16722
|
+
}
|
|
16723
|
+
function isEntryMap(value) {
|
|
16724
|
+
return isRecord4(value) && Object.values(value).every(isRecord4);
|
|
16725
|
+
}
|
|
16726
|
+
var VERBATIM_SECRET_KEYS = [
|
|
16727
|
+
"client_secret",
|
|
16728
|
+
"registration_access_token"
|
|
16729
|
+
];
|
|
16730
|
+
function isValidClientInformation(value) {
|
|
16731
|
+
if (value === void 0) return true;
|
|
16732
|
+
if (!isRecord4(value)) return false;
|
|
16733
|
+
return VERBATIM_SECRET_KEYS.every(
|
|
16734
|
+
(key) => !Object.hasOwn(value, key) || typeof value[key] === "string"
|
|
16735
|
+
);
|
|
16736
|
+
}
|
|
16737
|
+
var PartialTokensSchema = OAuthTokensSchema4.partial();
|
|
16738
|
+
function isValidServerEntry(entry) {
|
|
16739
|
+
if (!isRecord4(entry)) return false;
|
|
16740
|
+
if (!isValidClientInformation(entry.clientInformation)) return false;
|
|
16741
|
+
if (!isValidClientInformation(entry.preregisteredClientInformation))
|
|
16742
|
+
return false;
|
|
16743
|
+
if (entry.byIssuer !== void 0) {
|
|
16744
|
+
if (!isRecord4(entry.byIssuer)) return false;
|
|
16745
|
+
for (const slot of Object.values(entry.byIssuer)) {
|
|
16746
|
+
if (!isRecord4(slot)) return false;
|
|
16747
|
+
if (!isValidClientInformation(slot.clientInformation)) return false;
|
|
16748
|
+
}
|
|
16749
|
+
}
|
|
16750
|
+
return true;
|
|
16751
|
+
}
|
|
16752
|
+
function snapshotFromPayload(payload) {
|
|
16753
|
+
const servers = payload.servers ?? {};
|
|
16754
|
+
const idpSessions = payload.idpSessions ?? {};
|
|
16755
|
+
if (!isEntryMap(servers) || !isEntryMap(idpSessions)) return null;
|
|
16756
|
+
if (!Object.values(servers).every(isValidServerEntry)) return null;
|
|
16757
|
+
return {
|
|
16758
|
+
servers,
|
|
16759
|
+
idpSessions
|
|
16760
|
+
};
|
|
16761
|
+
}
|
|
16762
|
+
function parseOAuthPersistBlob(raw) {
|
|
16763
|
+
if (raw === null || raw === void 0) {
|
|
16764
|
+
return null;
|
|
16765
|
+
}
|
|
16766
|
+
const parsed = typeof raw === "string" ? raw ? parseStore(raw) : null : raw;
|
|
16767
|
+
if (!isRecord4(parsed)) {
|
|
16768
|
+
return null;
|
|
16769
|
+
}
|
|
16770
|
+
if (isRecord4(parsed.state) && "version" in parsed) {
|
|
16771
|
+
return snapshotFromPayload(parsed.state);
|
|
16772
|
+
}
|
|
16773
|
+
if ("servers" in parsed || "idpSessions" in parsed) {
|
|
16774
|
+
return snapshotFromPayload(parsed);
|
|
16775
|
+
}
|
|
16776
|
+
return null;
|
|
16777
|
+
}
|
|
16778
|
+
function serializeOAuthPersistBlob(snapshot) {
|
|
16779
|
+
return serializeStore(snapshot);
|
|
16780
|
+
}
|
|
16781
|
+
|
|
16782
|
+
// ../../core/auth/node/oauth-secrets.ts
|
|
16783
|
+
import { OAuthTokensSchema as OAuthTokensSchema5 } from "@modelcontextprotocol/core";
|
|
16784
|
+
var PERSIST_TOKENS_ENV = "MCP_INSPECTOR_PERSIST_TOKENS";
|
|
16785
|
+
var warnedPolicyValues = /* @__PURE__ */ new Set();
|
|
16786
|
+
function getPersistTokensPolicy(env2 = process.env) {
|
|
16787
|
+
const raw = env2[PERSIST_TOKENS_ENV];
|
|
16788
|
+
if (raw === void 0 || raw === "") return "all";
|
|
16789
|
+
if (raw === "all" || raw === "access" || raw === "none") return raw;
|
|
16790
|
+
if (!warnedPolicyValues.has(raw)) {
|
|
16791
|
+
warnedPolicyValues.add(raw);
|
|
16792
|
+
console.warn(
|
|
16793
|
+
`[mcp-inspector] Ignoring invalid ${PERSIST_TOKENS_ENV}=${JSON.stringify(raw)} (expected "all", "access", or "none"); persisting all tokens.`
|
|
16794
|
+
);
|
|
16795
|
+
}
|
|
16796
|
+
return "all";
|
|
16797
|
+
}
|
|
16798
|
+
var oauthSecretServerId = (serverUrl) => `oauth+${encodeURIComponent(serverUrl)}`;
|
|
16799
|
+
var oauthIdpSecretServerId = (issuer) => `oauth-idp+${encodeURIComponent(issuer)}`;
|
|
16800
|
+
var issuerTokensField = (issuer) => `tokens:${issuer}`;
|
|
16801
|
+
var issuerClientSecretField = (issuer) => `client-secret:${issuer}`;
|
|
16802
|
+
var issuerRegistrationTokenField = (issuer) => `registration-token:${issuer}`;
|
|
16803
|
+
var LEGACY_TOKENS_FIELD = "tokens";
|
|
16804
|
+
var LEGACY_CLIENT_SECRET_FIELD = "client-secret";
|
|
16805
|
+
var LEGACY_REGISTRATION_TOKEN_FIELD = "registration-token";
|
|
16806
|
+
var PREREG_CLIENT_SECRET_FIELD = "prereg-client-secret";
|
|
16807
|
+
var PREREG_REGISTRATION_TOKEN_FIELD = "prereg-registration-token";
|
|
16808
|
+
var IDP_SESSION_FIELD = "idp-session";
|
|
16809
|
+
function applyTokensPolicy(tokens, policy) {
|
|
16810
|
+
if (policy === "none") return void 0;
|
|
16811
|
+
if (policy === "access" && tokens.refresh_token !== void 0) {
|
|
16812
|
+
const { refresh_token: _stripped, ...rest } = tokens;
|
|
16813
|
+
return rest;
|
|
16814
|
+
}
|
|
16815
|
+
return tokens;
|
|
16816
|
+
}
|
|
16817
|
+
var StorableTokensSchema = OAuthTokensSchema5.partial();
|
|
16818
|
+
function hasSecretBearingTokenField(tokens) {
|
|
16819
|
+
return tokens.access_token !== void 0 || tokens.refresh_token !== void 0 || tokens.id_token !== void 0;
|
|
16820
|
+
}
|
|
16821
|
+
function splitTokens(tokens, policy) {
|
|
16822
|
+
const kept = applyTokensPolicy(tokens, policy);
|
|
16823
|
+
if (!kept) return {};
|
|
16824
|
+
if (!StorableTokensSchema.safeParse(kept).success) {
|
|
16825
|
+
return { plaintext: kept };
|
|
16826
|
+
}
|
|
16827
|
+
if (!hasSecretBearingTokenField(kept)) {
|
|
16828
|
+
return {};
|
|
16829
|
+
}
|
|
16830
|
+
return { secret: JSON.stringify(kept) };
|
|
16831
|
+
}
|
|
16832
|
+
function splitClientInformation(info, fields, secrets) {
|
|
16833
|
+
const { client_secret, registration_access_token, ...publicInfo } = info;
|
|
16834
|
+
if (client_secret === void 0 && registration_access_token === void 0) {
|
|
16835
|
+
return info;
|
|
16836
|
+
}
|
|
16837
|
+
if (client_secret !== void 0) {
|
|
16838
|
+
secrets[fields.clientSecret] = client_secret;
|
|
16839
|
+
}
|
|
16840
|
+
if (registration_access_token !== void 0) {
|
|
16841
|
+
secrets[fields.registrationToken] = registration_access_token;
|
|
16842
|
+
}
|
|
16843
|
+
return publicInfo;
|
|
16844
|
+
}
|
|
16845
|
+
function joinClientInformation(info, fields, secrets) {
|
|
16846
|
+
const clientSecret = secrets[fields.clientSecret];
|
|
16847
|
+
const registrationToken = secrets[fields.registrationToken];
|
|
16848
|
+
if (clientSecret === void 0 && registrationToken === void 0) {
|
|
16849
|
+
return info;
|
|
16850
|
+
}
|
|
16851
|
+
return {
|
|
16852
|
+
...info,
|
|
16853
|
+
...clientSecret !== void 0 && { client_secret: clientSecret },
|
|
16854
|
+
...registrationToken !== void 0 && {
|
|
16855
|
+
registration_access_token: registrationToken
|
|
16856
|
+
}
|
|
16857
|
+
};
|
|
16858
|
+
}
|
|
16859
|
+
var issuerClientInfoFields = (issuer) => ({
|
|
16860
|
+
clientSecret: issuerClientSecretField(issuer),
|
|
16861
|
+
registrationToken: issuerRegistrationTokenField(issuer)
|
|
16862
|
+
});
|
|
16863
|
+
var LEGACY_CLIENT_INFO_FIELDS = {
|
|
16864
|
+
clientSecret: LEGACY_CLIENT_SECRET_FIELD,
|
|
16865
|
+
registrationToken: LEGACY_REGISTRATION_TOKEN_FIELD
|
|
16866
|
+
};
|
|
16867
|
+
var PREREG_CLIENT_INFO_FIELDS = {
|
|
16868
|
+
clientSecret: PREREG_CLIENT_SECRET_FIELD,
|
|
16869
|
+
registrationToken: PREREG_REGISTRATION_TOKEN_FIELD
|
|
16870
|
+
};
|
|
16871
|
+
function splitServerOAuthState(state, policy) {
|
|
16872
|
+
const secrets = {};
|
|
16873
|
+
const residue = { ...state };
|
|
16874
|
+
if (state.byIssuer) {
|
|
16875
|
+
const byIssuer = {};
|
|
16876
|
+
for (const [issuer, slot] of Object.entries(state.byIssuer)) {
|
|
16877
|
+
const slotResidue = { ...slot };
|
|
16878
|
+
if (slot.tokens) {
|
|
16879
|
+
delete slotResidue.tokens;
|
|
16880
|
+
const tokenSplit = splitTokens(slot.tokens, policy);
|
|
16881
|
+
if (tokenSplit.secret !== void 0) {
|
|
16882
|
+
secrets[issuerTokensField(issuer)] = tokenSplit.secret;
|
|
16883
|
+
}
|
|
16884
|
+
if (tokenSplit.plaintext) slotResidue.tokens = tokenSplit.plaintext;
|
|
16885
|
+
}
|
|
16886
|
+
if (slot.clientInformation) {
|
|
16887
|
+
slotResidue.clientInformation = splitClientInformation(
|
|
16888
|
+
slot.clientInformation,
|
|
16889
|
+
issuerClientInfoFields(issuer),
|
|
16890
|
+
secrets
|
|
16891
|
+
);
|
|
16892
|
+
}
|
|
16893
|
+
setOwnEntry(byIssuer, issuer, slotResidue);
|
|
16894
|
+
}
|
|
16895
|
+
residue.byIssuer = byIssuer;
|
|
16896
|
+
}
|
|
16897
|
+
if (state.tokens) {
|
|
16898
|
+
delete residue.tokens;
|
|
16899
|
+
const tokenSplit = splitTokens(state.tokens, policy);
|
|
16900
|
+
if (tokenSplit.secret !== void 0) {
|
|
16901
|
+
secrets[LEGACY_TOKENS_FIELD] = tokenSplit.secret;
|
|
16902
|
+
}
|
|
16903
|
+
if (tokenSplit.plaintext) residue.tokens = tokenSplit.plaintext;
|
|
16904
|
+
}
|
|
16905
|
+
if (state.clientInformation) {
|
|
16906
|
+
residue.clientInformation = splitClientInformation(
|
|
16907
|
+
state.clientInformation,
|
|
16908
|
+
LEGACY_CLIENT_INFO_FIELDS,
|
|
16909
|
+
secrets
|
|
16910
|
+
);
|
|
16911
|
+
}
|
|
16912
|
+
if (state.preregisteredClientInformation) {
|
|
16913
|
+
residue.preregisteredClientInformation = splitClientInformation(
|
|
16914
|
+
state.preregisteredClientInformation,
|
|
16915
|
+
PREREG_CLIENT_INFO_FIELDS,
|
|
16916
|
+
secrets
|
|
16917
|
+
);
|
|
16918
|
+
}
|
|
16919
|
+
return { residue, secrets };
|
|
16920
|
+
}
|
|
16921
|
+
function parseStoredTokens(raw) {
|
|
16922
|
+
try {
|
|
16923
|
+
const parsed = JSON.parse(raw);
|
|
16924
|
+
if (StorableTokensSchema.safeParse(parsed).success && hasSecretBearingTokenField(parsed)) {
|
|
16925
|
+
return parsed;
|
|
16926
|
+
}
|
|
16927
|
+
} catch {
|
|
16928
|
+
}
|
|
16929
|
+
return void 0;
|
|
16930
|
+
}
|
|
16931
|
+
function parseStoredIdpSession(raw) {
|
|
16932
|
+
try {
|
|
16933
|
+
const parsed = JSON.parse(raw);
|
|
16934
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
16935
|
+
const { idToken, refreshToken } = parsed;
|
|
16936
|
+
const usable = {
|
|
16937
|
+
...typeof idToken === "string" && { idToken },
|
|
16938
|
+
...typeof refreshToken === "string" && { refreshToken }
|
|
16939
|
+
};
|
|
16940
|
+
if (Object.keys(usable).length > 0) return usable;
|
|
16941
|
+
}
|
|
16942
|
+
} catch {
|
|
16943
|
+
}
|
|
16944
|
+
return void 0;
|
|
16945
|
+
}
|
|
16946
|
+
function isUsableStoredSecret(field, raw) {
|
|
16947
|
+
if (field === LEGACY_TOKENS_FIELD || field.startsWith("tokens:")) {
|
|
16948
|
+
return parseStoredTokens(raw) !== void 0;
|
|
16949
|
+
}
|
|
16950
|
+
if (field === IDP_SESSION_FIELD) {
|
|
16951
|
+
return parseStoredIdpSession(raw) !== void 0;
|
|
16952
|
+
}
|
|
16953
|
+
return true;
|
|
16954
|
+
}
|
|
16955
|
+
function joinServerOAuthState(residue, secrets) {
|
|
16956
|
+
const joined = { ...residue };
|
|
16957
|
+
if (residue.byIssuer) {
|
|
16958
|
+
const byIssuer = {};
|
|
16959
|
+
for (const [issuer, slot] of Object.entries(residue.byIssuer)) {
|
|
16960
|
+
const joinedSlot = { ...slot };
|
|
16961
|
+
const tokensRaw = secrets[issuerTokensField(issuer)];
|
|
16962
|
+
if (tokensRaw !== void 0) {
|
|
16963
|
+
const tokens = parseStoredTokens(tokensRaw);
|
|
16964
|
+
if (tokens) joinedSlot.tokens = tokens;
|
|
16965
|
+
}
|
|
16966
|
+
if (joinedSlot.clientInformation) {
|
|
16967
|
+
joinedSlot.clientInformation = joinClientInformation(
|
|
16968
|
+
joinedSlot.clientInformation,
|
|
16969
|
+
issuerClientInfoFields(issuer),
|
|
16970
|
+
secrets
|
|
16971
|
+
);
|
|
16972
|
+
}
|
|
16973
|
+
setOwnEntry(byIssuer, issuer, joinedSlot);
|
|
16974
|
+
}
|
|
16975
|
+
joined.byIssuer = byIssuer;
|
|
16976
|
+
}
|
|
16977
|
+
const legacyTokensRaw = secrets[LEGACY_TOKENS_FIELD];
|
|
16978
|
+
if (legacyTokensRaw !== void 0) {
|
|
16979
|
+
const tokens = parseStoredTokens(legacyTokensRaw);
|
|
16980
|
+
if (tokens) joined.tokens = tokens;
|
|
16981
|
+
}
|
|
16982
|
+
if (joined.clientInformation) {
|
|
16983
|
+
joined.clientInformation = joinClientInformation(
|
|
16984
|
+
joined.clientInformation,
|
|
16985
|
+
LEGACY_CLIENT_INFO_FIELDS,
|
|
16986
|
+
secrets
|
|
16987
|
+
);
|
|
16988
|
+
}
|
|
16989
|
+
if (joined.preregisteredClientInformation) {
|
|
16990
|
+
joined.preregisteredClientInformation = joinClientInformation(
|
|
16991
|
+
joined.preregisteredClientInformation,
|
|
16992
|
+
PREREG_CLIENT_INFO_FIELDS,
|
|
16993
|
+
secrets
|
|
16994
|
+
);
|
|
16995
|
+
}
|
|
16996
|
+
return joined;
|
|
16997
|
+
}
|
|
16998
|
+
function splitIdpSession(session, policy) {
|
|
16999
|
+
const { idToken, refreshToken, ...residue } = session;
|
|
17000
|
+
const secrets = {};
|
|
17001
|
+
if (policy !== "none" && (idToken !== void 0 || refreshToken !== void 0)) {
|
|
17002
|
+
const kept = {
|
|
17003
|
+
...typeof idToken === "string" && { idToken },
|
|
17004
|
+
...policy === "all" && typeof refreshToken === "string" && { refreshToken }
|
|
17005
|
+
};
|
|
17006
|
+
if (Object.keys(kept).length > 0) {
|
|
17007
|
+
secrets[IDP_SESSION_FIELD] = JSON.stringify(kept);
|
|
17008
|
+
}
|
|
17009
|
+
}
|
|
17010
|
+
return { residue, secrets };
|
|
17011
|
+
}
|
|
17012
|
+
function joinIdpSession(residue, secrets) {
|
|
17013
|
+
const raw = secrets[IDP_SESSION_FIELD];
|
|
17014
|
+
if (raw === void 0) return { ...residue };
|
|
17015
|
+
const stored = parseStoredIdpSession(raw);
|
|
17016
|
+
return stored ? { ...residue, ...stored } : { ...residue };
|
|
17017
|
+
}
|
|
17018
|
+
function serverSecretFields(state) {
|
|
17019
|
+
const fields = /* @__PURE__ */ new Set([
|
|
17020
|
+
LEGACY_TOKENS_FIELD,
|
|
17021
|
+
LEGACY_CLIENT_SECRET_FIELD,
|
|
17022
|
+
LEGACY_REGISTRATION_TOKEN_FIELD,
|
|
17023
|
+
PREREG_CLIENT_SECRET_FIELD,
|
|
17024
|
+
PREREG_REGISTRATION_TOKEN_FIELD
|
|
17025
|
+
]);
|
|
17026
|
+
for (const issuer of Object.keys(state?.byIssuer ?? {})) {
|
|
17027
|
+
fields.add(issuerTokensField(issuer));
|
|
17028
|
+
fields.add(issuerClientSecretField(issuer));
|
|
17029
|
+
fields.add(issuerRegistrationTokenField(issuer));
|
|
17030
|
+
}
|
|
17031
|
+
return [...fields];
|
|
17032
|
+
}
|
|
17033
|
+
function clientInfoHasPlaintext(info) {
|
|
17034
|
+
return info !== void 0 && (info.client_secret !== void 0 || info.registration_access_token !== void 0);
|
|
17035
|
+
}
|
|
17036
|
+
function snapshotHasPlaintextSecrets(snapshot) {
|
|
17037
|
+
for (const state of Object.values(snapshot.servers)) {
|
|
17038
|
+
if (state.tokens) return true;
|
|
17039
|
+
if (clientInfoHasPlaintext(state.clientInformation)) return true;
|
|
17040
|
+
if (clientInfoHasPlaintext(state.preregisteredClientInformation)) {
|
|
17041
|
+
return true;
|
|
17042
|
+
}
|
|
17043
|
+
for (const slot of Object.values(state.byIssuer ?? {})) {
|
|
17044
|
+
if (slot.tokens) return true;
|
|
17045
|
+
if (clientInfoHasPlaintext(slot.clientInformation)) return true;
|
|
17046
|
+
}
|
|
17047
|
+
}
|
|
17048
|
+
for (const session of Object.values(snapshot.idpSessions)) {
|
|
17049
|
+
if (session.idToken !== void 0 || session.refreshToken !== void 0) {
|
|
17050
|
+
return true;
|
|
17051
|
+
}
|
|
17052
|
+
}
|
|
17053
|
+
return false;
|
|
17054
|
+
}
|
|
17055
|
+
|
|
17056
|
+
// ../../core/auth/node/oauth-persist-file.ts
|
|
17057
|
+
var warnedStoreFailures = /* @__PURE__ */ new Set();
|
|
17058
|
+
function warnStoreWriteFailure(error) {
|
|
17059
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
17060
|
+
if (warnedStoreFailures.has(reason)) return;
|
|
17061
|
+
warnedStoreFailures.add(reason);
|
|
17062
|
+
console.warn(
|
|
17063
|
+
`[mcp-inspector] Could not write OAuth tokens to the secret store (${reason}). Tokens will be kept in memory for this session only and will NOT be persisted; expect to re-authorize after a restart.`
|
|
17064
|
+
);
|
|
17065
|
+
}
|
|
17066
|
+
function warnRestoreFailure(error) {
|
|
17067
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
17068
|
+
const key = `restore:${reason}`;
|
|
17069
|
+
if (warnedStoreFailures.has(key)) return;
|
|
17070
|
+
warnedStoreFailures.add(key);
|
|
17071
|
+
console.warn(
|
|
17072
|
+
`[mcp-inspector] Could not restore secret-store entries after a failed OAuth state write (${reason}). The secret store may be inconsistent with oauth.json; if a server's stored credentials stop working, re-authorize it.`
|
|
17073
|
+
);
|
|
17074
|
+
}
|
|
17075
|
+
function warnUnconfirmedFile(error) {
|
|
17076
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
17077
|
+
const key = `unconfirmed:${reason}`;
|
|
17078
|
+
if (warnedStoreFailures.has(key)) return;
|
|
17079
|
+
warnedStoreFailures.add(key);
|
|
17080
|
+
console.warn(
|
|
17081
|
+
`[mcp-inspector] Could not re-read oauth.json after a failed OAuth state save (${reason}). The file may still contain the interrupted save while the secret store was restored to the previous values; if a server's stored credentials stop working, re-authorize it.`
|
|
17082
|
+
);
|
|
17083
|
+
}
|
|
17084
|
+
function warnMigrationFailure(error) {
|
|
17085
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
17086
|
+
const key = `migration:${reason}`;
|
|
17087
|
+
if (warnedStoreFailures.has(key)) return;
|
|
17088
|
+
warnedStoreFailures.add(key);
|
|
17089
|
+
console.warn(
|
|
17090
|
+
`[mcp-inspector] Could not migrate plaintext OAuth secrets into the secret store (${reason}). The plaintext copy in oauth.json was kept and keeps working; migration will be retried on the next read.`
|
|
17091
|
+
);
|
|
17092
|
+
}
|
|
17093
|
+
function rethrowLockError(filePath, error, action = "save") {
|
|
17094
|
+
if (error instanceof SecretFileLockHeldError) {
|
|
17095
|
+
throw new SecretFileLockHeldError(
|
|
17096
|
+
`Could not ${action} OAuth state: the state file at ${filePath} is locked by another Inspector process and did not become available.`,
|
|
17097
|
+
{ cause: error }
|
|
17098
|
+
);
|
|
17099
|
+
}
|
|
17100
|
+
throw error;
|
|
17101
|
+
}
|
|
17102
|
+
async function withOAuthStateLock(filePath, action, body) {
|
|
17103
|
+
let entered = false;
|
|
17104
|
+
try {
|
|
17105
|
+
return await withSecretFileLock(filePath, async () => {
|
|
17106
|
+
entered = true;
|
|
17107
|
+
return body();
|
|
17108
|
+
});
|
|
17109
|
+
} catch (error) {
|
|
17110
|
+
if (!entered) rethrowLockError(filePath, error, action);
|
|
17111
|
+
throw error;
|
|
17112
|
+
}
|
|
17113
|
+
}
|
|
17114
|
+
var OAuthStateFileUnrecognizedError = class extends Error {
|
|
17115
|
+
constructor(filePath, action) {
|
|
17116
|
+
super(
|
|
17117
|
+
`Refusing to ${action} OAuth state: ${filePath} exists but is not a recognized OAuth state file (it may be corrupt, truncated, or written by something else). Its entries are the only index of credentials in the OS keychain / secret store, so overwriting it would strand them. Restore the file from a backup or fix its JSON; deleting it starts fresh but abandons any credentials it indexed.`
|
|
17118
|
+
);
|
|
17119
|
+
this.name = "OAuthStateFileUnrecognizedError";
|
|
17120
|
+
}
|
|
17121
|
+
};
|
|
17122
|
+
async function readDiskForMutation(filePath, action) {
|
|
17123
|
+
const raw = await readStoreFile(filePath);
|
|
17124
|
+
const parsed = parseOAuthPersistBlob(raw);
|
|
17125
|
+
if (raw !== null && parsed === null) {
|
|
17126
|
+
throw new OAuthStateFileUnrecognizedError(filePath, action);
|
|
17127
|
+
}
|
|
17128
|
+
return parsed;
|
|
17129
|
+
}
|
|
17130
|
+
async function persistEntrySecrets(store, serverId, candidates, secrets, prior, allowDegrade) {
|
|
17131
|
+
const priorValue = new Map(prior.map(({ field, value }) => [field, value]));
|
|
17132
|
+
const changed = {};
|
|
17133
|
+
for (const [field, value] of Object.entries(secrets)) {
|
|
17134
|
+
if (priorValue.get(field) !== value) changed[field] = value;
|
|
17135
|
+
}
|
|
17136
|
+
try {
|
|
17137
|
+
if (Object.keys(changed).length > 0) {
|
|
17138
|
+
await secretStoreSetMany(store, serverId, changed);
|
|
17139
|
+
}
|
|
17140
|
+
} catch (error) {
|
|
17141
|
+
if (!allowDegrade) throw error;
|
|
17142
|
+
warnStoreWriteFailure(error);
|
|
17143
|
+
const touched = prior.filter(({ field }) => changed[field] !== void 0);
|
|
17144
|
+
let restoreFailure;
|
|
17145
|
+
await restoreSecretFields(store, touched, (err) => {
|
|
17146
|
+
restoreFailure = err;
|
|
17147
|
+
});
|
|
17148
|
+
if (restoreFailure !== void 0) throw restoreFailure;
|
|
17149
|
+
return false;
|
|
17150
|
+
}
|
|
17151
|
+
await settleStoreMutations(
|
|
17152
|
+
candidates.filter(
|
|
17153
|
+
(field) => secrets[field] === void 0 && priorValue.get(field) !== null
|
|
17154
|
+
).map((field) => store.delete(serverId, field))
|
|
17155
|
+
);
|
|
17156
|
+
return true;
|
|
17157
|
+
}
|
|
17158
|
+
function revertEntryToDisk(merged, disk, key) {
|
|
17159
|
+
const diskEntry = getOwnEntry(disk, key);
|
|
17160
|
+
if (diskEntry === void 0) {
|
|
17161
|
+
if (Object.hasOwn(merged, key)) delete merged[key];
|
|
17162
|
+
} else {
|
|
17163
|
+
setOwnEntry(merged, key, diskEntry);
|
|
17164
|
+
}
|
|
17165
|
+
}
|
|
17166
|
+
function preserveNonDurableSecrets(diskSecrets, secrets) {
|
|
17167
|
+
const keep = {};
|
|
17168
|
+
for (const [field, value] of Object.entries(secrets)) {
|
|
17169
|
+
if (diskSecrets[field] === value) keep[field] = value;
|
|
17170
|
+
}
|
|
17171
|
+
return keep;
|
|
17172
|
+
}
|
|
17173
|
+
async function writeOAuthSections(filePath, snapshot, sections, secretStore = defaultSecretStore()) {
|
|
17174
|
+
const policy = getPersistTokensPolicy();
|
|
17175
|
+
const durable = await secretStoreIsDurable(secretStore);
|
|
17176
|
+
await withOAuthStateLock(filePath, "save", async () => {
|
|
17177
|
+
const restoreBaseline = /* @__PURE__ */ new Map();
|
|
17178
|
+
const ourWrites = /* @__PURE__ */ new Map();
|
|
17179
|
+
const priorKey = (p) => `${p.serverId}\0${p.field}`;
|
|
17180
|
+
const foldPriors = (priors) => {
|
|
17181
|
+
for (const prior of priors) {
|
|
17182
|
+
const key = priorKey(prior);
|
|
17183
|
+
if (restoreBaseline.has(key) && ourWrites.get(key) !== void 0 && prior.value === ourWrites.get(key)) {
|
|
17184
|
+
continue;
|
|
17185
|
+
}
|
|
17186
|
+
restoreBaseline.set(key, prior);
|
|
17187
|
+
}
|
|
17188
|
+
};
|
|
17189
|
+
const restoreToBaseline = () => restoreSecretFields(
|
|
17190
|
+
secretStore,
|
|
17191
|
+
[...restoreBaseline.values()],
|
|
17192
|
+
warnRestoreFailure
|
|
17193
|
+
);
|
|
17194
|
+
let unconfirmed = null;
|
|
17195
|
+
const reconcileFailure = async () => {
|
|
17196
|
+
if (unconfirmed !== null) {
|
|
17197
|
+
const committed = unconfirmed;
|
|
17198
|
+
let observed = null;
|
|
17199
|
+
let readable = true;
|
|
17200
|
+
try {
|
|
17201
|
+
observed = await readStoreFile(filePath);
|
|
17202
|
+
} catch (error) {
|
|
17203
|
+
readable = false;
|
|
17204
|
+
warnUnconfirmedFile(error);
|
|
17205
|
+
}
|
|
17206
|
+
if (readable && observed === committed.written) {
|
|
17207
|
+
const target = new Map(
|
|
17208
|
+
[...restoreBaseline].map(([key, { serverId, field, value }]) => [
|
|
17209
|
+
key,
|
|
17210
|
+
{ serverId, field, value }
|
|
17211
|
+
])
|
|
17212
|
+
);
|
|
17213
|
+
for (const [key, write] of committed.writes) target.set(key, write);
|
|
17214
|
+
try {
|
|
17215
|
+
await settleStoreMutations(
|
|
17216
|
+
[...target.values()].map(
|
|
17217
|
+
({ serverId, field, value }) => value === null ? secretStore.delete(serverId, field) : secretStore.set(serverId, field, value)
|
|
17218
|
+
)
|
|
17219
|
+
);
|
|
17220
|
+
return true;
|
|
17221
|
+
} catch (error) {
|
|
17222
|
+
warnRestoreFailure(error);
|
|
17223
|
+
return false;
|
|
17224
|
+
}
|
|
17225
|
+
}
|
|
17226
|
+
}
|
|
17227
|
+
await restoreToBaseline();
|
|
17228
|
+
return false;
|
|
17229
|
+
};
|
|
17230
|
+
for (let attempt = 0; attempt < MAX_WRITE_ATTEMPTS; attempt++) {
|
|
17231
|
+
const priorSecrets = [];
|
|
17232
|
+
const attemptWrites = /* @__PURE__ */ new Map();
|
|
17233
|
+
let written;
|
|
17234
|
+
try {
|
|
17235
|
+
const disk = await readDiskForMutation(filePath, "save");
|
|
17236
|
+
const effective = sections ? {
|
|
17237
|
+
servers: sections.servers && [...new Set(sections.servers)],
|
|
17238
|
+
idpSessions: sections.idpSessions && [
|
|
17239
|
+
...new Set(sections.idpSessions)
|
|
17240
|
+
]
|
|
17241
|
+
} : {
|
|
17242
|
+
servers: [
|
|
17243
|
+
.../* @__PURE__ */ new Set([
|
|
17244
|
+
...Object.keys(disk?.servers ?? {}),
|
|
17245
|
+
...Object.keys(snapshot.servers)
|
|
17246
|
+
])
|
|
17247
|
+
],
|
|
17248
|
+
idpSessions: [
|
|
17249
|
+
.../* @__PURE__ */ new Set([
|
|
17250
|
+
...Object.keys(disk?.idpSessions ?? {}),
|
|
17251
|
+
...Object.keys(snapshot.idpSessions)
|
|
17252
|
+
])
|
|
17253
|
+
]
|
|
17254
|
+
};
|
|
17255
|
+
const merged = mergeOAuthSections(disk, snapshot, effective);
|
|
17256
|
+
for (const url of effective.servers ?? []) {
|
|
17257
|
+
const serverId = oauthSecretServerId(url);
|
|
17258
|
+
const next = getOwnEntry(snapshot.servers, url);
|
|
17259
|
+
const candidates = [
|
|
17260
|
+
.../* @__PURE__ */ new Set([
|
|
17261
|
+
...serverSecretFields(getOwnEntry(disk?.servers, url)),
|
|
17262
|
+
...serverSecretFields(next)
|
|
17263
|
+
])
|
|
17264
|
+
];
|
|
17265
|
+
const entryPrior = await snapshotSecretFields(
|
|
17266
|
+
secretStore,
|
|
17267
|
+
serverId,
|
|
17268
|
+
candidates
|
|
17269
|
+
);
|
|
17270
|
+
priorSecrets.push(...entryPrior);
|
|
17271
|
+
if (next === void 0) {
|
|
17272
|
+
for (const field of candidates) {
|
|
17273
|
+
ourWrites.set(priorKey({ serverId, field }), null);
|
|
17274
|
+
}
|
|
17275
|
+
await secretStore.deleteAllForServer(serverId);
|
|
17276
|
+
for (const field of candidates) {
|
|
17277
|
+
attemptWrites.set(priorKey({ serverId, field }), {
|
|
17278
|
+
serverId,
|
|
17279
|
+
field,
|
|
17280
|
+
value: null
|
|
17281
|
+
});
|
|
17282
|
+
}
|
|
17283
|
+
continue;
|
|
17284
|
+
}
|
|
17285
|
+
const { residue, secrets } = splitServerOAuthState(next, policy);
|
|
17286
|
+
for (const field of candidates) {
|
|
17287
|
+
ourWrites.set(
|
|
17288
|
+
priorKey({ serverId, field }),
|
|
17289
|
+
secrets[field] ?? null
|
|
17290
|
+
);
|
|
17291
|
+
}
|
|
17292
|
+
setOwnEntry(merged.servers, url, residue);
|
|
17293
|
+
if (!durable) {
|
|
17294
|
+
const diskEntry = getOwnEntry(disk?.servers, url);
|
|
17295
|
+
const keep = preserveNonDurableSecrets(
|
|
17296
|
+
diskEntry ? splitServerOAuthState(diskEntry, policy).secrets : {},
|
|
17297
|
+
secrets
|
|
17298
|
+
);
|
|
17299
|
+
if (Object.keys(keep).length > 0) {
|
|
17300
|
+
setOwnEntry(
|
|
17301
|
+
merged.servers,
|
|
17302
|
+
url,
|
|
17303
|
+
joinServerOAuthState(residue, keep)
|
|
17304
|
+
);
|
|
17305
|
+
}
|
|
17306
|
+
}
|
|
17307
|
+
const persisted = await persistEntrySecrets(
|
|
17308
|
+
secretStore,
|
|
17309
|
+
serverId,
|
|
17310
|
+
candidates,
|
|
17311
|
+
secrets,
|
|
17312
|
+
entryPrior,
|
|
17313
|
+
// Degrading is only sound when the disk entry is the pre-call
|
|
17314
|
+
// state this attempt's priors pair with; on a retry it may be an
|
|
17315
|
+
// earlier attempt's committed residue, so escalate into the
|
|
17316
|
+
// reconciling exit instead.
|
|
17317
|
+
attempt === 0
|
|
17318
|
+
);
|
|
17319
|
+
if (!persisted) {
|
|
17320
|
+
revertEntryToDisk(merged.servers, disk?.servers, url);
|
|
17321
|
+
continue;
|
|
17322
|
+
}
|
|
17323
|
+
for (const field of candidates) {
|
|
17324
|
+
attemptWrites.set(priorKey({ serverId, field }), {
|
|
17325
|
+
serverId,
|
|
17326
|
+
field,
|
|
17327
|
+
value: secrets[field] ?? null
|
|
17328
|
+
});
|
|
17329
|
+
}
|
|
17330
|
+
}
|
|
17331
|
+
for (const issuer of effective.idpSessions ?? []) {
|
|
17332
|
+
const serverId = oauthIdpSecretServerId(issuer);
|
|
17333
|
+
const next = getOwnEntry(snapshot.idpSessions, issuer);
|
|
17334
|
+
const entryPrior = await snapshotSecretFields(secretStore, serverId, [
|
|
17335
|
+
IDP_SESSION_FIELD
|
|
17336
|
+
]);
|
|
17337
|
+
priorSecrets.push(...entryPrior);
|
|
17338
|
+
if (next === void 0) {
|
|
17339
|
+
ourWrites.set(
|
|
17340
|
+
priorKey({ serverId, field: IDP_SESSION_FIELD }),
|
|
17341
|
+
null
|
|
17342
|
+
);
|
|
17343
|
+
await secretStore.deleteAllForServer(serverId);
|
|
17344
|
+
attemptWrites.set(
|
|
17345
|
+
priorKey({ serverId, field: IDP_SESSION_FIELD }),
|
|
17346
|
+
{
|
|
17347
|
+
serverId,
|
|
17348
|
+
field: IDP_SESSION_FIELD,
|
|
17349
|
+
value: null
|
|
17350
|
+
}
|
|
17351
|
+
);
|
|
17352
|
+
continue;
|
|
17353
|
+
}
|
|
17354
|
+
const { residue, secrets } = splitIdpSession(next, policy);
|
|
17355
|
+
ourWrites.set(
|
|
17356
|
+
priorKey({ serverId, field: IDP_SESSION_FIELD }),
|
|
17357
|
+
secrets[IDP_SESSION_FIELD] ?? null
|
|
17358
|
+
);
|
|
17359
|
+
setOwnEntry(merged.idpSessions, issuer, residue);
|
|
17360
|
+
if (!durable) {
|
|
17361
|
+
const diskSession = getOwnEntry(disk?.idpSessions, issuer);
|
|
17362
|
+
const keep = preserveNonDurableSecrets(
|
|
17363
|
+
diskSession ? splitIdpSession(diskSession, policy).secrets : {},
|
|
17364
|
+
secrets
|
|
17365
|
+
);
|
|
17366
|
+
if (Object.keys(keep).length > 0) {
|
|
17367
|
+
setOwnEntry(
|
|
17368
|
+
merged.idpSessions,
|
|
17369
|
+
issuer,
|
|
17370
|
+
joinIdpSession(residue, keep)
|
|
17371
|
+
);
|
|
17372
|
+
}
|
|
17373
|
+
}
|
|
17374
|
+
const persisted = await persistEntrySecrets(
|
|
17375
|
+
secretStore,
|
|
17376
|
+
serverId,
|
|
17377
|
+
[IDP_SESSION_FIELD],
|
|
17378
|
+
secrets,
|
|
17379
|
+
entryPrior,
|
|
17380
|
+
// Same as the server loop: degrade on the first attempt only.
|
|
17381
|
+
attempt === 0
|
|
17382
|
+
);
|
|
17383
|
+
if (!persisted) {
|
|
17384
|
+
revertEntryToDisk(merged.idpSessions, disk?.idpSessions, issuer);
|
|
17385
|
+
continue;
|
|
17386
|
+
}
|
|
17387
|
+
attemptWrites.set(priorKey({ serverId, field: IDP_SESSION_FIELD }), {
|
|
17388
|
+
serverId,
|
|
17389
|
+
field: IDP_SESSION_FIELD,
|
|
17390
|
+
value: secrets[IDP_SESSION_FIELD] ?? null
|
|
17391
|
+
});
|
|
17392
|
+
}
|
|
17393
|
+
written = serializeOAuthPersistBlob(merged);
|
|
17394
|
+
await writeStoreFile(filePath, written);
|
|
17395
|
+
unconfirmed = { written, writes: attemptWrites };
|
|
17396
|
+
} catch (error) {
|
|
17397
|
+
foldPriors(priorSecrets);
|
|
17398
|
+
if (await reconcileFailure()) return;
|
|
17399
|
+
throw error;
|
|
16115
17400
|
}
|
|
16116
|
-
|
|
16117
|
-
|
|
16118
|
-
|
|
16119
|
-
|
|
16120
|
-
|
|
16121
|
-
|
|
16122
|
-
|
|
17401
|
+
foldPriors(priorSecrets);
|
|
17402
|
+
let observed;
|
|
17403
|
+
try {
|
|
17404
|
+
observed = await readStoreFile(filePath);
|
|
17405
|
+
} catch {
|
|
17406
|
+
continue;
|
|
17407
|
+
}
|
|
17408
|
+
if (observed === written) return;
|
|
17409
|
+
unconfirmed = null;
|
|
17410
|
+
}
|
|
17411
|
+
if (await reconcileFailure()) return;
|
|
17412
|
+
throw new SecretStoreUnavailableError(
|
|
17413
|
+
`Could not save OAuth state: another process kept overwriting ${filePath} (gave up after ${MAX_WRITE_ATTEMPTS} attempts). Re-run the action to retry.`
|
|
17414
|
+
);
|
|
17415
|
+
});
|
|
17416
|
+
}
|
|
17417
|
+
function secretRequestsFor(snapshot) {
|
|
17418
|
+
const requests = [];
|
|
17419
|
+
for (const [url, state] of Object.entries(snapshot.servers)) {
|
|
17420
|
+
requests.push({
|
|
17421
|
+
serverId: oauthSecretServerId(url),
|
|
17422
|
+
fields: serverSecretFields(state)
|
|
17423
|
+
});
|
|
16123
17424
|
}
|
|
16124
|
-
|
|
16125
|
-
|
|
16126
|
-
|
|
17425
|
+
for (const issuer of Object.keys(snapshot.idpSessions)) {
|
|
17426
|
+
requests.push({
|
|
17427
|
+
serverId: oauthIdpSecretServerId(issuer),
|
|
17428
|
+
fields: [IDP_SESSION_FIELD]
|
|
17429
|
+
});
|
|
16127
17430
|
}
|
|
16128
|
-
|
|
16129
|
-
|
|
16130
|
-
// ../../core/auth/oauth-persist.ts
|
|
16131
|
-
function isRecord2(value) {
|
|
16132
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17431
|
+
return requests;
|
|
16133
17432
|
}
|
|
16134
|
-
function
|
|
17433
|
+
async function joinSnapshot(snapshot, secretStore) {
|
|
17434
|
+
const requests = secretRequestsFor(snapshot);
|
|
17435
|
+
const values = requests.length > 0 ? await secretStoreGetManyStrict(secretStore, requests) : {};
|
|
16135
17436
|
return {
|
|
16136
|
-
servers:
|
|
16137
|
-
|
|
17437
|
+
servers: Object.fromEntries(
|
|
17438
|
+
Object.entries(snapshot.servers).map(([url, state]) => [
|
|
17439
|
+
url,
|
|
17440
|
+
joinServerOAuthState(state, values[oauthSecretServerId(url)] ?? {})
|
|
17441
|
+
])
|
|
17442
|
+
),
|
|
17443
|
+
idpSessions: Object.fromEntries(
|
|
17444
|
+
Object.entries(snapshot.idpSessions).map(([issuer, session]) => [
|
|
17445
|
+
issuer,
|
|
17446
|
+
joinIdpSession(session, values[oauthIdpSecretServerId(issuer)] ?? {})
|
|
17447
|
+
])
|
|
17448
|
+
)
|
|
16138
17449
|
};
|
|
16139
17450
|
}
|
|
16140
|
-
function
|
|
16141
|
-
|
|
16142
|
-
|
|
16143
|
-
|
|
16144
|
-
const
|
|
16145
|
-
|
|
16146
|
-
|
|
16147
|
-
|
|
16148
|
-
|
|
16149
|
-
|
|
16150
|
-
|
|
16151
|
-
|
|
16152
|
-
|
|
16153
|
-
|
|
16154
|
-
|
|
17451
|
+
async function migratePlaintextSecrets(filePath, secretStore) {
|
|
17452
|
+
const raw = await readStoreFile(filePath);
|
|
17453
|
+
const fresh = parseOAuthPersistBlob(raw);
|
|
17454
|
+
if (!fresh || !snapshotHasPlaintextSecrets(fresh)) return;
|
|
17455
|
+
const migrateEntrySecrets = async (serverId, secrets) => {
|
|
17456
|
+
const absent = {};
|
|
17457
|
+
for (const [field, value] of Object.entries(secrets)) {
|
|
17458
|
+
const existing = await secretStoreGetStrict(secretStore, serverId, field);
|
|
17459
|
+
if (existing === null || !isUsableStoredSecret(field, existing)) {
|
|
17460
|
+
absent[field] = value;
|
|
17461
|
+
}
|
|
17462
|
+
}
|
|
17463
|
+
if (Object.keys(absent).length > 0) {
|
|
17464
|
+
await secretStoreSetMany(secretStore, serverId, absent);
|
|
17465
|
+
}
|
|
17466
|
+
};
|
|
17467
|
+
const residue = { servers: {}, idpSessions: {} };
|
|
17468
|
+
for (const [url, state] of Object.entries(fresh.servers)) {
|
|
17469
|
+
const split = splitServerOAuthState(state, "all");
|
|
17470
|
+
setOwnEntry(residue.servers, url, split.residue);
|
|
17471
|
+
await migrateEntrySecrets(oauthSecretServerId(url), split.secrets);
|
|
17472
|
+
}
|
|
17473
|
+
for (const [issuer, session] of Object.entries(fresh.idpSessions)) {
|
|
17474
|
+
const split = splitIdpSession(session, "all");
|
|
17475
|
+
setOwnEntry(residue.idpSessions, issuer, split.residue);
|
|
17476
|
+
await migrateEntrySecrets(oauthIdpSecretServerId(issuer), split.secrets);
|
|
17477
|
+
}
|
|
17478
|
+
const stripped = serializeOAuthPersistBlob(residue);
|
|
17479
|
+
if (stripped !== raw) {
|
|
17480
|
+
await writeStoreFile(filePath, stripped);
|
|
17481
|
+
}
|
|
17482
|
+
}
|
|
17483
|
+
async function readOAuthStore(filePath, secretStore = defaultSecretStore()) {
|
|
17484
|
+
return withOAuthStateLock(filePath, "read", async () => {
|
|
17485
|
+
let snapshot = parseOAuthPersistBlob(await readStoreFile(filePath));
|
|
17486
|
+
if (snapshot === null) return null;
|
|
17487
|
+
if (snapshotHasPlaintextSecrets(snapshot) && await secretStoreIsDurable(secretStore)) {
|
|
17488
|
+
try {
|
|
17489
|
+
await migratePlaintextSecrets(filePath, secretStore);
|
|
17490
|
+
snapshot = parseOAuthPersistBlob(await readStoreFile(filePath)) ?? snapshot;
|
|
17491
|
+
} catch (error) {
|
|
17492
|
+
warnMigrationFailure(error);
|
|
17493
|
+
}
|
|
17494
|
+
}
|
|
17495
|
+
return joinSnapshot(snapshot, secretStore);
|
|
17496
|
+
});
|
|
16155
17497
|
}
|
|
16156
|
-
function
|
|
16157
|
-
|
|
17498
|
+
async function removeOAuthStore(filePath, secretStore = defaultSecretStore()) {
|
|
17499
|
+
await withOAuthStateLock(filePath, "remove", async () => {
|
|
17500
|
+
const snapshot = await readDiskForMutation(filePath, "remove");
|
|
17501
|
+
if (snapshot) {
|
|
17502
|
+
const targets = [
|
|
17503
|
+
...Object.entries(snapshot.servers).map(([url, state]) => ({
|
|
17504
|
+
id: oauthSecretServerId(url),
|
|
17505
|
+
fields: serverSecretFields(state)
|
|
17506
|
+
})),
|
|
17507
|
+
...Object.keys(snapshot.idpSessions).map((issuer) => ({
|
|
17508
|
+
id: oauthIdpSecretServerId(issuer),
|
|
17509
|
+
fields: [IDP_SESSION_FIELD]
|
|
17510
|
+
}))
|
|
17511
|
+
];
|
|
17512
|
+
const priorSecrets = [];
|
|
17513
|
+
try {
|
|
17514
|
+
for (const { id, fields } of targets) {
|
|
17515
|
+
priorSecrets.push(
|
|
17516
|
+
...await snapshotSecretFields(secretStore, id, fields)
|
|
17517
|
+
);
|
|
17518
|
+
await secretStore.deleteAllForServer(id);
|
|
17519
|
+
}
|
|
17520
|
+
await deleteStoreFile(filePath);
|
|
17521
|
+
} catch (error) {
|
|
17522
|
+
await restoreSecretFields(
|
|
17523
|
+
secretStore,
|
|
17524
|
+
priorSecrets,
|
|
17525
|
+
warnRestoreFailure
|
|
17526
|
+
);
|
|
17527
|
+
throw error;
|
|
17528
|
+
}
|
|
17529
|
+
} else {
|
|
17530
|
+
await deleteStoreFile(filePath);
|
|
17531
|
+
}
|
|
17532
|
+
});
|
|
16158
17533
|
}
|
|
16159
|
-
|
|
16160
|
-
// ../../core/auth/node/oauth-persist-file.ts
|
|
16161
17534
|
function createFileOAuthPersistBackend(options) {
|
|
17535
|
+
const secretStore = options.secretStore ?? defaultSecretStore();
|
|
16162
17536
|
return {
|
|
16163
17537
|
async read() {
|
|
16164
|
-
|
|
16165
|
-
return parseOAuthPersistBlob(raw);
|
|
17538
|
+
return readOAuthStore(options.filePath, secretStore);
|
|
16166
17539
|
},
|
|
16167
|
-
async write(snapshot) {
|
|
16168
|
-
await
|
|
17540
|
+
async write(snapshot, sections) {
|
|
17541
|
+
await writeOAuthSections(
|
|
16169
17542
|
options.filePath,
|
|
16170
|
-
|
|
17543
|
+
snapshot,
|
|
17544
|
+
sections,
|
|
17545
|
+
secretStore
|
|
16171
17546
|
);
|
|
16172
17547
|
},
|
|
16173
17548
|
async remove() {
|
|
16174
|
-
await
|
|
17549
|
+
await removeOAuthStore(options.filePath, secretStore);
|
|
16175
17550
|
}
|
|
16176
17551
|
};
|
|
16177
17552
|
}
|
|
@@ -16188,25 +17563,33 @@ function getStateFilePath(customPath) {
|
|
|
16188
17563
|
}
|
|
16189
17564
|
return DEFAULT_STATE_PATH;
|
|
16190
17565
|
}
|
|
16191
|
-
var
|
|
16192
|
-
function
|
|
17566
|
+
var sharedStateCache = /* @__PURE__ */ new Map();
|
|
17567
|
+
function getSharedState(stateFilePath) {
|
|
16193
17568
|
const key = getStateFilePath(stateFilePath);
|
|
16194
|
-
let
|
|
16195
|
-
if (!
|
|
16196
|
-
|
|
16197
|
-
|
|
17569
|
+
let shared = sharedStateCache.get(key);
|
|
17570
|
+
if (!shared) {
|
|
17571
|
+
shared = {
|
|
17572
|
+
memory: new OAuthMemoryStore(),
|
|
17573
|
+
coordination: new OAuthStorageCoordination()
|
|
17574
|
+
};
|
|
17575
|
+
sharedStateCache.set(key, shared);
|
|
16198
17576
|
}
|
|
16199
|
-
return
|
|
17577
|
+
return shared;
|
|
16200
17578
|
}
|
|
16201
17579
|
var NodeOAuthStorage = class extends OAuthStorageBase {
|
|
16202
17580
|
/**
|
|
16203
17581
|
* @param storagePath - Optional path to state file. Default: ~/.mcp-inspector/storage/oauth.json
|
|
17582
|
+
* @param secretStore - Optional secret store for tokens/client secrets.
|
|
17583
|
+
* Default: the process-wide selected store. Tests inject an in-memory
|
|
17584
|
+
* double here so they never touch the OS keychain.
|
|
16204
17585
|
*/
|
|
16205
|
-
constructor(storagePath) {
|
|
17586
|
+
constructor(storagePath, secretStore) {
|
|
16206
17587
|
const filePath = getStateFilePath(storagePath);
|
|
17588
|
+
const shared = getSharedState(storagePath);
|
|
16207
17589
|
super(
|
|
16208
|
-
|
|
16209
|
-
createFileOAuthPersistBackend({ filePath })
|
|
17590
|
+
shared.memory,
|
|
17591
|
+
createFileOAuthPersistBackend({ filePath, secretStore }),
|
|
17592
|
+
shared.coordination
|
|
16210
17593
|
);
|
|
16211
17594
|
}
|
|
16212
17595
|
};
|
|
@@ -18141,7 +19524,11 @@ async function verifySkills(client, entries, metadata) {
|
|
|
18141
19524
|
files,
|
|
18142
19525
|
...incomplete ? { incomplete } : {},
|
|
18143
19526
|
ok: !hasError && !fileFailed,
|
|
18144
|
-
|
|
19527
|
+
// Precedence runs from the loudest verdict down: a broken MUST outranks
|
|
19528
|
+
// an unfinished walk, and an unfinished walk outranks a skill that had
|
|
19529
|
+
// nothing to hash — a `"dynamic"` skill past the run's catalog budget
|
|
19530
|
+
// was not read at all, which `incomplete` already says more precisely.
|
|
19531
|
+
outcome: hasError || fileFailed ? "failed" : incomplete !== void 0 ? "incomplete" : entry.resources === DYNAMIC_RESOURCES ? "unverifiable" : "verified"
|
|
18145
19532
|
});
|
|
18146
19533
|
}
|
|
18147
19534
|
return reports;
|
|
@@ -18173,6 +19560,7 @@ var FILE_COLOR = {
|
|
|
18173
19560
|
};
|
|
18174
19561
|
var VERIFY_STATUS = {
|
|
18175
19562
|
verified: "[Verified \u2014 Enter to re-verify]",
|
|
19563
|
+
unverifiable: "[UNVERIFIABLE \u2014 Enter to re-verify]",
|
|
18176
19564
|
incomplete: "[Verification INCOMPLETE \u2014 Enter to re-verify]",
|
|
18177
19565
|
failed: "[Verification FAILED \u2014 Enter to re-verify]"
|
|
18178
19566
|
};
|
|
@@ -18485,7 +19873,7 @@ var BOOLEAN_VALUED_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
18485
19873
|
"additionalItems",
|
|
18486
19874
|
"unevaluatedItems"
|
|
18487
19875
|
]);
|
|
18488
|
-
var
|
|
19876
|
+
var SUBSCHEMA_KEYWORDS2 = [
|
|
18489
19877
|
"items",
|
|
18490
19878
|
"contains",
|
|
18491
19879
|
"not",
|
|
@@ -18502,13 +19890,13 @@ var SUBSCHEMA_KEYWORDS = [
|
|
|
18502
19890
|
// real finding.
|
|
18503
19891
|
"contentSchema"
|
|
18504
19892
|
];
|
|
18505
|
-
var
|
|
19893
|
+
var SUBSCHEMA_ARRAY_KEYWORDS2 = [
|
|
18506
19894
|
"allOf",
|
|
18507
19895
|
"anyOf",
|
|
18508
19896
|
"oneOf",
|
|
18509
19897
|
"prefixItems"
|
|
18510
19898
|
];
|
|
18511
|
-
var
|
|
19899
|
+
var SUBSCHEMA_MAP_KEYWORDS2 = [
|
|
18512
19900
|
"properties",
|
|
18513
19901
|
"patternProperties",
|
|
18514
19902
|
"dependentSchemas",
|
|
@@ -18590,8 +19978,8 @@ function isPortableTypeUnion(type) {
|
|
|
18590
19978
|
}
|
|
18591
19979
|
return new Set(type).size === type.length;
|
|
18592
19980
|
}
|
|
18593
|
-
var
|
|
18594
|
-
function
|
|
19981
|
+
var MAX_DEPTH2 = 64;
|
|
19982
|
+
function isRecord5(value) {
|
|
18595
19983
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18596
19984
|
}
|
|
18597
19985
|
function childPath(parent, key) {
|
|
@@ -18607,7 +19995,7 @@ function describeSchemaPath(schema, path6) {
|
|
|
18607
19995
|
return path6 === "" ? schema : `${schema}.${path6}`;
|
|
18608
19996
|
}
|
|
18609
19997
|
function declaresAnyId(node, depth = 0) {
|
|
18610
|
-
if (depth >
|
|
19998
|
+
if (depth > MAX_DEPTH2 || !isRecord5(node)) return false;
|
|
18611
19999
|
if (typeof node.$id === "string" && node.$id !== "") return true;
|
|
18612
20000
|
let found = false;
|
|
18613
20001
|
forEachSubschema(node, "", (child) => {
|
|
@@ -18626,21 +20014,21 @@ function add(ctx, rule, severity, path6, issue, suggestion) {
|
|
|
18626
20014
|
});
|
|
18627
20015
|
}
|
|
18628
20016
|
function forEachSubschema(node, path6, visit) {
|
|
18629
|
-
for (const key of
|
|
20017
|
+
for (const key of SUBSCHEMA_MAP_KEYWORDS2) {
|
|
18630
20018
|
const map = node[key];
|
|
18631
|
-
if (!
|
|
20019
|
+
if (!isRecord5(map)) continue;
|
|
18632
20020
|
for (const [name, sub] of Object.entries(map)) {
|
|
18633
20021
|
visit(sub, childPath(childPath(path6, key), name), key);
|
|
18634
20022
|
}
|
|
18635
20023
|
}
|
|
18636
|
-
for (const key of
|
|
20024
|
+
for (const key of SUBSCHEMA_ARRAY_KEYWORDS2) {
|
|
18637
20025
|
const arr = node[key];
|
|
18638
20026
|
if (!Array.isArray(arr)) continue;
|
|
18639
20027
|
arr.forEach((sub, i) => {
|
|
18640
20028
|
visit(sub, indexPath(childPath(path6, key), i), key);
|
|
18641
20029
|
});
|
|
18642
20030
|
}
|
|
18643
|
-
for (const key of
|
|
20031
|
+
for (const key of SUBSCHEMA_KEYWORDS2) {
|
|
18644
20032
|
if (!(key in node)) continue;
|
|
18645
20033
|
const value = node[key];
|
|
18646
20034
|
if (key === "items" && Array.isArray(value)) {
|
|
@@ -18659,7 +20047,7 @@ function booleanTrueSuggestion(keyword) {
|
|
|
18659
20047
|
return 'Declare what the value actually is \u2014 e.g. `{"type": "object", "additionalProperties": true}` for a free-form object. That is a deliberate change of contract, not an equivalent rewrite: `true` accepts any JSON value at all.';
|
|
18660
20048
|
}
|
|
18661
20049
|
function walk(node, path6, keyword, depth, ctx) {
|
|
18662
|
-
if (depth >
|
|
20050
|
+
if (depth > MAX_DEPTH2) return;
|
|
18663
20051
|
if (typeof node === "boolean") {
|
|
18664
20052
|
if (keyword !== void 0 && BOOLEAN_VALUED_KEYWORDS.has(keyword)) return;
|
|
18665
20053
|
add(
|
|
@@ -18678,12 +20066,13 @@ function walk(node, path6, keyword, depth, ctx) {
|
|
|
18678
20066
|
);
|
|
18679
20067
|
return;
|
|
18680
20068
|
}
|
|
18681
|
-
if (!
|
|
20069
|
+
if (!isRecord5(node)) return;
|
|
18682
20070
|
lintNode(node, path6, keyword, ctx);
|
|
18683
20071
|
forEachSubschema(node, path6, (child, childPathValue, childKeyword) => {
|
|
18684
20072
|
walk(child, childPathValue, childKeyword, depth + 1, ctx);
|
|
18685
20073
|
});
|
|
18686
20074
|
}
|
|
20075
|
+
var NULL_BRANCH_CAVEAT = " A dialect with no `null` type, such as OpenAPI 3.0, still cannot express the `null` branch directly; there nullability is written `nullable: true`, which is not JSON Schema, so no single spelling is portable to both.";
|
|
18687
20076
|
function lintNode(node, path6, keyword, ctx) {
|
|
18688
20077
|
const type = node.type;
|
|
18689
20078
|
if (Array.isArray(type) && isPortableTypeUnion(type)) {
|
|
@@ -18692,10 +20081,10 @@ function lintNode(node, path6, keyword, ctx) {
|
|
|
18692
20081
|
"type-union",
|
|
18693
20082
|
"warning",
|
|
18694
20083
|
path6,
|
|
18695
|
-
`\`type\` is an array (${JSON.stringify(type)}).
|
|
20084
|
+
`\`type\` is an array (${JSON.stringify(type)}). This is legal JSON Schema, and some model providers recommend it for nullable fields, but it is less portable: a client that maps tool schemas onto a single-\`type\` dialect (such as the OpenAPI subset used for Gemini function declarations) may reject the tool or drop the constraint.`,
|
|
18696
20085
|
`Split it into \`anyOf\` branches, each with a single \`type\` \u2014 \`{"anyOf": [${type.map((t) => `{"type": "${t}"}`).join(
|
|
18697
20086
|
", "
|
|
18698
|
-
)}]}\`. (Making the property optional instead is a different contract: absent is not the same as \`null\`.)`
|
|
20087
|
+
)}]}\`. (Making the property optional instead is a different contract: absent is not the same as \`null\`.)${type.includes("null") ? NULL_BRANCH_CAVEAT : ""}`
|
|
18699
20088
|
);
|
|
18700
20089
|
}
|
|
18701
20090
|
const ref = node.$ref;
|
|
@@ -19255,8 +20644,64 @@ function HistoryTab({
|
|
|
19255
20644
|
|
|
19256
20645
|
// src/components/RequestsTab.tsx
|
|
19257
20646
|
import React9, { useEffect as useEffect10, useRef as useRef12 } from "react";
|
|
19258
|
-
import { Box as
|
|
20647
|
+
import { Box as Box13, Text as Text12, useInput as useInput9 } from "ink";
|
|
20648
|
+
|
|
20649
|
+
// src/components/BodyLines.tsx
|
|
20650
|
+
import { Box as Box12, Text as Text11 } from "ink";
|
|
20651
|
+
|
|
20652
|
+
// src/utils/bodyLines.ts
|
|
20653
|
+
var MAX_BODY_LINES = 500;
|
|
20654
|
+
var MAX_BODY_LINE_CHARS = 2e3;
|
|
20655
|
+
function formatBody(body) {
|
|
20656
|
+
try {
|
|
20657
|
+
return JSON.stringify(JSON.parse(body), null, 2);
|
|
20658
|
+
} catch {
|
|
20659
|
+
return body;
|
|
20660
|
+
}
|
|
20661
|
+
}
|
|
20662
|
+
function clipLine(line, maxChars) {
|
|
20663
|
+
if (line.length <= maxChars) return line;
|
|
20664
|
+
return `${line.slice(0, maxChars)}\u2026 (+${line.length - maxChars} chars)`;
|
|
20665
|
+
}
|
|
20666
|
+
function layoutBody(body, maxLines = MAX_BODY_LINES, maxLineChars = MAX_BODY_LINE_CHARS) {
|
|
20667
|
+
const all = formatBody(body).split("\n");
|
|
20668
|
+
return {
|
|
20669
|
+
lines: all.slice(0, maxLines).map((line) => clipLine(line, maxLineChars)),
|
|
20670
|
+
hiddenLines: Math.max(all.length - maxLines, 0),
|
|
20671
|
+
totalLines: all.length
|
|
20672
|
+
};
|
|
20673
|
+
}
|
|
20674
|
+
|
|
20675
|
+
// src/components/BodyLines.tsx
|
|
19259
20676
|
import { Fragment as Fragment8, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
20677
|
+
function BodyLines({
|
|
20678
|
+
body,
|
|
20679
|
+
keyPrefix
|
|
20680
|
+
}) {
|
|
20681
|
+
const { lines, hiddenLines, totalLines } = layoutBody(body);
|
|
20682
|
+
return /* @__PURE__ */ jsxs11(Fragment8, { children: [
|
|
20683
|
+
lines.map((line, idx) => /* @__PURE__ */ jsx12(
|
|
20684
|
+
Box12,
|
|
20685
|
+
{
|
|
20686
|
+
marginTop: idx === 0 ? 1 : 0,
|
|
20687
|
+
paddingLeft: 2,
|
|
20688
|
+
flexShrink: 0,
|
|
20689
|
+
children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: line })
|
|
20690
|
+
},
|
|
20691
|
+
`${keyPrefix}-${idx}`
|
|
20692
|
+
)),
|
|
20693
|
+
hiddenLines > 0 && /* @__PURE__ */ jsx12(Box12, { paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsxs11(Text11, { dimColor: true, italic: true, children: [
|
|
20694
|
+
"\u2026 ",
|
|
20695
|
+
hiddenLines,
|
|
20696
|
+
" more lines not shown (",
|
|
20697
|
+
totalLines,
|
|
20698
|
+
" total)"
|
|
20699
|
+
] }) })
|
|
20700
|
+
] });
|
|
20701
|
+
}
|
|
20702
|
+
|
|
20703
|
+
// src/components/RequestsTab.tsx
|
|
20704
|
+
import { Fragment as Fragment9, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
19260
20705
|
function RequestsTab({
|
|
19261
20706
|
requests,
|
|
19262
20707
|
width,
|
|
@@ -19324,9 +20769,9 @@ function RequestsTab({
|
|
|
19324
20769
|
if (status >= 400) return "red";
|
|
19325
20770
|
return "gray";
|
|
19326
20771
|
};
|
|
19327
|
-
return /* @__PURE__ */
|
|
19328
|
-
/* @__PURE__ */
|
|
19329
|
-
|
|
20772
|
+
return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "row", width, height, children: [
|
|
20773
|
+
/* @__PURE__ */ jsxs12(
|
|
20774
|
+
Box13,
|
|
19330
20775
|
{
|
|
19331
20776
|
width: listWidth,
|
|
19332
20777
|
height,
|
|
@@ -19338,8 +20783,8 @@ function RequestsTab({
|
|
|
19338
20783
|
flexDirection: "column",
|
|
19339
20784
|
paddingX: 1,
|
|
19340
20785
|
children: [
|
|
19341
|
-
/* @__PURE__ */
|
|
19342
|
-
|
|
20786
|
+
/* @__PURE__ */ jsx13(Box13, { paddingY: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs12(
|
|
20787
|
+
Text12,
|
|
19343
20788
|
{
|
|
19344
20789
|
bold: true,
|
|
19345
20790
|
backgroundColor: focusedPane === "requests" ? "yellow" : void 0,
|
|
@@ -19350,8 +20795,8 @@ function RequestsTab({
|
|
|
19350
20795
|
]
|
|
19351
20796
|
}
|
|
19352
20797
|
) }),
|
|
19353
|
-
requests.length === 0 ? /* @__PURE__ */
|
|
19354
|
-
|
|
20798
|
+
requests.length === 0 ? /* @__PURE__ */ jsx13(Box13, { paddingY: 1, children: /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: "No requests" }) }) : /* @__PURE__ */ jsx13(
|
|
20799
|
+
Box13,
|
|
19355
20800
|
{
|
|
19356
20801
|
flexDirection: "column",
|
|
19357
20802
|
height: visibleCount,
|
|
@@ -19364,14 +20809,14 @@ function RequestsTab({
|
|
|
19364
20809
|
const statusText = req.responseStatus ? `${req.responseStatus}` : req.error ? "ERROR" : "...";
|
|
19365
20810
|
const categoryLabel = req.category === "auth" ? "AUTH" : "MCP ";
|
|
19366
20811
|
const methodPadded = req.method === "GET" ? "GET " : req.method;
|
|
19367
|
-
return /* @__PURE__ */
|
|
20812
|
+
return /* @__PURE__ */ jsx13(Box13, { paddingY: 0, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Text12, { color: isSelected ? "white" : "white", children: [
|
|
19368
20813
|
isSelected ? "\u25B6 " : " ",
|
|
19369
|
-
/* @__PURE__ */
|
|
20814
|
+
/* @__PURE__ */ jsx13(Text12, { children: categoryLabel }),
|
|
19370
20815
|
" ",
|
|
19371
|
-
/* @__PURE__ */
|
|
20816
|
+
/* @__PURE__ */ jsx13(Text12, { color: statusColor, children: methodPadded }),
|
|
19372
20817
|
" ",
|
|
19373
|
-
/* @__PURE__ */
|
|
19374
|
-
req.duration !== void 0 && /* @__PURE__ */
|
|
20818
|
+
/* @__PURE__ */ jsx13(Text12, { dimColor: true, children: statusText }),
|
|
20819
|
+
req.duration !== void 0 && /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
19375
20820
|
" ",
|
|
19376
20821
|
req.duration,
|
|
19377
20822
|
"ms"
|
|
@@ -19383,8 +20828,8 @@ function RequestsTab({
|
|
|
19383
20828
|
]
|
|
19384
20829
|
}
|
|
19385
20830
|
),
|
|
19386
|
-
/* @__PURE__ */
|
|
19387
|
-
|
|
20831
|
+
/* @__PURE__ */ jsx13(
|
|
20832
|
+
Box13,
|
|
19388
20833
|
{
|
|
19389
20834
|
width: detailWidth,
|
|
19390
20835
|
height,
|
|
@@ -19396,9 +20841,9 @@ function RequestsTab({
|
|
|
19396
20841
|
borderBottom: false,
|
|
19397
20842
|
borderLeft: false,
|
|
19398
20843
|
borderRight: false,
|
|
19399
|
-
children: selectedRequest ? /* @__PURE__ */
|
|
19400
|
-
/* @__PURE__ */
|
|
19401
|
-
|
|
20844
|
+
children: selectedRequest ? /* @__PURE__ */ jsxs12(Fragment9, { children: [
|
|
20845
|
+
/* @__PURE__ */ jsx13(Box13, { flexShrink: 0, paddingTop: 1, children: /* @__PURE__ */ jsxs12(
|
|
20846
|
+
Text12,
|
|
19402
20847
|
{
|
|
19403
20848
|
bold: true,
|
|
19404
20849
|
backgroundColor: focusedPane === "details" ? "yellow" : void 0,
|
|
@@ -19410,17 +20855,17 @@ function RequestsTab({
|
|
|
19410
20855
|
]
|
|
19411
20856
|
}
|
|
19412
20857
|
) }),
|
|
19413
|
-
/* @__PURE__ */
|
|
19414
|
-
/* @__PURE__ */
|
|
20858
|
+
/* @__PURE__ */ jsxs12(ScrollView, { ref: scrollViewRef, height: height - 5, children: [
|
|
20859
|
+
/* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Text12, { bold: true, children: [
|
|
19415
20860
|
"Category:",
|
|
19416
20861
|
" ",
|
|
19417
|
-
/* @__PURE__ */
|
|
20862
|
+
/* @__PURE__ */ jsx13(Text12, { children: selectedRequest.category === "auth" ? "auth" : "transport" })
|
|
19418
20863
|
] }) }),
|
|
19419
|
-
selectedRequest.responseStatus !== void 0 ? /* @__PURE__ */
|
|
20864
|
+
selectedRequest.responseStatus !== void 0 ? /* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Text12, { bold: true, children: [
|
|
19420
20865
|
"Status:",
|
|
19421
20866
|
" ",
|
|
19422
|
-
/* @__PURE__ */
|
|
19423
|
-
|
|
20867
|
+
/* @__PURE__ */ jsxs12(
|
|
20868
|
+
Text12,
|
|
19424
20869
|
{
|
|
19425
20870
|
color: getStatusColor(selectedRequest.responseStatus),
|
|
19426
20871
|
children: [
|
|
@@ -19430,54 +20875,44 @@ function RequestsTab({
|
|
|
19430
20875
|
]
|
|
19431
20876
|
}
|
|
19432
20877
|
)
|
|
19433
|
-
] }) }) : selectedRequest.error ? /* @__PURE__ */
|
|
20878
|
+
] }) }) : selectedRequest.error ? /* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Text12, { bold: true, color: "red", children: [
|
|
19434
20879
|
"Error: ",
|
|
19435
20880
|
selectedRequest.error
|
|
19436
|
-
] }) }) : /* @__PURE__ */
|
|
19437
|
-
selectedRequest.duration !== void 0 && /* @__PURE__ */
|
|
20881
|
+
] }) }) : /* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx13(Text12, { dimColor: true, italic: true, children: "Request in progress..." }) }),
|
|
20882
|
+
selectedRequest.duration !== void 0 && /* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
19438
20883
|
selectedRequest.timestamp.toLocaleTimeString(),
|
|
19439
20884
|
" (",
|
|
19440
20885
|
selectedRequest.duration,
|
|
19441
20886
|
"ms)"
|
|
19442
20887
|
] }) }),
|
|
19443
|
-
/* @__PURE__ */
|
|
20888
|
+
/* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx13(Text12, { bold: true, children: "Request Headers:" }) }),
|
|
19444
20889
|
Object.entries(selectedRequest.requestHeaders).map(
|
|
19445
|
-
([key, value]) => /* @__PURE__ */
|
|
20890
|
+
([key, value]) => /* @__PURE__ */ jsx13(Box13, { marginTop: 0, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
19446
20891
|
key,
|
|
19447
20892
|
": ",
|
|
19448
20893
|
value
|
|
19449
20894
|
] }) }, key)
|
|
19450
20895
|
),
|
|
19451
|
-
selectedRequest.requestBody && /* @__PURE__ */
|
|
19452
|
-
/* @__PURE__ */
|
|
19453
|
-
|
|
19454
|
-
|
|
19455
|
-
|
|
19456
|
-
|
|
19457
|
-
|
|
19458
|
-
{
|
|
19459
|
-
marginTop: idx === 0 ? 1 : 0,
|
|
19460
|
-
paddingLeft: 2,
|
|
19461
|
-
flexShrink: 0,
|
|
19462
|
-
children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: line })
|
|
19463
|
-
},
|
|
19464
|
-
`req-body-${idx}`
|
|
19465
|
-
));
|
|
19466
|
-
} catch {
|
|
19467
|
-
return /* @__PURE__ */ jsx12(Box12, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: selectedRequest.requestBody }) });
|
|
20896
|
+
selectedRequest.requestBody && /* @__PURE__ */ jsxs12(Fragment9, { children: [
|
|
20897
|
+
/* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx13(Text12, { bold: true, children: "Request Body:" }) }),
|
|
20898
|
+
/* @__PURE__ */ jsx13(
|
|
20899
|
+
BodyLines,
|
|
20900
|
+
{
|
|
20901
|
+
body: selectedRequest.requestBody,
|
|
20902
|
+
keyPrefix: "req-body"
|
|
19468
20903
|
}
|
|
19469
|
-
|
|
20904
|
+
)
|
|
19470
20905
|
] }),
|
|
19471
|
-
selectedRequest.responseHeaders && Object.keys(selectedRequest.responseHeaders).length > 0 && /* @__PURE__ */
|
|
19472
|
-
/* @__PURE__ */
|
|
20906
|
+
selectedRequest.responseHeaders && Object.keys(selectedRequest.responseHeaders).length > 0 && /* @__PURE__ */ jsxs12(Fragment9, { children: [
|
|
20907
|
+
/* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx13(Text12, { bold: true, children: "Response Headers:" }) }),
|
|
19473
20908
|
Object.entries(selectedRequest.responseHeaders).map(
|
|
19474
|
-
([key, value]) => /* @__PURE__ */
|
|
19475
|
-
|
|
20909
|
+
([key, value]) => /* @__PURE__ */ jsx13(
|
|
20910
|
+
Box13,
|
|
19476
20911
|
{
|
|
19477
20912
|
marginTop: 0,
|
|
19478
20913
|
paddingLeft: 2,
|
|
19479
20914
|
flexShrink: 0,
|
|
19480
|
-
children: /* @__PURE__ */
|
|
20915
|
+
children: /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
19481
20916
|
key,
|
|
19482
20917
|
": ",
|
|
19483
20918
|
value
|
|
@@ -19487,38 +20922,28 @@ function RequestsTab({
|
|
|
19487
20922
|
)
|
|
19488
20923
|
)
|
|
19489
20924
|
] }),
|
|
19490
|
-
selectedRequest.responseBody && /* @__PURE__ */
|
|
19491
|
-
/* @__PURE__ */
|
|
19492
|
-
|
|
19493
|
-
|
|
19494
|
-
|
|
19495
|
-
|
|
19496
|
-
|
|
19497
|
-
{
|
|
19498
|
-
marginTop: idx === 0 ? 1 : 0,
|
|
19499
|
-
paddingLeft: 2,
|
|
19500
|
-
flexShrink: 0,
|
|
19501
|
-
children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: line })
|
|
19502
|
-
},
|
|
19503
|
-
`resp-body-${idx}`
|
|
19504
|
-
));
|
|
19505
|
-
} catch {
|
|
19506
|
-
return /* @__PURE__ */ jsx12(Box12, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: selectedRequest.responseBody }) });
|
|
20925
|
+
selectedRequest.responseBody && /* @__PURE__ */ jsxs12(Fragment9, { children: [
|
|
20926
|
+
/* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx13(Text12, { bold: true, children: "Response Body:" }) }),
|
|
20927
|
+
/* @__PURE__ */ jsx13(
|
|
20928
|
+
BodyLines,
|
|
20929
|
+
{
|
|
20930
|
+
body: selectedRequest.responseBody,
|
|
20931
|
+
keyPrefix: "resp-body"
|
|
19507
20932
|
}
|
|
19508
|
-
|
|
20933
|
+
)
|
|
19509
20934
|
] })
|
|
19510
20935
|
] }),
|
|
19511
|
-
focusedPane === "details" && /* @__PURE__ */
|
|
19512
|
-
|
|
20936
|
+
focusedPane === "details" && /* @__PURE__ */ jsx13(
|
|
20937
|
+
Box13,
|
|
19513
20938
|
{
|
|
19514
20939
|
flexShrink: 0,
|
|
19515
20940
|
height: 1,
|
|
19516
20941
|
justifyContent: "center",
|
|
19517
20942
|
backgroundColor: "gray",
|
|
19518
|
-
children: /* @__PURE__ */
|
|
20943
|
+
children: /* @__PURE__ */ jsx13(Text12, { bold: true, color: "white", children: "\u2191/\u2193 to scroll, + to zoom" })
|
|
19519
20944
|
}
|
|
19520
20945
|
)
|
|
19521
|
-
] }) : /* @__PURE__ */
|
|
20946
|
+
] }) : /* @__PURE__ */ jsx13(Box13, { paddingY: 1, flexShrink: 0, children: /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: "Select a request to view details" }) })
|
|
19522
20947
|
}
|
|
19523
20948
|
)
|
|
19524
20949
|
] });
|
|
@@ -19526,16 +20951,16 @@ function RequestsTab({
|
|
|
19526
20951
|
|
|
19527
20952
|
// src/components/ToolTestModal.tsx
|
|
19528
20953
|
import React26, { useState as useState14 } from "react";
|
|
19529
|
-
import { Box as
|
|
20954
|
+
import { Box as Box25, Text as Text22, useInput as useInput18 } from "ink";
|
|
19530
20955
|
|
|
19531
20956
|
// node_modules/ink-form/lib/Form.js
|
|
19532
|
-
import { Box as
|
|
20957
|
+
import { Box as Box24, useFocusManager, useInput as useInput17 } from "ink";
|
|
19533
20958
|
import { useEffect as useEffect13, useMemo as useMemo3, useState as useState13 } from "react";
|
|
19534
20959
|
import * as React24 from "react";
|
|
19535
20960
|
|
|
19536
20961
|
// node_modules/ink-form/lib/FormHeader.js
|
|
19537
20962
|
import * as React10 from "react";
|
|
19538
|
-
import { Box as
|
|
20963
|
+
import { Box as Box14, Text as Text13, useInput as useInput10 } from "ink";
|
|
19539
20964
|
var FormHeader = (props) => {
|
|
19540
20965
|
const sections = props.form.sections;
|
|
19541
20966
|
useInput10((input, key) => {
|
|
@@ -19552,42 +20977,42 @@ var FormHeader = (props) => {
|
|
|
19552
20977
|
}
|
|
19553
20978
|
}, { isActive: !props.editingField });
|
|
19554
20979
|
return React10.createElement(
|
|
19555
|
-
|
|
20980
|
+
Box14,
|
|
19556
20981
|
{ borderStyle: "double", width: "100%", flexDirection: "column" },
|
|
19557
20982
|
React10.createElement(
|
|
19558
|
-
|
|
20983
|
+
Box14,
|
|
19559
20984
|
{ width: "100%" },
|
|
19560
20985
|
React10.createElement(
|
|
19561
|
-
|
|
20986
|
+
Box14,
|
|
19562
20987
|
{ flexGrow: 1 },
|
|
19563
|
-
React10.createElement(
|
|
20988
|
+
React10.createElement(Text13, { bold: true }, props.form.title)
|
|
19564
20989
|
),
|
|
19565
20990
|
React10.createElement(
|
|
19566
|
-
|
|
20991
|
+
Box14,
|
|
19567
20992
|
null,
|
|
19568
|
-
React10.createElement(
|
|
20993
|
+
React10.createElement(Text13, null, !props.editingField ? "Use arrow keys to move around" : "Press ESC to cancel, or Enter to complete field")
|
|
19569
20994
|
)
|
|
19570
20995
|
),
|
|
19571
20996
|
React10.createElement(
|
|
19572
|
-
|
|
20997
|
+
Box14,
|
|
19573
20998
|
{ width: "100%" },
|
|
19574
|
-
React10.createElement(
|
|
19575
|
-
|
|
20999
|
+
React10.createElement(Box14, null, !props.editingField ? sections.map((section, id) => React10.createElement(
|
|
21000
|
+
Box14,
|
|
19576
21001
|
{ key: section.title },
|
|
19577
21002
|
React10.createElement(
|
|
19578
|
-
|
|
21003
|
+
Text13,
|
|
19579
21004
|
{ color: "gray" },
|
|
19580
21005
|
"[",
|
|
19581
21006
|
id + 1,
|
|
19582
21007
|
"] "
|
|
19583
21008
|
),
|
|
19584
|
-
React10.createElement(
|
|
19585
|
-
React10.createElement(
|
|
21009
|
+
React10.createElement(Text13, { color: props.currentTab === id ? "blue" : void 0, underline: props.currentTab === id }, section.title),
|
|
21010
|
+
React10.createElement(Text13, null, " ")
|
|
19586
21011
|
)) : React10.createElement(
|
|
19587
|
-
|
|
21012
|
+
Box14,
|
|
19588
21013
|
null,
|
|
19589
21014
|
React10.createElement(
|
|
19590
|
-
|
|
21015
|
+
Text13,
|
|
19591
21016
|
null,
|
|
19592
21017
|
"Editing ",
|
|
19593
21018
|
props.editingField
|
|
@@ -19599,18 +21024,18 @@ var FormHeader = (props) => {
|
|
|
19599
21024
|
|
|
19600
21025
|
// node_modules/ink-form/lib/FormFieldRenderer.js
|
|
19601
21026
|
import React22, { useState as useState12 } from "react";
|
|
19602
|
-
import { Box as
|
|
21027
|
+
import { Box as Box22, useFocus, Text as Text20, useInput as useInput15 } from "ink";
|
|
19603
21028
|
|
|
19604
21029
|
// node_modules/ink-form/lib/managers/FloatFormFieldManager.js
|
|
19605
21030
|
import React13 from "react";
|
|
19606
21031
|
|
|
19607
21032
|
// node_modules/ink-form/lib/NumberFieldRenderer.js
|
|
19608
21033
|
import React12 from "react";
|
|
19609
|
-
import { Box as
|
|
21034
|
+
import { Box as Box15, Text as Text15, useInput as useInput12 } from "ink";
|
|
19610
21035
|
|
|
19611
21036
|
// node_modules/ink-text-input/build/index.js
|
|
19612
21037
|
import React11, { useState as useState10, useEffect as useEffect11 } from "react";
|
|
19613
|
-
import { Text as
|
|
21038
|
+
import { Text as Text14, useInput as useInput11 } from "ink";
|
|
19614
21039
|
|
|
19615
21040
|
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
19616
21041
|
var ANSI_BACKGROUND_OFFSET = 10;
|
|
@@ -20192,7 +21617,7 @@ function TextInput({ value: originalValue, placeholder = "", focus = true, mask,
|
|
|
20192
21617
|
onChange(nextValue);
|
|
20193
21618
|
}
|
|
20194
21619
|
}, { isActive: focus });
|
|
20195
|
-
return React11.createElement(
|
|
21620
|
+
return React11.createElement(Text14, null, placeholder ? value.length > 0 ? renderedValue : renderedPlaceholder : renderedValue);
|
|
20196
21621
|
}
|
|
20197
21622
|
var build_default = TextInput;
|
|
20198
21623
|
|
|
@@ -20236,10 +21661,10 @@ var NumberFieldRenderer = (props) => {
|
|
|
20236
21661
|
}
|
|
20237
21662
|
});
|
|
20238
21663
|
return React12.createElement(
|
|
20239
|
-
|
|
21664
|
+
Box15,
|
|
20240
21665
|
{ borderStyle: "round", width: "100%", flexDirection: "column" },
|
|
20241
21666
|
React12.createElement(
|
|
20242
|
-
|
|
21667
|
+
Box15,
|
|
20243
21668
|
null,
|
|
20244
21669
|
React12.createElement(build_default, { value: "" + (props.value ?? ""), onChange: (value) => {
|
|
20245
21670
|
if (regex.test(value)) {
|
|
@@ -20252,9 +21677,9 @@ var NumberFieldRenderer = (props) => {
|
|
|
20252
21677
|
}, placeholder: props.field.placeholder, onSubmit: () => props.onSetEditingField(void 0) })
|
|
20253
21678
|
),
|
|
20254
21679
|
React12.createElement(
|
|
20255
|
-
|
|
21680
|
+
Box15,
|
|
20256
21681
|
null,
|
|
20257
|
-
React12.createElement(
|
|
21682
|
+
React12.createElement(Text15, { dimColor: true }, "Press UP/DOWN to increase or decrease the value.")
|
|
20258
21683
|
)
|
|
20259
21684
|
);
|
|
20260
21685
|
};
|
|
@@ -20276,11 +21701,11 @@ var IntegerFormFieldManager = class {
|
|
|
20276
21701
|
|
|
20277
21702
|
// node_modules/ink-form/lib/managers/SelectFormFieldManager.js
|
|
20278
21703
|
import React18 from "react";
|
|
20279
|
-
import { Box as
|
|
21704
|
+
import { Box as Box18 } from "ink";
|
|
20280
21705
|
|
|
20281
21706
|
// node_modules/ink-select-input/build/Indicator.js
|
|
20282
21707
|
import React15 from "react";
|
|
20283
|
-
import { Box as
|
|
21708
|
+
import { Box as Box16, Text as Text16 } from "ink";
|
|
20284
21709
|
|
|
20285
21710
|
// node_modules/is-unicode-supported/index.js
|
|
20286
21711
|
import process3 from "process";
|
|
@@ -20571,15 +21996,15 @@ var replacements = Object.entries(specialMainSymbols);
|
|
|
20571
21996
|
|
|
20572
21997
|
// node_modules/ink-select-input/build/Indicator.js
|
|
20573
21998
|
function Indicator({ isSelected = false }) {
|
|
20574
|
-
return React15.createElement(
|
|
21999
|
+
return React15.createElement(Box16, { marginRight: 1 }, isSelected ? React15.createElement(Text16, { color: "blue" }, figures_default.pointer) : React15.createElement(Text16, null, " "));
|
|
20575
22000
|
}
|
|
20576
22001
|
var Indicator_default = Indicator;
|
|
20577
22002
|
|
|
20578
22003
|
// node_modules/ink-select-input/build/Item.js
|
|
20579
22004
|
import * as React16 from "react";
|
|
20580
|
-
import { Text as
|
|
22005
|
+
import { Text as Text17 } from "ink";
|
|
20581
22006
|
function Item({ isSelected = false, label }) {
|
|
20582
|
-
return React16.createElement(
|
|
22007
|
+
return React16.createElement(Text17, { color: isSelected ? "blue" : void 0 }, label);
|
|
20583
22008
|
}
|
|
20584
22009
|
var Item_default = Item;
|
|
20585
22010
|
|
|
@@ -20610,7 +22035,7 @@ function toRotated(array, steps) {
|
|
|
20610
22035
|
}
|
|
20611
22036
|
|
|
20612
22037
|
// node_modules/ink-select-input/build/SelectInput.js
|
|
20613
|
-
import { Box as
|
|
22038
|
+
import { Box as Box17, useInput as useInput13 } from "ink";
|
|
20614
22039
|
function SelectInput({ items = [], isFocused = true, initialIndex = 0, indicatorComponent = Indicator_default, itemComponent = Item_default, limit: customLimit, onSelect, onHighlight }) {
|
|
20615
22040
|
const hasLimit = typeof customLimit === "number" && items.length > customLimit;
|
|
20616
22041
|
const limit = hasLimit ? Math.min(customLimit, items.length) : items.length;
|
|
@@ -20677,12 +22102,12 @@ function SelectInput({ items = [], isFocused = true, initialIndex = 0, indicator
|
|
|
20677
22102
|
onHighlight
|
|
20678
22103
|
]), { isActive: isFocused });
|
|
20679
22104
|
const slicedItems = hasLimit ? toRotated(items, rotateIndex).slice(0, limit) : items;
|
|
20680
|
-
return React17.createElement(
|
|
22105
|
+
return React17.createElement(Box17, { flexDirection: "column" }, slicedItems.map((item, index) => {
|
|
20681
22106
|
const isSelected = index === selectedIndex;
|
|
20682
22107
|
return (
|
|
20683
22108
|
// @ts-expect-error - `key` can't be optional but `item.value` is generic T
|
|
20684
22109
|
React17.createElement(
|
|
20685
|
-
|
|
22110
|
+
Box17,
|
|
20686
22111
|
{ key: item.key ?? item.value },
|
|
20687
22112
|
React17.createElement(indicatorComponent, { isSelected }),
|
|
20688
22113
|
React17.createElement(itemComponent, { ...item, isSelected })
|
|
@@ -20696,7 +22121,7 @@ var SelectInput_default = SelectInput;
|
|
|
20696
22121
|
var SelectFormFieldManager = class {
|
|
20697
22122
|
type = "select";
|
|
20698
22123
|
renderField = (props) => React18.createElement(
|
|
20699
|
-
|
|
22124
|
+
Box18,
|
|
20700
22125
|
{ borderStyle: "round", width: "100%" },
|
|
20701
22126
|
React18.createElement(SelectInput_default, { items: props.field.options.map((option) => ({ value: option.value, label: option.label ?? option.value })), onHighlight: (option) => props.onChange(option.value), initialIndex: props.field.options.findIndex((option) => option.value === props.value) ?? 0 })
|
|
20702
22127
|
);
|
|
@@ -20705,11 +22130,11 @@ var SelectFormFieldManager = class {
|
|
|
20705
22130
|
|
|
20706
22131
|
// node_modules/ink-form/lib/managers/StringFormFieldManager.js
|
|
20707
22132
|
import React19 from "react";
|
|
20708
|
-
import { Box as
|
|
22133
|
+
import { Box as Box19, Transform } from "ink";
|
|
20709
22134
|
var StringFormFieldManager = class {
|
|
20710
22135
|
type = "string";
|
|
20711
22136
|
renderField = (props) => React19.createElement(
|
|
20712
|
-
|
|
22137
|
+
Box19,
|
|
20713
22138
|
{ borderStyle: "round", width: "100%" },
|
|
20714
22139
|
React19.createElement(build_default, { value: props.value ?? "", onChange: (value) => {
|
|
20715
22140
|
props.onChange(value);
|
|
@@ -20725,7 +22150,7 @@ var StringFormFieldManager = class {
|
|
|
20725
22150
|
|
|
20726
22151
|
// node_modules/ink-form/lib/managers/BooleanFormFieldManager.js
|
|
20727
22152
|
import React20 from "react";
|
|
20728
|
-
import { Box as
|
|
22153
|
+
import { Box as Box20, Text as Text18, useInput as useInput14 } from "ink";
|
|
20729
22154
|
var BooleanFormFieldManager = class {
|
|
20730
22155
|
type = "boolean";
|
|
20731
22156
|
renderField = (props) => {
|
|
@@ -20735,21 +22160,21 @@ var BooleanFormFieldManager = class {
|
|
|
20735
22160
|
}
|
|
20736
22161
|
});
|
|
20737
22162
|
return React20.createElement(
|
|
20738
|
-
|
|
22163
|
+
Box20,
|
|
20739
22164
|
{ width: "100%", borderStyle: "round", borderColor: props.value ? "green" : "gray", marginBottom: 2 },
|
|
20740
22165
|
React20.createElement(
|
|
20741
|
-
|
|
22166
|
+
Box20,
|
|
20742
22167
|
{ marginRight: 2 },
|
|
20743
|
-
React20.createElement(
|
|
22168
|
+
React20.createElement(Text18, { color: props.value ? "green" : "gray" }, props.value === void 0 ? "[Not set]" : props.value ? "[True]" : "[False]")
|
|
20744
22169
|
),
|
|
20745
22170
|
React20.createElement(
|
|
20746
|
-
|
|
22171
|
+
Box20,
|
|
20747
22172
|
{ flexGrow: 1 },
|
|
20748
|
-
React20.createElement(
|
|
22173
|
+
React20.createElement(Text18, null, "Press Space to toggle value")
|
|
20749
22174
|
)
|
|
20750
22175
|
);
|
|
20751
22176
|
};
|
|
20752
|
-
renderValue = (props) => React20.createElement(
|
|
22177
|
+
renderValue = (props) => React20.createElement(Text18, null, props.value === void 0 ? "[Not set]" : props.value ? "[True]" : "[False]");
|
|
20753
22178
|
};
|
|
20754
22179
|
|
|
20755
22180
|
// node_modules/ink-form/lib/managers/managers.js
|
|
@@ -20766,20 +22191,20 @@ var getManager = (formFieldType, customManagers = []) => {
|
|
|
20766
22191
|
|
|
20767
22192
|
// node_modules/ink-form/lib/DescriptionRenderer.js
|
|
20768
22193
|
import React21 from "react";
|
|
20769
|
-
import { Box as
|
|
22194
|
+
import { Box as Box21, Text as Text19 } from "ink";
|
|
20770
22195
|
var DescriptionRenderer = (props) => {
|
|
20771
22196
|
if (!props.description) {
|
|
20772
22197
|
return null;
|
|
20773
22198
|
} else if (props.description.type) {
|
|
20774
22199
|
return props.description;
|
|
20775
22200
|
} else if (Array.isArray(props.description)) {
|
|
20776
|
-
return React21.createElement(
|
|
20777
|
-
|
|
22201
|
+
return React21.createElement(Box21, { flexDirection: "column" }, props.description.map((line) => React21.createElement(
|
|
22202
|
+
Box21,
|
|
20778
22203
|
{ key: line, width: "100%", marginBottom: 1 },
|
|
20779
|
-
React21.createElement(
|
|
22204
|
+
React21.createElement(Text19, null, line)
|
|
20780
22205
|
)));
|
|
20781
22206
|
} else {
|
|
20782
|
-
return React21.createElement(
|
|
22207
|
+
return React21.createElement(Text19, null, props.description);
|
|
20783
22208
|
}
|
|
20784
22209
|
};
|
|
20785
22210
|
|
|
@@ -20822,24 +22247,24 @@ var FormFieldRenderer = (props) => {
|
|
|
20822
22247
|
if (!isEditing) {
|
|
20823
22248
|
const RenderValue = manager?.renderValue ?? (() => React22.createElement(React22.Fragment, null, props.value));
|
|
20824
22249
|
return React22.createElement(
|
|
20825
|
-
|
|
22250
|
+
Box22,
|
|
20826
22251
|
{ marginX: 2, paddingX: 1, borderStyle: "round", borderColor: isFocused ? "blue" : void 0 },
|
|
20827
22252
|
React22.createElement(
|
|
20828
|
-
|
|
22253
|
+
Box22,
|
|
20829
22254
|
{ flexGrow: 1 },
|
|
20830
|
-
React22.createElement(
|
|
20831
|
-
props.field.required && React22.createElement(
|
|
20832
|
-
React22.createElement(
|
|
22255
|
+
React22.createElement(Text20, { underline: isFocused, color: isFocused ? "blue" : void 0 }, props.field.label ?? props.field.name),
|
|
22256
|
+
props.field.required && React22.createElement(Text20, { color: "red" }, "*"),
|
|
22257
|
+
React22.createElement(Text20, null, ": "),
|
|
20833
22258
|
React22.createElement(
|
|
20834
|
-
|
|
22259
|
+
Text20,
|
|
20835
22260
|
{ dimColor: true },
|
|
20836
22261
|
React22.createElement(RenderValue, { value: props.value, field: props.field })
|
|
20837
22262
|
)
|
|
20838
22263
|
),
|
|
20839
22264
|
isFocused && React22.createElement(
|
|
20840
|
-
|
|
22265
|
+
Box22,
|
|
20841
22266
|
null,
|
|
20842
|
-
React22.createElement(
|
|
22267
|
+
React22.createElement(Text20, null, "Press enter to edit")
|
|
20843
22268
|
)
|
|
20844
22269
|
);
|
|
20845
22270
|
} else {
|
|
@@ -20856,7 +22281,7 @@ var FormFieldRenderer = (props) => {
|
|
|
20856
22281
|
};
|
|
20857
22282
|
if (!manager) {
|
|
20858
22283
|
component = React22.createElement(
|
|
20859
|
-
|
|
22284
|
+
Text20,
|
|
20860
22285
|
{ color: "red" },
|
|
20861
22286
|
"No formfield manager for form field of type ",
|
|
20862
22287
|
props.field.type,
|
|
@@ -20867,39 +22292,39 @@ var FormFieldRenderer = (props) => {
|
|
|
20867
22292
|
component = React22.createElement(Field, { ...rendererProps });
|
|
20868
22293
|
}
|
|
20869
22294
|
return React22.createElement(
|
|
20870
|
-
|
|
22295
|
+
Box22,
|
|
20871
22296
|
{ paddingX: 3, paddingY: 1, flexDirection: "column" },
|
|
20872
22297
|
React22.createElement(
|
|
20873
|
-
|
|
22298
|
+
Box22,
|
|
20874
22299
|
null,
|
|
20875
|
-
React22.createElement(
|
|
20876
|
-
props.field.required && React22.createElement(
|
|
20877
|
-
React22.createElement(
|
|
22300
|
+
React22.createElement(Text20, null, props.field.label ?? props.field.name),
|
|
22301
|
+
props.field.required && React22.createElement(Text20, { color: "red" }, "*"),
|
|
22302
|
+
React22.createElement(Text20, null, ": ")
|
|
20878
22303
|
),
|
|
20879
|
-
React22.createElement(
|
|
22304
|
+
React22.createElement(Box22, null, component),
|
|
20880
22305
|
props.field.description && React22.createElement(
|
|
20881
|
-
|
|
22306
|
+
Box22,
|
|
20882
22307
|
null,
|
|
20883
22308
|
React22.createElement(
|
|
20884
|
-
|
|
22309
|
+
Text20,
|
|
20885
22310
|
{ dimColor: true },
|
|
20886
22311
|
React22.createElement(DescriptionRenderer, { description: props.field.description })
|
|
20887
22312
|
)
|
|
20888
22313
|
),
|
|
20889
22314
|
error && React22.createElement(
|
|
20890
|
-
|
|
22315
|
+
Box22,
|
|
20891
22316
|
null,
|
|
20892
22317
|
React22.createElement(
|
|
20893
|
-
|
|
22318
|
+
Text20,
|
|
20894
22319
|
{ color: "red" },
|
|
20895
22320
|
"Error: ",
|
|
20896
22321
|
error
|
|
20897
22322
|
)
|
|
20898
22323
|
),
|
|
20899
22324
|
React22.createElement(
|
|
20900
|
-
|
|
22325
|
+
Box22,
|
|
20901
22326
|
{ marginTop: 2 },
|
|
20902
|
-
React22.createElement(
|
|
22327
|
+
React22.createElement(Text20, { dimColor: true }, error ? React22.createElement(React22.Fragment, null, "Press ESC to cancel.") : React22.createElement(
|
|
20903
22328
|
React22.Fragment,
|
|
20904
22329
|
null,
|
|
20905
22330
|
"Press ",
|
|
@@ -20918,7 +22343,7 @@ var canSubmit = (form, value) => {
|
|
|
20918
22343
|
|
|
20919
22344
|
// node_modules/ink-form/lib/SubmitButton.js
|
|
20920
22345
|
import React23 from "react";
|
|
20921
|
-
import { Text as
|
|
22346
|
+
import { Text as Text21, Box as Box23, useFocus as useFocus2, useInput as useInput16 } from "ink";
|
|
20922
22347
|
var SubmitButton = (props) => {
|
|
20923
22348
|
const { isFocused } = useFocus2({ isActive: props.canSubmit });
|
|
20924
22349
|
useInput16((input, key) => {
|
|
@@ -20927,17 +22352,17 @@ var SubmitButton = (props) => {
|
|
|
20927
22352
|
}
|
|
20928
22353
|
});
|
|
20929
22354
|
return React23.createElement(
|
|
20930
|
-
|
|
22355
|
+
Box23,
|
|
20931
22356
|
{ marginRight: 2 },
|
|
20932
22357
|
React23.createElement(
|
|
20933
|
-
|
|
22358
|
+
Box23,
|
|
20934
22359
|
{ marginRight: 2, paddingY: 1 },
|
|
20935
|
-
React23.createElement(
|
|
22360
|
+
React23.createElement(Text21, null, !props.canSubmit ? "There are still required inputs you have not completed yet." : isFocused ? "Press Enter to submit form" : "Use the arrow keys to navigate to the submit button.")
|
|
20936
22361
|
),
|
|
20937
22362
|
React23.createElement(
|
|
20938
|
-
|
|
22363
|
+
Box23,
|
|
20939
22364
|
{ borderStyle: "round", borderColor: !props.canSubmit ? "gray" : isFocused ? "blue" : "white", paddingX: 2 },
|
|
20940
|
-
React23.createElement(
|
|
22365
|
+
React23.createElement(Text21, { color: !props.canSubmit ? "gray" : isFocused ? "blue" : "white", bold: true, underline: isFocused }, props.canSubmit ? "Submit form" : "Cannot submit form yet")
|
|
20941
22366
|
)
|
|
20942
22367
|
);
|
|
20943
22368
|
};
|
|
@@ -20978,17 +22403,17 @@ var Form = (props) => {
|
|
|
20978
22403
|
}
|
|
20979
22404
|
}, { isActive: !editingField });
|
|
20980
22405
|
return React24.createElement(
|
|
20981
|
-
|
|
22406
|
+
Box24,
|
|
20982
22407
|
{ width: "100%", height: "100%", flexDirection: "column" },
|
|
20983
22408
|
React24.createElement(FormHeader, { ...props, currentTab, onChangeTab: setCurrentTab, editingField }),
|
|
20984
22409
|
!editingField && props.form.sections[currentTab].description && React24.createElement(
|
|
20985
|
-
|
|
22410
|
+
Box24,
|
|
20986
22411
|
{ marginX: 4 },
|
|
20987
22412
|
React24.createElement(DescriptionRenderer, { description: props.form.sections[currentTab].description })
|
|
20988
22413
|
),
|
|
20989
|
-
React24.createElement(
|
|
22414
|
+
React24.createElement(Box24, { flexDirection: "column" }, currentTab > props.form.sections.length - 1 ? null : props.form.sections[currentTab].fields.map((field) => React24.createElement(FormFieldRenderer, { field, key: field.name, form: props.form, value: value[field.name], onChange: (v) => setValueAndPropagate({ ...value, [field.name]: v }), onSetEditingField: setEditingField, editingField, customManagers: props.customManagers }))),
|
|
20990
22415
|
!editingField && React24.createElement(
|
|
20991
|
-
|
|
22416
|
+
Box24,
|
|
20992
22417
|
{ flexDirection: "row-reverse" },
|
|
20993
22418
|
React24.createElement(SubmitButton, { canSubmit: canSubmitForm, onSubmit: () => props.onSubmit?.(value) })
|
|
20994
22419
|
)
|
|
@@ -21260,7 +22685,7 @@ function missingRequiredFields(schema, decoded, rawValues = {}) {
|
|
|
21260
22685
|
}
|
|
21261
22686
|
|
|
21262
22687
|
// src/components/ToolTestModal.tsx
|
|
21263
|
-
import { Fragment as
|
|
22688
|
+
import { Fragment as Fragment10, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
21264
22689
|
function ToolTestModal({
|
|
21265
22690
|
tool,
|
|
21266
22691
|
inspectorClient,
|
|
@@ -21289,7 +22714,8 @@ function ToolTestModal({
|
|
|
21289
22714
|
process.stdout.off("resize", updateDimensions);
|
|
21290
22715
|
};
|
|
21291
22716
|
}, [width, height]);
|
|
21292
|
-
const
|
|
22717
|
+
const inputSchema = inlineLocalRefs(tool?.inputSchema);
|
|
22718
|
+
const formStructure = inputSchema ? schemaToForm(inputSchema, tool?.name || "Unknown Tool") : {
|
|
21293
22719
|
title: `Test Tool: ${tool?.name || "Unknown"}`,
|
|
21294
22720
|
sections: [{ title: "Parameters", fields: [] }]
|
|
21295
22721
|
};
|
|
@@ -21328,8 +22754,8 @@ function ToolTestModal({
|
|
|
21328
22754
|
);
|
|
21329
22755
|
const handleFormSubmit = async (rawValues) => {
|
|
21330
22756
|
if (!inspectorClient || !tool) return;
|
|
21331
|
-
const values = decodeFormValues(
|
|
21332
|
-
const missing = missingRequiredFields(
|
|
22757
|
+
const values = decodeFormValues(inputSchema, rawValues);
|
|
22758
|
+
const missing = missingRequiredFields(inputSchema, values, rawValues);
|
|
21333
22759
|
if (missing.length > 0) {
|
|
21334
22760
|
setResult({
|
|
21335
22761
|
input: values,
|
|
@@ -21385,8 +22811,8 @@ function ToolTestModal({
|
|
|
21385
22811
|
};
|
|
21386
22812
|
const modalWidth = terminalDimensions.width - 2;
|
|
21387
22813
|
const modalHeight = terminalDimensions.height - 2;
|
|
21388
|
-
return /* @__PURE__ */
|
|
21389
|
-
|
|
22814
|
+
return /* @__PURE__ */ jsx14(
|
|
22815
|
+
Box25,
|
|
21390
22816
|
{
|
|
21391
22817
|
position: "absolute",
|
|
21392
22818
|
width: terminalDimensions.width,
|
|
@@ -21394,8 +22820,8 @@ function ToolTestModal({
|
|
|
21394
22820
|
flexDirection: "column",
|
|
21395
22821
|
justifyContent: "center",
|
|
21396
22822
|
alignItems: "center",
|
|
21397
|
-
children: /* @__PURE__ */
|
|
21398
|
-
|
|
22823
|
+
children: /* @__PURE__ */ jsxs13(
|
|
22824
|
+
Box25,
|
|
21399
22825
|
{
|
|
21400
22826
|
width: modalWidth,
|
|
21401
22827
|
height: modalHeight,
|
|
@@ -21406,40 +22832,40 @@ function ToolTestModal({
|
|
|
21406
22832
|
paddingY: 1,
|
|
21407
22833
|
backgroundColor: "black",
|
|
21408
22834
|
children: [
|
|
21409
|
-
/* @__PURE__ */
|
|
21410
|
-
/* @__PURE__ */
|
|
21411
|
-
/* @__PURE__ */
|
|
21412
|
-
/* @__PURE__ */
|
|
22835
|
+
/* @__PURE__ */ jsxs13(Box25, { flexShrink: 0, marginBottom: 1, children: [
|
|
22836
|
+
/* @__PURE__ */ jsx14(Text22, { bold: true, color: "cyan", children: formStructure.title }),
|
|
22837
|
+
/* @__PURE__ */ jsx14(Text22, { children: " " }),
|
|
22838
|
+
/* @__PURE__ */ jsx14(Text22, { dimColor: true, children: "(Press ESC to close)" })
|
|
21413
22839
|
] }),
|
|
21414
|
-
/* @__PURE__ */
|
|
21415
|
-
state === "form" && /* @__PURE__ */
|
|
22840
|
+
/* @__PURE__ */ jsxs13(Box25, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
|
|
22841
|
+
state === "form" && /* @__PURE__ */ jsx14(Box25, { flexGrow: 1, width: "100%", children: /* @__PURE__ */ jsx14(
|
|
21416
22842
|
Form,
|
|
21417
22843
|
{
|
|
21418
22844
|
form: formStructure,
|
|
21419
22845
|
onSubmit: (value) => void handleFormSubmit(value)
|
|
21420
22846
|
}
|
|
21421
22847
|
) }),
|
|
21422
|
-
state === "loading" && /* @__PURE__ */
|
|
21423
|
-
state === "results" && result && /* @__PURE__ */
|
|
21424
|
-
/* @__PURE__ */
|
|
22848
|
+
state === "loading" && /* @__PURE__ */ jsx14(Box25, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx14(Text22, { color: "yellow", children: "Calling tool..." }) }),
|
|
22849
|
+
state === "results" && result && /* @__PURE__ */ jsx14(Box25, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: /* @__PURE__ */ jsxs13(ScrollView, { ref: scrollViewRef, children: [
|
|
22850
|
+
/* @__PURE__ */ jsx14(Box25, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs13(Text22, { bold: true, color: "green", children: [
|
|
21425
22851
|
"Duration: ",
|
|
21426
22852
|
result.duration,
|
|
21427
22853
|
"ms"
|
|
21428
22854
|
] }) }),
|
|
21429
|
-
/* @__PURE__ */
|
|
21430
|
-
/* @__PURE__ */
|
|
21431
|
-
/* @__PURE__ */
|
|
22855
|
+
/* @__PURE__ */ jsxs13(Box25, { marginBottom: 1, flexShrink: 0, flexDirection: "column", children: [
|
|
22856
|
+
/* @__PURE__ */ jsx14(Text22, { bold: true, color: "cyan", children: "Input:" }),
|
|
22857
|
+
/* @__PURE__ */ jsx14(Box25, { paddingLeft: 2, children: /* @__PURE__ */ jsx14(Text22, { dimColor: true, children: JSON.stringify(result.input, null, 2) }) })
|
|
21432
22858
|
] }),
|
|
21433
|
-
result.error ? /* @__PURE__ */
|
|
21434
|
-
/* @__PURE__ */
|
|
21435
|
-
/* @__PURE__ */
|
|
21436
|
-
result.errorDetails != null ? /* @__PURE__ */
|
|
21437
|
-
/* @__PURE__ */
|
|
21438
|
-
/* @__PURE__ */
|
|
22859
|
+
result.error ? /* @__PURE__ */ jsxs13(Box25, { flexShrink: 0, flexDirection: "column", children: [
|
|
22860
|
+
/* @__PURE__ */ jsx14(Text22, { bold: true, color: "red", children: "Error:" }),
|
|
22861
|
+
/* @__PURE__ */ jsx14(Box25, { paddingLeft: 2, children: /* @__PURE__ */ jsx14(Text22, { color: "red", children: String(result.error) }) }),
|
|
22862
|
+
result.errorDetails != null ? /* @__PURE__ */ jsxs13(Fragment10, { children: [
|
|
22863
|
+
/* @__PURE__ */ jsx14(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text22, { bold: true, color: "red", dimColor: true, children: "Error Details:" }) }),
|
|
22864
|
+
/* @__PURE__ */ jsx14(Box25, { paddingLeft: 2, children: /* @__PURE__ */ jsx14(Text22, { dimColor: true, children: JSON.stringify(result.errorDetails, null, 2) }) })
|
|
21439
22865
|
] }) : null
|
|
21440
|
-
] }) : /* @__PURE__ */
|
|
21441
|
-
/* @__PURE__ */
|
|
21442
|
-
/* @__PURE__ */
|
|
22866
|
+
] }) : /* @__PURE__ */ jsxs13(Box25, { flexShrink: 0, flexDirection: "column", children: [
|
|
22867
|
+
/* @__PURE__ */ jsx14(Text22, { bold: true, color: "green", children: "Output:" }),
|
|
22868
|
+
/* @__PURE__ */ jsx14(Box25, { paddingLeft: 2, children: /* @__PURE__ */ jsx14(Text22, { dimColor: true, children: JSON.stringify(result.output, null, 2) }) })
|
|
21443
22869
|
] })
|
|
21444
22870
|
] }) })
|
|
21445
22871
|
] })
|
|
@@ -21452,7 +22878,7 @@ function ToolTestModal({
|
|
|
21452
22878
|
|
|
21453
22879
|
// src/components/ResourceTestModal.tsx
|
|
21454
22880
|
import React27, { useState as useState15 } from "react";
|
|
21455
|
-
import { Box as
|
|
22881
|
+
import { Box as Box26, Text as Text23, useInput as useInput19 } from "ink";
|
|
21456
22882
|
|
|
21457
22883
|
// src/utils/uriTemplateToForm.ts
|
|
21458
22884
|
import { UriTemplate as UriTemplate2 } from "@modelcontextprotocol/client";
|
|
@@ -21485,7 +22911,7 @@ function uriTemplateToForm(uriTemplate, templateName) {
|
|
|
21485
22911
|
}
|
|
21486
22912
|
|
|
21487
22913
|
// src/components/ResourceTestModal.tsx
|
|
21488
|
-
import { Fragment as
|
|
22914
|
+
import { Fragment as Fragment11, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
21489
22915
|
function getErrorMessage(error) {
|
|
21490
22916
|
if (error instanceof Error) {
|
|
21491
22917
|
return error.message;
|
|
@@ -21634,8 +23060,8 @@ function ResourceTestModal({
|
|
|
21634
23060
|
};
|
|
21635
23061
|
const modalWidth = terminalDimensions.width - 2;
|
|
21636
23062
|
const modalHeight = terminalDimensions.height - 2;
|
|
21637
|
-
return /* @__PURE__ */
|
|
21638
|
-
|
|
23063
|
+
return /* @__PURE__ */ jsx15(
|
|
23064
|
+
Box26,
|
|
21639
23065
|
{
|
|
21640
23066
|
position: "absolute",
|
|
21641
23067
|
width: terminalDimensions.width,
|
|
@@ -21643,8 +23069,8 @@ function ResourceTestModal({
|
|
|
21643
23069
|
flexDirection: "column",
|
|
21644
23070
|
justifyContent: "center",
|
|
21645
23071
|
alignItems: "center",
|
|
21646
|
-
children: /* @__PURE__ */
|
|
21647
|
-
|
|
23072
|
+
children: /* @__PURE__ */ jsxs14(
|
|
23073
|
+
Box26,
|
|
21648
23074
|
{
|
|
21649
23075
|
width: modalWidth,
|
|
21650
23076
|
height: modalHeight,
|
|
@@ -21655,15 +23081,15 @@ function ResourceTestModal({
|
|
|
21655
23081
|
paddingY: 1,
|
|
21656
23082
|
backgroundColor: "black",
|
|
21657
23083
|
children: [
|
|
21658
|
-
/* @__PURE__ */
|
|
21659
|
-
/* @__PURE__ */
|
|
21660
|
-
/* @__PURE__ */
|
|
21661
|
-
/* @__PURE__ */
|
|
23084
|
+
/* @__PURE__ */ jsxs14(Box26, { flexShrink: 0, marginBottom: 1, children: [
|
|
23085
|
+
/* @__PURE__ */ jsx15(Text23, { bold: true, color: "cyan", children: formStructure.title }),
|
|
23086
|
+
/* @__PURE__ */ jsx15(Text23, { children: " " }),
|
|
23087
|
+
/* @__PURE__ */ jsx15(Text23, { dimColor: true, children: "(Press ESC to close)" })
|
|
21662
23088
|
] }),
|
|
21663
|
-
/* @__PURE__ */
|
|
21664
|
-
state === "form" && /* @__PURE__ */
|
|
21665
|
-
template.description && /* @__PURE__ */
|
|
21666
|
-
/* @__PURE__ */
|
|
23089
|
+
/* @__PURE__ */ jsxs14(Box26, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
|
|
23090
|
+
state === "form" && /* @__PURE__ */ jsxs14(Box26, { flexGrow: 1, flexDirection: "column", children: [
|
|
23091
|
+
template.description && /* @__PURE__ */ jsx15(Box26, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: template.description }) }),
|
|
23092
|
+
/* @__PURE__ */ jsx15(
|
|
21667
23093
|
Form,
|
|
21668
23094
|
{
|
|
21669
23095
|
form: formStructure,
|
|
@@ -21671,34 +23097,34 @@ function ResourceTestModal({
|
|
|
21671
23097
|
}
|
|
21672
23098
|
)
|
|
21673
23099
|
] }),
|
|
21674
|
-
state === "loading" && /* @__PURE__ */
|
|
21675
|
-
state === "results" && result && /* @__PURE__ */
|
|
21676
|
-
/* @__PURE__ */
|
|
23100
|
+
state === "loading" && /* @__PURE__ */ jsx15(Box26, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx15(Text23, { color: "yellow", children: "Reading resource..." }) }),
|
|
23101
|
+
state === "results" && result && /* @__PURE__ */ jsx15(Box26, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: /* @__PURE__ */ jsxs14(ScrollView, { ref: scrollViewRef, children: [
|
|
23102
|
+
/* @__PURE__ */ jsx15(Box26, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs14(Text23, { bold: true, color: "green", children: [
|
|
21677
23103
|
"Duration: ",
|
|
21678
23104
|
result.duration,
|
|
21679
23105
|
"ms"
|
|
21680
23106
|
] }) }),
|
|
21681
|
-
/* @__PURE__ */
|
|
21682
|
-
/* @__PURE__ */
|
|
23107
|
+
/* @__PURE__ */ jsxs14(Box26, { marginBottom: 1, flexShrink: 0, children: [
|
|
23108
|
+
/* @__PURE__ */ jsxs14(Text23, { bold: true, color: "cyan", children: [
|
|
21683
23109
|
"URI:",
|
|
21684
23110
|
" "
|
|
21685
23111
|
] }),
|
|
21686
|
-
/* @__PURE__ */
|
|
23112
|
+
/* @__PURE__ */ jsx15(Text23, { dimColor: true, children: result.uri })
|
|
21687
23113
|
] }),
|
|
21688
|
-
/* @__PURE__ */
|
|
21689
|
-
/* @__PURE__ */
|
|
21690
|
-
/* @__PURE__ */
|
|
23114
|
+
/* @__PURE__ */ jsxs14(Box26, { marginBottom: 1, flexShrink: 0, flexDirection: "column", children: [
|
|
23115
|
+
/* @__PURE__ */ jsx15(Text23, { bold: true, color: "cyan", children: "Template Values:" }),
|
|
23116
|
+
/* @__PURE__ */ jsx15(Box26, { paddingLeft: 2, children: /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: JSON.stringify(result.input, null, 2) }) })
|
|
21691
23117
|
] }),
|
|
21692
|
-
result.error ? /* @__PURE__ */
|
|
21693
|
-
/* @__PURE__ */
|
|
21694
|
-
/* @__PURE__ */
|
|
21695
|
-
result.errorDetails != null ? /* @__PURE__ */
|
|
21696
|
-
/* @__PURE__ */
|
|
21697
|
-
/* @__PURE__ */
|
|
23118
|
+
result.error ? /* @__PURE__ */ jsxs14(Box26, { flexShrink: 0, flexDirection: "column", children: [
|
|
23119
|
+
/* @__PURE__ */ jsx15(Box26, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { bold: true, color: "red", children: "Error:" }) }),
|
|
23120
|
+
/* @__PURE__ */ jsx15(Box26, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { color: "red", children: String(result.error) }) }),
|
|
23121
|
+
result.errorDetails != null ? /* @__PURE__ */ jsxs14(Fragment11, { children: [
|
|
23122
|
+
/* @__PURE__ */ jsx15(Box26, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { bold: true, color: "red", dimColor: true, children: "Error Details:" }) }),
|
|
23123
|
+
/* @__PURE__ */ jsx15(Box26, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: JSON.stringify(result.errorDetails, null, 2) }) })
|
|
21698
23124
|
] }) : null
|
|
21699
|
-
] }) : /* @__PURE__ */
|
|
21700
|
-
/* @__PURE__ */
|
|
21701
|
-
/* @__PURE__ */
|
|
23125
|
+
] }) : /* @__PURE__ */ jsxs14(Box26, { flexShrink: 0, flexDirection: "column", children: [
|
|
23126
|
+
/* @__PURE__ */ jsx15(Text23, { bold: true, color: "green", children: "Resource Content:" }),
|
|
23127
|
+
/* @__PURE__ */ jsx15(Box26, { paddingLeft: 2, children: /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: JSON.stringify(result.output, null, 2) }) })
|
|
21702
23128
|
] })
|
|
21703
23129
|
] }) })
|
|
21704
23130
|
] })
|
|
@@ -21711,7 +23137,7 @@ function ResourceTestModal({
|
|
|
21711
23137
|
|
|
21712
23138
|
// src/components/PromptTestModal.tsx
|
|
21713
23139
|
import React28, { useState as useState16 } from "react";
|
|
21714
|
-
import { Box as
|
|
23140
|
+
import { Box as Box27, Text as Text24, useInput as useInput20 } from "ink";
|
|
21715
23141
|
|
|
21716
23142
|
// src/utils/promptArgsToForm.ts
|
|
21717
23143
|
function promptArgsToForm(promptArguments, promptName) {
|
|
@@ -21747,7 +23173,7 @@ function promptArgsToForm(promptArguments, promptName) {
|
|
|
21747
23173
|
}
|
|
21748
23174
|
|
|
21749
23175
|
// src/components/PromptTestModal.tsx
|
|
21750
|
-
import { Fragment as
|
|
23176
|
+
import { Fragment as Fragment12, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
21751
23177
|
function getErrorMessage2(error) {
|
|
21752
23178
|
if (error instanceof Error) {
|
|
21753
23179
|
return error.message;
|
|
@@ -21869,8 +23295,8 @@ function PromptTestModal({
|
|
|
21869
23295
|
};
|
|
21870
23296
|
const modalWidth = terminalDimensions.width - 2;
|
|
21871
23297
|
const modalHeight = terminalDimensions.height - 2;
|
|
21872
|
-
return /* @__PURE__ */
|
|
21873
|
-
|
|
23298
|
+
return /* @__PURE__ */ jsx16(
|
|
23299
|
+
Box27,
|
|
21874
23300
|
{
|
|
21875
23301
|
position: "absolute",
|
|
21876
23302
|
width: terminalDimensions.width,
|
|
@@ -21878,8 +23304,8 @@ function PromptTestModal({
|
|
|
21878
23304
|
flexDirection: "column",
|
|
21879
23305
|
justifyContent: "center",
|
|
21880
23306
|
alignItems: "center",
|
|
21881
|
-
children: /* @__PURE__ */
|
|
21882
|
-
|
|
23307
|
+
children: /* @__PURE__ */ jsxs15(
|
|
23308
|
+
Box27,
|
|
21883
23309
|
{
|
|
21884
23310
|
width: modalWidth,
|
|
21885
23311
|
height: modalHeight,
|
|
@@ -21890,15 +23316,15 @@ function PromptTestModal({
|
|
|
21890
23316
|
paddingY: 1,
|
|
21891
23317
|
backgroundColor: "black",
|
|
21892
23318
|
children: [
|
|
21893
|
-
/* @__PURE__ */
|
|
21894
|
-
/* @__PURE__ */
|
|
21895
|
-
/* @__PURE__ */
|
|
21896
|
-
/* @__PURE__ */
|
|
23319
|
+
/* @__PURE__ */ jsxs15(Box27, { flexShrink: 0, marginBottom: 1, children: [
|
|
23320
|
+
/* @__PURE__ */ jsx16(Text24, { bold: true, color: "cyan", children: formStructure.title }),
|
|
23321
|
+
/* @__PURE__ */ jsx16(Text24, { children: " " }),
|
|
23322
|
+
/* @__PURE__ */ jsx16(Text24, { dimColor: true, children: "(Press ESC to close)" })
|
|
21897
23323
|
] }),
|
|
21898
|
-
/* @__PURE__ */
|
|
21899
|
-
state === "form" && /* @__PURE__ */
|
|
21900
|
-
prompt.description && /* @__PURE__ */
|
|
21901
|
-
/* @__PURE__ */
|
|
23324
|
+
/* @__PURE__ */ jsxs15(Box27, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
|
|
23325
|
+
state === "form" && /* @__PURE__ */ jsxs15(Box27, { flexGrow: 1, flexDirection: "column", children: [
|
|
23326
|
+
prompt.description && /* @__PURE__ */ jsx16(Box27, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsx16(Text24, { dimColor: true, children: prompt.description }) }),
|
|
23327
|
+
/* @__PURE__ */ jsx16(
|
|
21902
23328
|
Form,
|
|
21903
23329
|
{
|
|
21904
23330
|
form: formStructure,
|
|
@@ -21906,27 +23332,27 @@ function PromptTestModal({
|
|
|
21906
23332
|
}
|
|
21907
23333
|
)
|
|
21908
23334
|
] }),
|
|
21909
|
-
state === "loading" && /* @__PURE__ */
|
|
21910
|
-
state === "results" && result && /* @__PURE__ */
|
|
21911
|
-
/* @__PURE__ */
|
|
23335
|
+
state === "loading" && /* @__PURE__ */ jsx16(Box27, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx16(Text24, { color: "yellow", children: "Getting prompt..." }) }),
|
|
23336
|
+
state === "results" && result && /* @__PURE__ */ jsx16(Box27, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: /* @__PURE__ */ jsxs15(ScrollView, { ref: scrollViewRef, children: [
|
|
23337
|
+
/* @__PURE__ */ jsx16(Box27, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs15(Text24, { bold: true, color: "green", children: [
|
|
21912
23338
|
"Duration: ",
|
|
21913
23339
|
result.duration,
|
|
21914
23340
|
"ms"
|
|
21915
23341
|
] }) }),
|
|
21916
|
-
Object.keys(result.input).length > 0 && /* @__PURE__ */
|
|
21917
|
-
/* @__PURE__ */
|
|
21918
|
-
/* @__PURE__ */
|
|
23342
|
+
Object.keys(result.input).length > 0 && /* @__PURE__ */ jsxs15(Box27, { marginBottom: 1, flexShrink: 0, flexDirection: "column", children: [
|
|
23343
|
+
/* @__PURE__ */ jsx16(Text24, { bold: true, color: "cyan", children: "Arguments:" }),
|
|
23344
|
+
/* @__PURE__ */ jsx16(Box27, { paddingLeft: 2, children: /* @__PURE__ */ jsx16(Text24, { dimColor: true, children: JSON.stringify(result.input, null, 2) }) })
|
|
21919
23345
|
] }),
|
|
21920
|
-
result.error ? /* @__PURE__ */
|
|
21921
|
-
/* @__PURE__ */
|
|
21922
|
-
/* @__PURE__ */
|
|
21923
|
-
result.errorDetails != null ? /* @__PURE__ */
|
|
21924
|
-
/* @__PURE__ */
|
|
21925
|
-
/* @__PURE__ */
|
|
23346
|
+
result.error ? /* @__PURE__ */ jsxs15(Box27, { flexShrink: 0, flexDirection: "column", children: [
|
|
23347
|
+
/* @__PURE__ */ jsx16(Box27, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx16(Text24, { bold: true, color: "red", children: "Error:" }) }),
|
|
23348
|
+
/* @__PURE__ */ jsx16(Box27, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx16(Text24, { color: "red", children: String(result.error) }) }),
|
|
23349
|
+
result.errorDetails != null ? /* @__PURE__ */ jsxs15(Fragment12, { children: [
|
|
23350
|
+
/* @__PURE__ */ jsx16(Box27, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx16(Text24, { bold: true, color: "red", dimColor: true, children: "Error Details:" }) }),
|
|
23351
|
+
/* @__PURE__ */ jsx16(Box27, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx16(Text24, { dimColor: true, children: JSON.stringify(result.errorDetails, null, 2) }) })
|
|
21926
23352
|
] }) : null
|
|
21927
|
-
] }) : /* @__PURE__ */
|
|
21928
|
-
/* @__PURE__ */
|
|
21929
|
-
/* @__PURE__ */
|
|
23353
|
+
] }) : /* @__PURE__ */ jsxs15(Box27, { flexShrink: 0, flexDirection: "column", children: [
|
|
23354
|
+
/* @__PURE__ */ jsx16(Text24, { bold: true, color: "green", children: "Prompt Messages:" }),
|
|
23355
|
+
/* @__PURE__ */ jsx16(Box27, { paddingLeft: 2, children: /* @__PURE__ */ jsx16(Text24, { dimColor: true, children: JSON.stringify(result.output, null, 2) }) })
|
|
21930
23356
|
] })
|
|
21931
23357
|
] }) })
|
|
21932
23358
|
] })
|
|
@@ -21939,8 +23365,8 @@ function PromptTestModal({
|
|
|
21939
23365
|
|
|
21940
23366
|
// src/components/DetailsModal.tsx
|
|
21941
23367
|
import React29, { useRef as useRef14 } from "react";
|
|
21942
|
-
import { Box as
|
|
21943
|
-
import { jsx as
|
|
23368
|
+
import { Box as Box28, Text as Text25, useInput as useInput21 } from "ink";
|
|
23369
|
+
import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
21944
23370
|
function DetailsModal({
|
|
21945
23371
|
title,
|
|
21946
23372
|
content,
|
|
@@ -21986,8 +23412,8 @@ function DetailsModal({
|
|
|
21986
23412
|
);
|
|
21987
23413
|
const modalWidth = terminalDimensions.width - 2;
|
|
21988
23414
|
const modalHeight = terminalDimensions.height - 2;
|
|
21989
|
-
return /* @__PURE__ */
|
|
21990
|
-
|
|
23415
|
+
return /* @__PURE__ */ jsx17(
|
|
23416
|
+
Box28,
|
|
21991
23417
|
{
|
|
21992
23418
|
position: "absolute",
|
|
21993
23419
|
width: terminalDimensions.width,
|
|
@@ -21995,8 +23421,8 @@ function DetailsModal({
|
|
|
21995
23421
|
flexDirection: "column",
|
|
21996
23422
|
justifyContent: "center",
|
|
21997
23423
|
alignItems: "center",
|
|
21998
|
-
children: /* @__PURE__ */
|
|
21999
|
-
|
|
23424
|
+
children: /* @__PURE__ */ jsxs16(
|
|
23425
|
+
Box28,
|
|
22000
23426
|
{
|
|
22001
23427
|
width: modalWidth,
|
|
22002
23428
|
height: modalHeight,
|
|
@@ -22007,12 +23433,12 @@ function DetailsModal({
|
|
|
22007
23433
|
paddingY: 1,
|
|
22008
23434
|
backgroundColor: "black",
|
|
22009
23435
|
children: [
|
|
22010
|
-
/* @__PURE__ */
|
|
22011
|
-
/* @__PURE__ */
|
|
22012
|
-
/* @__PURE__ */
|
|
22013
|
-
/* @__PURE__ */
|
|
23436
|
+
/* @__PURE__ */ jsxs16(Box28, { flexShrink: 0, marginBottom: 1, children: [
|
|
23437
|
+
/* @__PURE__ */ jsx17(Text25, { bold: true, color: "cyan", children: title }),
|
|
23438
|
+
/* @__PURE__ */ jsx17(Text25, { children: " " }),
|
|
23439
|
+
/* @__PURE__ */ jsx17(Text25, { dimColor: true, children: "(Press ESC to close)" })
|
|
22014
23440
|
] }),
|
|
22015
|
-
/* @__PURE__ */
|
|
23441
|
+
/* @__PURE__ */ jsx17(Box28, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: /* @__PURE__ */ jsx17(ScrollView, { ref: scrollViewRef, children: content }) })
|
|
22016
23442
|
]
|
|
22017
23443
|
}
|
|
22018
23444
|
)
|
|
@@ -22021,7 +23447,7 @@ function DetailsModal({
|
|
|
22021
23447
|
}
|
|
22022
23448
|
|
|
22023
23449
|
// src/App.tsx
|
|
22024
|
-
import { Fragment as
|
|
23450
|
+
import { Fragment as Fragment13, jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
22025
23451
|
var APP_NAME = "MCP Inspector TUI";
|
|
22026
23452
|
var APP_DESCRIPTION = "Terminal User Interface for the Model Context Protocol Inspector";
|
|
22027
23453
|
var APP_VERSION = readInspectorVersion(import.meta.url);
|
|
@@ -22709,48 +24135,48 @@ function App({
|
|
|
22709
24135
|
managedTools,
|
|
22710
24136
|
inspectorStderrLogs
|
|
22711
24137
|
]);
|
|
22712
|
-
const renderResourceDetails = (resource) => /* @__PURE__ */
|
|
22713
|
-
"uri" in resource && resource.description && /* @__PURE__ */
|
|
22714
|
-
|
|
24138
|
+
const renderResourceDetails = (resource) => /* @__PURE__ */ jsxs17(Fragment13, { children: [
|
|
24139
|
+
"uri" in resource && resource.description && /* @__PURE__ */ jsx18(Fragment13, { children: resource.description.split("\n").map((line, idx) => /* @__PURE__ */ jsx18(
|
|
24140
|
+
Box29,
|
|
22715
24141
|
{
|
|
22716
24142
|
marginTop: idx === 0 ? 0 : 0,
|
|
22717
24143
|
flexShrink: 0,
|
|
22718
|
-
children: /* @__PURE__ */
|
|
24144
|
+
children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: line })
|
|
22719
24145
|
},
|
|
22720
24146
|
`desc-${idx}`
|
|
22721
24147
|
)) }),
|
|
22722
|
-
"uri" in resource && resource.uri && /* @__PURE__ */
|
|
22723
|
-
/* @__PURE__ */
|
|
22724
|
-
/* @__PURE__ */
|
|
24148
|
+
"uri" in resource && resource.uri && /* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, children: [
|
|
24149
|
+
/* @__PURE__ */ jsx18(Text26, { bold: true, children: "URI:" }),
|
|
24150
|
+
/* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: resource.uri }) })
|
|
22725
24151
|
] }),
|
|
22726
|
-
"mimeType" in resource && resource.mimeType && /* @__PURE__ */
|
|
22727
|
-
/* @__PURE__ */
|
|
22728
|
-
/* @__PURE__ */
|
|
24152
|
+
"mimeType" in resource && resource.mimeType && /* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, children: [
|
|
24153
|
+
/* @__PURE__ */ jsx18(Text26, { bold: true, children: "MIME Type:" }),
|
|
24154
|
+
/* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: resource.mimeType }) })
|
|
22729
24155
|
] }),
|
|
22730
|
-
/* @__PURE__ */
|
|
22731
|
-
/* @__PURE__ */
|
|
22732
|
-
/* @__PURE__ */
|
|
24156
|
+
/* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
|
|
24157
|
+
/* @__PURE__ */ jsx18(Text26, { bold: true, children: "Full JSON:" }),
|
|
24158
|
+
/* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: JSON.stringify(resource, null, 2) }) })
|
|
22733
24159
|
] })
|
|
22734
24160
|
] });
|
|
22735
|
-
const renderPromptDetails = (prompt) => /* @__PURE__ */
|
|
22736
|
-
prompt.description && /* @__PURE__ */
|
|
22737
|
-
|
|
24161
|
+
const renderPromptDetails = (prompt) => /* @__PURE__ */ jsxs17(Fragment13, { children: [
|
|
24162
|
+
prompt.description && /* @__PURE__ */ jsx18(Fragment13, { children: prompt.description.split("\n").map((line, idx) => /* @__PURE__ */ jsx18(
|
|
24163
|
+
Box29,
|
|
22738
24164
|
{
|
|
22739
24165
|
marginTop: idx === 0 ? 0 : 0,
|
|
22740
24166
|
flexShrink: 0,
|
|
22741
|
-
children: /* @__PURE__ */
|
|
24167
|
+
children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: line })
|
|
22742
24168
|
},
|
|
22743
24169
|
`desc-${idx}`
|
|
22744
24170
|
)) }),
|
|
22745
|
-
prompt.arguments && prompt.arguments.length > 0 && /* @__PURE__ */
|
|
22746
|
-
/* @__PURE__ */
|
|
22747
|
-
prompt.arguments.map((arg, idx) => /* @__PURE__ */
|
|
22748
|
-
|
|
24171
|
+
prompt.arguments && prompt.arguments.length > 0 && /* @__PURE__ */ jsxs17(Fragment13, { children: [
|
|
24172
|
+
/* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx18(Text26, { bold: true, children: "Arguments:" }) }),
|
|
24173
|
+
prompt.arguments.map((arg, idx) => /* @__PURE__ */ jsx18(
|
|
24174
|
+
Box29,
|
|
22749
24175
|
{
|
|
22750
24176
|
marginTop: 1,
|
|
22751
24177
|
paddingLeft: 2,
|
|
22752
24178
|
flexShrink: 0,
|
|
22753
|
-
children: /* @__PURE__ */
|
|
24179
|
+
children: /* @__PURE__ */ jsxs17(Text26, { dimColor: true, children: [
|
|
22754
24180
|
"- ",
|
|
22755
24181
|
arg.name,
|
|
22756
24182
|
":",
|
|
@@ -22761,134 +24187,102 @@ function App({
|
|
|
22761
24187
|
`arg-${idx}`
|
|
22762
24188
|
))
|
|
22763
24189
|
] }),
|
|
22764
|
-
/* @__PURE__ */
|
|
22765
|
-
/* @__PURE__ */
|
|
22766
|
-
/* @__PURE__ */
|
|
24190
|
+
/* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
|
|
24191
|
+
/* @__PURE__ */ jsx18(Text26, { bold: true, children: "Full JSON:" }),
|
|
24192
|
+
/* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: JSON.stringify(prompt, null, 2) }) })
|
|
22767
24193
|
] })
|
|
22768
24194
|
] });
|
|
22769
|
-
const renderToolDetails = (tool) => /* @__PURE__ */
|
|
22770
|
-
tool.description && /* @__PURE__ */
|
|
22771
|
-
|
|
24195
|
+
const renderToolDetails = (tool) => /* @__PURE__ */ jsxs17(Fragment13, { children: [
|
|
24196
|
+
tool.description && /* @__PURE__ */ jsx18(Fragment13, { children: tool.description.split("\n").map((line, idx) => /* @__PURE__ */ jsx18(
|
|
24197
|
+
Box29,
|
|
22772
24198
|
{
|
|
22773
24199
|
marginTop: idx === 0 ? 0 : 0,
|
|
22774
24200
|
flexShrink: 0,
|
|
22775
|
-
children: /* @__PURE__ */
|
|
24201
|
+
children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: line })
|
|
22776
24202
|
},
|
|
22777
24203
|
`desc-${idx}`
|
|
22778
24204
|
)) }),
|
|
22779
|
-
tool.inputSchema && /* @__PURE__ */
|
|
22780
|
-
/* @__PURE__ */
|
|
22781
|
-
/* @__PURE__ */
|
|
24205
|
+
tool.inputSchema && /* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
|
|
24206
|
+
/* @__PURE__ */ jsx18(Text26, { bold: true, children: "Input Schema:" }),
|
|
24207
|
+
/* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: JSON.stringify(tool.inputSchema, null, 2) }) })
|
|
22782
24208
|
] }),
|
|
22783
|
-
/* @__PURE__ */
|
|
22784
|
-
/* @__PURE__ */
|
|
22785
|
-
/* @__PURE__ */
|
|
24209
|
+
/* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
|
|
24210
|
+
/* @__PURE__ */ jsx18(Text26, { bold: true, children: "Full JSON:" }),
|
|
24211
|
+
/* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: JSON.stringify(tool, null, 2) }) })
|
|
22786
24212
|
] })
|
|
22787
24213
|
] });
|
|
22788
|
-
const renderRequestDetails = (request) => /* @__PURE__ */
|
|
22789
|
-
/* @__PURE__ */
|
|
24214
|
+
const renderRequestDetails = (request) => /* @__PURE__ */ jsxs17(Fragment13, { children: [
|
|
24215
|
+
/* @__PURE__ */ jsx18(Box29, { flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { bold: true, children: [
|
|
22790
24216
|
request.method,
|
|
22791
24217
|
" ",
|
|
22792
24218
|
request.url
|
|
22793
24219
|
] }) }),
|
|
22794
|
-
/* @__PURE__ */
|
|
24220
|
+
/* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { bold: true, children: [
|
|
22795
24221
|
"Category:",
|
|
22796
24222
|
" ",
|
|
22797
|
-
/* @__PURE__ */
|
|
24223
|
+
/* @__PURE__ */ jsx18(Text26, { children: request.category === "auth" ? "auth" : "transport" })
|
|
22798
24224
|
] }) }),
|
|
22799
|
-
request.responseStatus !== void 0 ? /* @__PURE__ */
|
|
24225
|
+
request.responseStatus !== void 0 ? /* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { bold: true, children: [
|
|
22800
24226
|
"Status: ",
|
|
22801
24227
|
request.responseStatus,
|
|
22802
24228
|
" ",
|
|
22803
24229
|
request.responseStatusText || ""
|
|
22804
|
-
] }) }) : request.error ? /* @__PURE__ */
|
|
24230
|
+
] }) }) : request.error ? /* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { bold: true, color: "red", children: [
|
|
22805
24231
|
"Error: ",
|
|
22806
24232
|
request.error
|
|
22807
24233
|
] }) }) : null,
|
|
22808
|
-
request.duration !== void 0 && /* @__PURE__ */
|
|
24234
|
+
request.duration !== void 0 && /* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { dimColor: true, children: [
|
|
22809
24235
|
request.timestamp.toLocaleTimeString(),
|
|
22810
24236
|
" (",
|
|
22811
24237
|
request.duration,
|
|
22812
24238
|
"ms)"
|
|
22813
24239
|
] }) }),
|
|
22814
|
-
/* @__PURE__ */
|
|
22815
|
-
/* @__PURE__ */
|
|
22816
|
-
Object.entries(request.requestHeaders).map(([key, value]) => /* @__PURE__ */
|
|
24240
|
+
/* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, children: [
|
|
24241
|
+
/* @__PURE__ */ jsx18(Text26, { bold: true, children: "Request Headers:" }),
|
|
24242
|
+
Object.entries(request.requestHeaders).map(([key, value]) => /* @__PURE__ */ jsx18(Box29, { marginTop: 0, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { dimColor: true, children: [
|
|
22817
24243
|
key,
|
|
22818
24244
|
": ",
|
|
22819
24245
|
value
|
|
22820
24246
|
] }) }, key))
|
|
22821
24247
|
] }),
|
|
22822
|
-
request.requestBody && /* @__PURE__ */
|
|
22823
|
-
/* @__PURE__ */
|
|
22824
|
-
(
|
|
22825
|
-
try {
|
|
22826
|
-
const parsed = JSON.parse(request.requestBody);
|
|
22827
|
-
return JSON.stringify(parsed, null, 2).split("\n").map((line, idx) => /* @__PURE__ */ jsx17(
|
|
22828
|
-
Box28,
|
|
22829
|
-
{
|
|
22830
|
-
marginTop: idx === 0 ? 1 : 0,
|
|
22831
|
-
paddingLeft: 2,
|
|
22832
|
-
flexShrink: 0,
|
|
22833
|
-
children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: line })
|
|
22834
|
-
},
|
|
22835
|
-
`req-body-${idx}`
|
|
22836
|
-
));
|
|
22837
|
-
} catch {
|
|
22838
|
-
return /* @__PURE__ */ jsx17(Box28, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: request.requestBody }) });
|
|
22839
|
-
}
|
|
22840
|
-
})()
|
|
24248
|
+
request.requestBody && /* @__PURE__ */ jsxs17(Fragment13, { children: [
|
|
24249
|
+
/* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx18(Text26, { bold: true, children: "Request Body:" }) }),
|
|
24250
|
+
/* @__PURE__ */ jsx18(BodyLines, { body: request.requestBody, keyPrefix: "req-body" })
|
|
22841
24251
|
] }),
|
|
22842
|
-
request.responseHeaders && Object.keys(request.responseHeaders).length > 0 && /* @__PURE__ */
|
|
22843
|
-
/* @__PURE__ */
|
|
22844
|
-
Object.entries(request.responseHeaders).map(([key, value]) => /* @__PURE__ */
|
|
24252
|
+
request.responseHeaders && Object.keys(request.responseHeaders).length > 0 && /* @__PURE__ */ jsxs17(Fragment13, { children: [
|
|
24253
|
+
/* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx18(Text26, { bold: true, children: "Response Headers:" }) }),
|
|
24254
|
+
Object.entries(request.responseHeaders).map(([key, value]) => /* @__PURE__ */ jsx18(Box29, { marginTop: 0, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { dimColor: true, children: [
|
|
22845
24255
|
key,
|
|
22846
24256
|
": ",
|
|
22847
24257
|
value
|
|
22848
24258
|
] }) }, key))
|
|
22849
24259
|
] }),
|
|
22850
|
-
request.responseBody && /* @__PURE__ */
|
|
22851
|
-
/* @__PURE__ */
|
|
22852
|
-
(
|
|
22853
|
-
try {
|
|
22854
|
-
const parsed = JSON.parse(request.responseBody);
|
|
22855
|
-
return JSON.stringify(parsed, null, 2).split("\n").map((line, idx) => /* @__PURE__ */ jsx17(
|
|
22856
|
-
Box28,
|
|
22857
|
-
{
|
|
22858
|
-
marginTop: idx === 0 ? 1 : 0,
|
|
22859
|
-
paddingLeft: 2,
|
|
22860
|
-
flexShrink: 0,
|
|
22861
|
-
children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: line })
|
|
22862
|
-
},
|
|
22863
|
-
`resp-body-${idx}`
|
|
22864
|
-
));
|
|
22865
|
-
} catch {
|
|
22866
|
-
return /* @__PURE__ */ jsx17(Box28, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: request.responseBody }) });
|
|
22867
|
-
}
|
|
22868
|
-
})()
|
|
24260
|
+
request.responseBody && /* @__PURE__ */ jsxs17(Fragment13, { children: [
|
|
24261
|
+
/* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx18(Text26, { bold: true, children: "Response Body:" }) }),
|
|
24262
|
+
/* @__PURE__ */ jsx18(BodyLines, { body: request.responseBody, keyPrefix: "resp-body" })
|
|
22869
24263
|
] })
|
|
22870
24264
|
] });
|
|
22871
|
-
const renderMessageDetails = (message) => /* @__PURE__ */
|
|
22872
|
-
/* @__PURE__ */
|
|
24265
|
+
const renderMessageDetails = (message) => /* @__PURE__ */ jsxs17(Fragment13, { children: [
|
|
24266
|
+
/* @__PURE__ */ jsx18(Box29, { flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { bold: true, children: [
|
|
22873
24267
|
"Direction: ",
|
|
22874
24268
|
message.direction
|
|
22875
24269
|
] }) }),
|
|
22876
|
-
/* @__PURE__ */
|
|
24270
|
+
/* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { dimColor: true, children: [
|
|
22877
24271
|
message.timestamp.toLocaleTimeString(),
|
|
22878
24272
|
message.duration !== void 0 && ` (${message.duration}ms)`
|
|
22879
24273
|
] }) }),
|
|
22880
|
-
message.direction === "request" ? /* @__PURE__ */
|
|
22881
|
-
/* @__PURE__ */
|
|
22882
|
-
/* @__PURE__ */
|
|
22883
|
-
/* @__PURE__ */
|
|
24274
|
+
message.direction === "request" ? /* @__PURE__ */ jsxs17(Fragment13, { children: [
|
|
24275
|
+
/* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
|
|
24276
|
+
/* @__PURE__ */ jsx18(Text26, { bold: true, children: "Request:" }),
|
|
24277
|
+
/* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: JSON.stringify(message.message, null, 2) }) })
|
|
22884
24278
|
] }),
|
|
22885
|
-
message.response && /* @__PURE__ */
|
|
22886
|
-
/* @__PURE__ */
|
|
22887
|
-
/* @__PURE__ */
|
|
24279
|
+
message.response && /* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
|
|
24280
|
+
/* @__PURE__ */ jsx18(Text26, { bold: true, children: "Response:" }),
|
|
24281
|
+
/* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: JSON.stringify(message.response, null, 2) }) })
|
|
22888
24282
|
] })
|
|
22889
|
-
] }) : /* @__PURE__ */
|
|
22890
|
-
/* @__PURE__ */
|
|
22891
|
-
/* @__PURE__ */
|
|
24283
|
+
] }) : /* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
|
|
24284
|
+
/* @__PURE__ */ jsx18(Text26, { bold: true, children: message.direction === "response" ? "Response:" : "Notification:" }),
|
|
24285
|
+
/* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: JSON.stringify(message.message, null, 2) }) })
|
|
22892
24286
|
] })
|
|
22893
24287
|
] });
|
|
22894
24288
|
useEffect14(() => {
|
|
@@ -23079,15 +24473,15 @@ function App({
|
|
|
23079
24473
|
return "\u25CB";
|
|
23080
24474
|
}
|
|
23081
24475
|
};
|
|
23082
|
-
return /* @__PURE__ */
|
|
23083
|
-
|
|
24476
|
+
return /* @__PURE__ */ jsxs17(
|
|
24477
|
+
Box29,
|
|
23084
24478
|
{
|
|
23085
24479
|
flexDirection: "column",
|
|
23086
24480
|
width: dimensions.width,
|
|
23087
24481
|
height: dimensions.height,
|
|
23088
24482
|
children: [
|
|
23089
|
-
/* @__PURE__ */
|
|
23090
|
-
|
|
24483
|
+
/* @__PURE__ */ jsxs17(
|
|
24484
|
+
Box29,
|
|
23091
24485
|
{
|
|
23092
24486
|
width: dimensions.width,
|
|
23093
24487
|
height: headerHeight,
|
|
@@ -23099,29 +24493,29 @@ function App({
|
|
|
23099
24493
|
justifyContent: "space-between",
|
|
23100
24494
|
alignItems: "center",
|
|
23101
24495
|
children: [
|
|
23102
|
-
/* @__PURE__ */
|
|
23103
|
-
/* @__PURE__ */
|
|
23104
|
-
/* @__PURE__ */
|
|
24496
|
+
/* @__PURE__ */ jsxs17(Box29, { children: [
|
|
24497
|
+
/* @__PURE__ */ jsx18(Text26, { bold: true, color: "cyan", children: APP_NAME }),
|
|
24498
|
+
/* @__PURE__ */ jsxs17(Text26, { dimColor: true, children: [
|
|
23105
24499
|
" - ",
|
|
23106
24500
|
APP_DESCRIPTION
|
|
23107
24501
|
] })
|
|
23108
24502
|
] }),
|
|
23109
|
-
/* @__PURE__ */
|
|
24503
|
+
/* @__PURE__ */ jsxs17(Text26, { dimColor: true, children: [
|
|
23110
24504
|
"v",
|
|
23111
24505
|
APP_VERSION
|
|
23112
24506
|
] })
|
|
23113
24507
|
]
|
|
23114
24508
|
}
|
|
23115
24509
|
),
|
|
23116
|
-
/* @__PURE__ */
|
|
23117
|
-
|
|
24510
|
+
/* @__PURE__ */ jsxs17(
|
|
24511
|
+
Box29,
|
|
23118
24512
|
{
|
|
23119
24513
|
flexDirection: "row",
|
|
23120
24514
|
height: availableHeight + tabsHeight,
|
|
23121
24515
|
width: dimensions.width,
|
|
23122
24516
|
children: [
|
|
23123
|
-
/* @__PURE__ */
|
|
23124
|
-
|
|
24517
|
+
/* @__PURE__ */ jsxs17(
|
|
24518
|
+
Box29,
|
|
23125
24519
|
{
|
|
23126
24520
|
width: serverListWidth,
|
|
23127
24521
|
height: availableHeight + tabsHeight,
|
|
@@ -23133,43 +24527,43 @@ function App({
|
|
|
23133
24527
|
flexDirection: "column",
|
|
23134
24528
|
paddingX: 1,
|
|
23135
24529
|
children: [
|
|
23136
|
-
/* @__PURE__ */
|
|
23137
|
-
|
|
24530
|
+
/* @__PURE__ */ jsx18(Box29, { marginTop: 1, marginBottom: 1, children: /* @__PURE__ */ jsx18(
|
|
24531
|
+
Text26,
|
|
23138
24532
|
{
|
|
23139
24533
|
bold: true,
|
|
23140
24534
|
backgroundColor: focus === "serverList" ? "yellow" : void 0,
|
|
23141
24535
|
children: "MCP Servers"
|
|
23142
24536
|
}
|
|
23143
24537
|
) }),
|
|
23144
|
-
/* @__PURE__ */
|
|
24538
|
+
/* @__PURE__ */ jsx18(Box29, { flexDirection: "column", flexGrow: 1, children: serverNames.map((serverName) => {
|
|
23145
24539
|
const isSelected = selectedServer === serverName;
|
|
23146
|
-
return /* @__PURE__ */
|
|
24540
|
+
return /* @__PURE__ */ jsx18(Box29, { paddingY: 0, children: /* @__PURE__ */ jsxs17(Text26, { children: [
|
|
23147
24541
|
isSelected ? "\u25B6 " : " ",
|
|
23148
24542
|
serverName
|
|
23149
24543
|
] }) }, serverName);
|
|
23150
24544
|
}) }),
|
|
23151
|
-
/* @__PURE__ */
|
|
23152
|
-
|
|
24545
|
+
/* @__PURE__ */ jsx18(
|
|
24546
|
+
Box29,
|
|
23153
24547
|
{
|
|
23154
24548
|
flexShrink: 0,
|
|
23155
24549
|
height: 1,
|
|
23156
24550
|
justifyContent: "center",
|
|
23157
24551
|
backgroundColor: "gray",
|
|
23158
|
-
children: /* @__PURE__ */
|
|
24552
|
+
children: /* @__PURE__ */ jsx18(Text26, { bold: true, color: "white", children: "ESC to exit" })
|
|
23159
24553
|
}
|
|
23160
24554
|
)
|
|
23161
24555
|
]
|
|
23162
24556
|
}
|
|
23163
24557
|
),
|
|
23164
|
-
/* @__PURE__ */
|
|
23165
|
-
|
|
24558
|
+
/* @__PURE__ */ jsxs17(
|
|
24559
|
+
Box29,
|
|
23166
24560
|
{
|
|
23167
24561
|
flexGrow: 1,
|
|
23168
24562
|
height: availableHeight + tabsHeight,
|
|
23169
24563
|
flexDirection: "column",
|
|
23170
24564
|
children: [
|
|
23171
|
-
/* @__PURE__ */
|
|
23172
|
-
|
|
24565
|
+
/* @__PURE__ */ jsx18(
|
|
24566
|
+
Box29,
|
|
23173
24567
|
{
|
|
23174
24568
|
width: contentWidth,
|
|
23175
24569
|
borderStyle: "single",
|
|
@@ -23181,49 +24575,49 @@ function App({
|
|
|
23181
24575
|
paddingY: 1,
|
|
23182
24576
|
flexDirection: "column",
|
|
23183
24577
|
flexShrink: 0,
|
|
23184
|
-
children: /* @__PURE__ */
|
|
23185
|
-
/* @__PURE__ */
|
|
23186
|
-
|
|
24578
|
+
children: /* @__PURE__ */ jsxs17(Box29, { flexDirection: "column", children: [
|
|
24579
|
+
/* @__PURE__ */ jsxs17(
|
|
24580
|
+
Box29,
|
|
23187
24581
|
{
|
|
23188
24582
|
flexDirection: "row",
|
|
23189
24583
|
justifyContent: "space-between",
|
|
23190
24584
|
alignItems: "center",
|
|
23191
24585
|
children: [
|
|
23192
|
-
/* @__PURE__ */
|
|
23193
|
-
/* @__PURE__ */
|
|
23194
|
-
/* @__PURE__ */
|
|
24586
|
+
/* @__PURE__ */ jsx18(Text26, { bold: true, color: "cyan", children: selectedServer }),
|
|
24587
|
+
/* @__PURE__ */ jsx18(Box29, { flexDirection: "row", alignItems: "center", gap: 1, children: currentServerState && /* @__PURE__ */ jsxs17(Fragment13, { children: [
|
|
24588
|
+
/* @__PURE__ */ jsxs17(Text26, { color: getStatusColor(currentServerState.status), children: [
|
|
23195
24589
|
getStatusSymbol(currentServerState.status),
|
|
23196
24590
|
" ",
|
|
23197
24591
|
currentServerState.status
|
|
23198
24592
|
] }),
|
|
23199
|
-
/* @__PURE__ */
|
|
23200
|
-
(currentServerState?.status === "disconnected" || currentServerState?.status === "error") && /* @__PURE__ */
|
|
24593
|
+
/* @__PURE__ */ jsx18(Text26, { children: " " }),
|
|
24594
|
+
(currentServerState?.status === "disconnected" || currentServerState?.status === "error") && /* @__PURE__ */ jsxs17(Text26, { color: "cyan", bold: true, children: [
|
|
23201
24595
|
"[",
|
|
23202
|
-
/* @__PURE__ */
|
|
24596
|
+
/* @__PURE__ */ jsx18(Text26, { underline: true, children: "C" }),
|
|
23203
24597
|
"onnect]"
|
|
23204
24598
|
] }),
|
|
23205
|
-
(currentServerState?.status === "connected" || currentServerState?.status === "connecting") && /* @__PURE__ */
|
|
24599
|
+
(currentServerState?.status === "connected" || currentServerState?.status === "connecting") && /* @__PURE__ */ jsxs17(Text26, { color: "red", bold: true, children: [
|
|
23206
24600
|
"[",
|
|
23207
|
-
/* @__PURE__ */
|
|
24601
|
+
/* @__PURE__ */ jsx18(Text26, { underline: true, children: "D" }),
|
|
23208
24602
|
"isconnect]"
|
|
23209
24603
|
] })
|
|
23210
24604
|
] }) })
|
|
23211
24605
|
]
|
|
23212
24606
|
}
|
|
23213
24607
|
),
|
|
23214
|
-
oauthStatus === "authenticating" && /* @__PURE__ */
|
|
23215
|
-
oauthStatus === "error" && oauthMessage && /* @__PURE__ */
|
|
24608
|
+
oauthStatus === "authenticating" && /* @__PURE__ */ jsx18(Box29, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: "OAuth: authenticating\u2026" }) }),
|
|
24609
|
+
oauthStatus === "error" && oauthMessage && /* @__PURE__ */ jsx18(Box29, { marginTop: 1, children: /* @__PURE__ */ jsxs17(Text26, { color: "red", children: [
|
|
23216
24610
|
"OAuth: ",
|
|
23217
24611
|
oauthMessage
|
|
23218
24612
|
] }) }),
|
|
23219
|
-
disconnectError && /* @__PURE__ */
|
|
24613
|
+
disconnectError && /* @__PURE__ */ jsx18(Box29, { marginTop: 1, children: /* @__PURE__ */ jsxs17(Text26, { color: "red", children: [
|
|
23220
24614
|
"Disconnect failed: ",
|
|
23221
24615
|
disconnectError
|
|
23222
24616
|
] }) })
|
|
23223
24617
|
] })
|
|
23224
24618
|
}
|
|
23225
24619
|
),
|
|
23226
|
-
/* @__PURE__ */
|
|
24620
|
+
/* @__PURE__ */ jsx18(
|
|
23227
24621
|
Tabs,
|
|
23228
24622
|
{
|
|
23229
24623
|
activeTab,
|
|
@@ -23240,8 +24634,8 @@ function App({
|
|
|
23240
24634
|
})() : false
|
|
23241
24635
|
}
|
|
23242
24636
|
),
|
|
23243
|
-
/* @__PURE__ */
|
|
23244
|
-
|
|
24637
|
+
/* @__PURE__ */ jsxs17(
|
|
24638
|
+
Box29,
|
|
23245
24639
|
{
|
|
23246
24640
|
flexGrow: 1,
|
|
23247
24641
|
minHeight: 6,
|
|
@@ -23251,7 +24645,7 @@ function App({
|
|
|
23251
24645
|
borderRight: false,
|
|
23252
24646
|
borderBottom: false,
|
|
23253
24647
|
children: [
|
|
23254
|
-
activeTab === "info" && /* @__PURE__ */
|
|
24648
|
+
activeTab === "info" && /* @__PURE__ */ jsx18(
|
|
23255
24649
|
InfoTab,
|
|
23256
24650
|
{
|
|
23257
24651
|
serverName: selectedServer,
|
|
@@ -23263,7 +24657,7 @@ function App({
|
|
|
23263
24657
|
focused: focus === "tabContentList" || focus === "tabContentDetails"
|
|
23264
24658
|
}
|
|
23265
24659
|
),
|
|
23266
|
-
activeTab === "auth" && selectedServer && selectedServerConfig && isOAuthCapableServerConfig(selectedServerConfig) ? /* @__PURE__ */
|
|
24660
|
+
activeTab === "auth" && selectedServer && selectedServerConfig && isOAuthCapableServerConfig(selectedServerConfig) ? /* @__PURE__ */ jsx18(
|
|
23267
24661
|
AuthTab,
|
|
23268
24662
|
{
|
|
23269
24663
|
serverName: selectedServer,
|
|
@@ -23361,7 +24755,7 @@ function App({
|
|
|
23361
24755
|
connectionStatus: inspectorStatus
|
|
23362
24756
|
}
|
|
23363
24757
|
) : null,
|
|
23364
|
-
activeTab === "resources" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */
|
|
24758
|
+
activeTab === "resources" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
|
|
23365
24759
|
ResourcesTab,
|
|
23366
24760
|
{
|
|
23367
24761
|
resources: currentServerState.resources,
|
|
@@ -23387,7 +24781,7 @@ function App({
|
|
|
23387
24781
|
modalOpen: !!(toolTestModal || resourceTestModal || promptTestModal || detailsModal)
|
|
23388
24782
|
},
|
|
23389
24783
|
`resources-${selectedServer}`
|
|
23390
|
-
) : activeTab === "skills" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */
|
|
24784
|
+
) : activeTab === "skills" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
|
|
23391
24785
|
SkillsTab,
|
|
23392
24786
|
{
|
|
23393
24787
|
skills: managedSkills,
|
|
@@ -23401,7 +24795,7 @@ function App({
|
|
|
23401
24795
|
modalOpen: !!(toolTestModal || resourceTestModal || promptTestModal || detailsModal)
|
|
23402
24796
|
},
|
|
23403
24797
|
`skills-${selectedServer}`
|
|
23404
|
-
) : activeTab === "prompts" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */
|
|
24798
|
+
) : activeTab === "prompts" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
|
|
23405
24799
|
PromptsTab,
|
|
23406
24800
|
{
|
|
23407
24801
|
prompts: currentServerState.prompts,
|
|
@@ -23424,7 +24818,7 @@ function App({
|
|
|
23424
24818
|
modalOpen: !!(toolTestModal || resourceTestModal || promptTestModal || detailsModal)
|
|
23425
24819
|
},
|
|
23426
24820
|
`prompts-${selectedServer}`
|
|
23427
|
-
) : activeTab === "tools" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */
|
|
24821
|
+
) : activeTab === "tools" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
|
|
23428
24822
|
ToolsTab,
|
|
23429
24823
|
{
|
|
23430
24824
|
tools: currentServerState.tools,
|
|
@@ -23444,7 +24838,7 @@ function App({
|
|
|
23444
24838
|
modalOpen: !!(toolTestModal || detailsModal)
|
|
23445
24839
|
},
|
|
23446
24840
|
`tools-${selectedServer}`
|
|
23447
|
-
) : activeTab === "messages" && selectedInspectorClient ? /* @__PURE__ */
|
|
24841
|
+
) : activeTab === "messages" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
|
|
23448
24842
|
HistoryTab,
|
|
23449
24843
|
{
|
|
23450
24844
|
serverName: selectedServer,
|
|
@@ -23462,7 +24856,7 @@ function App({
|
|
|
23462
24856
|
});
|
|
23463
24857
|
}
|
|
23464
24858
|
}
|
|
23465
|
-
) : activeTab === "requests" && selectedInspectorClient && (inspectorStatus === "connected" || inspectorFetchRequests.length > 0) ? /* @__PURE__ */
|
|
24859
|
+
) : activeTab === "requests" && selectedInspectorClient && (inspectorStatus === "connected" || inspectorFetchRequests.length > 0) ? /* @__PURE__ */ jsx18(
|
|
23466
24860
|
RequestsTab,
|
|
23467
24861
|
{
|
|
23468
24862
|
serverName: selectedServer,
|
|
@@ -23479,7 +24873,7 @@ function App({
|
|
|
23479
24873
|
});
|
|
23480
24874
|
}
|
|
23481
24875
|
}
|
|
23482
|
-
) : activeTab === "logging" && selectedInspectorClient ? /* @__PURE__ */
|
|
24876
|
+
) : activeTab === "logging" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
|
|
23483
24877
|
NotificationsTab,
|
|
23484
24878
|
{
|
|
23485
24879
|
stderrLogs: inspectorStderrLogs,
|
|
@@ -23498,7 +24892,7 @@ function App({
|
|
|
23498
24892
|
]
|
|
23499
24893
|
}
|
|
23500
24894
|
),
|
|
23501
|
-
toolTestModal && /* @__PURE__ */
|
|
24895
|
+
toolTestModal && /* @__PURE__ */ jsx18(
|
|
23502
24896
|
ToolTestModal,
|
|
23503
24897
|
{
|
|
23504
24898
|
tool: toolTestModal.tool,
|
|
@@ -23512,7 +24906,7 @@ function App({
|
|
|
23512
24906
|
}
|
|
23513
24907
|
}
|
|
23514
24908
|
),
|
|
23515
|
-
resourceTestModal && /* @__PURE__ */
|
|
24909
|
+
resourceTestModal && /* @__PURE__ */ jsx18(
|
|
23516
24910
|
ResourceTestModal,
|
|
23517
24911
|
{
|
|
23518
24912
|
template: resourceTestModal.template,
|
|
@@ -23526,7 +24920,7 @@ function App({
|
|
|
23526
24920
|
}
|
|
23527
24921
|
}
|
|
23528
24922
|
),
|
|
23529
|
-
promptTestModal && /* @__PURE__ */
|
|
24923
|
+
promptTestModal && /* @__PURE__ */ jsx18(
|
|
23530
24924
|
PromptTestModal,
|
|
23531
24925
|
{
|
|
23532
24926
|
prompt: promptTestModal.prompt,
|
|
@@ -23540,7 +24934,7 @@ function App({
|
|
|
23540
24934
|
}
|
|
23541
24935
|
}
|
|
23542
24936
|
),
|
|
23543
|
-
detailsModal && /* @__PURE__ */
|
|
24937
|
+
detailsModal && /* @__PURE__ */ jsx18(
|
|
23544
24938
|
DetailsModal,
|
|
23545
24939
|
{
|
|
23546
24940
|
title: detailsModal.title,
|
|
@@ -23557,7 +24951,7 @@ function App({
|
|
|
23557
24951
|
var App_default = App;
|
|
23558
24952
|
|
|
23559
24953
|
// tui.tsx
|
|
23560
|
-
import { jsx as
|
|
24954
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
23561
24955
|
async function runTui(args) {
|
|
23562
24956
|
const program = new Command();
|
|
23563
24957
|
program.name("mcp-inspector-tui").description("Terminal UI for MCP Inspector").option(
|
|
@@ -23646,7 +25040,7 @@ async function runTui(args) {
|
|
|
23646
25040
|
process.stdout.write("\x1B[?1049h");
|
|
23647
25041
|
}
|
|
23648
25042
|
const instance = render2(
|
|
23649
|
-
/* @__PURE__ */
|
|
25043
|
+
/* @__PURE__ */ jsx19(
|
|
23650
25044
|
App_default,
|
|
23651
25045
|
{
|
|
23652
25046
|
mcpServers,
|