@modelcontextprotocol/inspector 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as reactExports, j as jsxRuntimeExports, S as SESSION_KEYS, h as handleOAuthCallback } from "./index-
|
|
1
|
+
import { r as reactExports, j as jsxRuntimeExports, S as SESSION_KEYS, h as handleOAuthCallback } from "./index-DVugRvpa.js";
|
|
2
2
|
const OAuthCallback = () => {
|
|
3
3
|
const hasProcessedRef = reactExports.useRef(false);
|
|
4
4
|
reactExports.useEffect(() => {
|
|
@@ -16,8 +16,14 @@ const OAuthCallback = () => {
|
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
18
|
try {
|
|
19
|
-
const
|
|
20
|
-
sessionStorage.setItem(SESSION_KEYS.ACCESS_TOKEN,
|
|
19
|
+
const tokens = await handleOAuthCallback(serverUrl, code);
|
|
20
|
+
sessionStorage.setItem(SESSION_KEYS.ACCESS_TOKEN, tokens.access_token);
|
|
21
|
+
if (tokens.refresh_token) {
|
|
22
|
+
sessionStorage.setItem(
|
|
23
|
+
SESSION_KEYS.REFRESH_TOKEN,
|
|
24
|
+
tokens.refresh_token
|
|
25
|
+
);
|
|
26
|
+
}
|
|
21
27
|
window.location.href = `/?serverUrl=${encodeURIComponent(serverUrl)}`;
|
|
22
28
|
} catch (error) {
|
|
23
29
|
console.error("OAuth callback error:", error);
|
|
@@ -11230,16 +11230,32 @@ ZodReadonly.create = (type, params2) => {
|
|
|
11230
11230
|
...processCreateParams(params2)
|
|
11231
11231
|
});
|
|
11232
11232
|
};
|
|
11233
|
-
function
|
|
11233
|
+
function cleanParams(params2, data) {
|
|
11234
|
+
const p2 = typeof params2 === "function" ? params2(data) : typeof params2 === "string" ? { message: params2 } : params2;
|
|
11235
|
+
const p22 = typeof p2 === "string" ? { message: p2 } : p2;
|
|
11236
|
+
return p22;
|
|
11237
|
+
}
|
|
11238
|
+
function custom(check, _params = {}, fatal) {
|
|
11234
11239
|
if (check)
|
|
11235
11240
|
return ZodAny.create().superRefine((data, ctx) => {
|
|
11236
11241
|
var _a, _b;
|
|
11237
|
-
|
|
11238
|
-
|
|
11239
|
-
|
|
11240
|
-
|
|
11241
|
-
|
|
11242
|
+
const r2 = check(data);
|
|
11243
|
+
if (r2 instanceof Promise) {
|
|
11244
|
+
return r2.then((r3) => {
|
|
11245
|
+
var _a2, _b2;
|
|
11246
|
+
if (!r3) {
|
|
11247
|
+
const params2 = cleanParams(_params, data);
|
|
11248
|
+
const _fatal = (_b2 = (_a2 = params2.fatal) !== null && _a2 !== void 0 ? _a2 : fatal) !== null && _b2 !== void 0 ? _b2 : true;
|
|
11249
|
+
ctx.addIssue({ code: "custom", ...params2, fatal: _fatal });
|
|
11250
|
+
}
|
|
11251
|
+
});
|
|
11242
11252
|
}
|
|
11253
|
+
if (!r2) {
|
|
11254
|
+
const params2 = cleanParams(_params, data);
|
|
11255
|
+
const _fatal = (_b = (_a = params2.fatal) !== null && _a !== void 0 ? _a : fatal) !== null && _b !== void 0 ? _b : true;
|
|
11256
|
+
ctx.addIssue({ code: "custom", ...params2, fatal: _fatal });
|
|
11257
|
+
}
|
|
11258
|
+
return;
|
|
11243
11259
|
});
|
|
11244
11260
|
return ZodAny.create();
|
|
11245
11261
|
}
|
|
@@ -13118,27 +13134,39 @@ async function pkceChallenge(length) {
|
|
|
13118
13134
|
const SESSION_KEYS = {
|
|
13119
13135
|
CODE_VERIFIER: "mcp_code_verifier",
|
|
13120
13136
|
SERVER_URL: "mcp_server_url",
|
|
13121
|
-
ACCESS_TOKEN: "mcp_access_token"
|
|
13137
|
+
ACCESS_TOKEN: "mcp_access_token",
|
|
13138
|
+
REFRESH_TOKEN: "mcp_refresh_token"
|
|
13122
13139
|
};
|
|
13140
|
+
const OAuthMetadataSchema = z.object({
|
|
13141
|
+
authorization_endpoint: z.string(),
|
|
13142
|
+
token_endpoint: z.string()
|
|
13143
|
+
});
|
|
13144
|
+
const OAuthTokensSchema = z.object({
|
|
13145
|
+
access_token: z.string(),
|
|
13146
|
+
refresh_token: z.string().optional(),
|
|
13147
|
+
expires_in: z.number().optional()
|
|
13148
|
+
});
|
|
13123
13149
|
async function discoverOAuthMetadata(serverUrl) {
|
|
13124
13150
|
try {
|
|
13125
13151
|
const url = new URL("/.well-known/oauth-authorization-server", serverUrl);
|
|
13126
13152
|
const response = await fetch(url.toString());
|
|
13127
13153
|
if (response.ok) {
|
|
13128
13154
|
const metadata = await response.json();
|
|
13129
|
-
|
|
13155
|
+
const validatedMetadata = OAuthMetadataSchema.parse({
|
|
13130
13156
|
authorization_endpoint: metadata.authorization_endpoint,
|
|
13131
13157
|
token_endpoint: metadata.token_endpoint
|
|
13132
|
-
};
|
|
13158
|
+
});
|
|
13159
|
+
return validatedMetadata;
|
|
13133
13160
|
}
|
|
13134
13161
|
} catch (error) {
|
|
13135
13162
|
console.warn("OAuth metadata discovery failed:", error);
|
|
13136
13163
|
}
|
|
13137
13164
|
const baseUrl = new URL(serverUrl);
|
|
13138
|
-
|
|
13165
|
+
const defaultMetadata = {
|
|
13139
13166
|
authorization_endpoint: new URL("/authorize", baseUrl).toString(),
|
|
13140
13167
|
token_endpoint: new URL("/token", baseUrl).toString()
|
|
13141
13168
|
};
|
|
13169
|
+
return OAuthMetadataSchema.parse(defaultMetadata);
|
|
13142
13170
|
}
|
|
13143
13171
|
async function startOAuthFlow(serverUrl) {
|
|
13144
13172
|
const challenge = await pkceChallenge();
|
|
@@ -13177,8 +13205,30 @@ async function handleOAuthCallback(serverUrl, code) {
|
|
|
13177
13205
|
if (!response.ok) {
|
|
13178
13206
|
throw new Error("Token exchange failed");
|
|
13179
13207
|
}
|
|
13180
|
-
const
|
|
13181
|
-
return
|
|
13208
|
+
const tokens = await response.json();
|
|
13209
|
+
return OAuthTokensSchema.parse(tokens);
|
|
13210
|
+
}
|
|
13211
|
+
async function refreshAccessToken(serverUrl) {
|
|
13212
|
+
const refreshToken = sessionStorage.getItem(SESSION_KEYS.REFRESH_TOKEN);
|
|
13213
|
+
if (!refreshToken) {
|
|
13214
|
+
throw new Error("No refresh token available");
|
|
13215
|
+
}
|
|
13216
|
+
const metadata = await discoverOAuthMetadata(serverUrl);
|
|
13217
|
+
const response = await fetch(metadata.token_endpoint, {
|
|
13218
|
+
method: "POST",
|
|
13219
|
+
headers: {
|
|
13220
|
+
"Content-Type": "application/json"
|
|
13221
|
+
},
|
|
13222
|
+
body: JSON.stringify({
|
|
13223
|
+
grant_type: "refresh_token",
|
|
13224
|
+
refresh_token: refreshToken
|
|
13225
|
+
})
|
|
13226
|
+
});
|
|
13227
|
+
if (!response.ok) {
|
|
13228
|
+
throw new Error("Token refresh failed");
|
|
13229
|
+
}
|
|
13230
|
+
const tokens = await response.json();
|
|
13231
|
+
return OAuthTokensSchema.parse(tokens);
|
|
13182
13232
|
}
|
|
13183
13233
|
const StdErrNotificationSchema = NotificationSchema.extend({
|
|
13184
13234
|
method: z.literal("notifications/stderr"),
|
|
@@ -13257,7 +13307,46 @@ function useConnection({
|
|
|
13257
13307
|
throw e;
|
|
13258
13308
|
}
|
|
13259
13309
|
};
|
|
13260
|
-
const
|
|
13310
|
+
const initiateOAuthFlow = async () => {
|
|
13311
|
+
sessionStorage.removeItem(SESSION_KEYS.ACCESS_TOKEN);
|
|
13312
|
+
sessionStorage.removeItem(SESSION_KEYS.REFRESH_TOKEN);
|
|
13313
|
+
sessionStorage.setItem(SESSION_KEYS.SERVER_URL, sseUrl);
|
|
13314
|
+
const redirectUrl = await startOAuthFlow(sseUrl);
|
|
13315
|
+
window.location.href = redirectUrl;
|
|
13316
|
+
};
|
|
13317
|
+
const handleTokenRefresh = async () => {
|
|
13318
|
+
try {
|
|
13319
|
+
const tokens = await refreshAccessToken(sseUrl);
|
|
13320
|
+
sessionStorage.setItem(SESSION_KEYS.ACCESS_TOKEN, tokens.access_token);
|
|
13321
|
+
if (tokens.refresh_token) {
|
|
13322
|
+
sessionStorage.setItem(
|
|
13323
|
+
SESSION_KEYS.REFRESH_TOKEN,
|
|
13324
|
+
tokens.refresh_token
|
|
13325
|
+
);
|
|
13326
|
+
}
|
|
13327
|
+
return tokens.access_token;
|
|
13328
|
+
} catch (error) {
|
|
13329
|
+
console.error("Token refresh failed:", error);
|
|
13330
|
+
await initiateOAuthFlow();
|
|
13331
|
+
throw error;
|
|
13332
|
+
}
|
|
13333
|
+
};
|
|
13334
|
+
const handleAuthError = async (error) => {
|
|
13335
|
+
if (error instanceof SseError && error.code === 401) {
|
|
13336
|
+
if (sessionStorage.getItem(SESSION_KEYS.REFRESH_TOKEN)) {
|
|
13337
|
+
try {
|
|
13338
|
+
await handleTokenRefresh();
|
|
13339
|
+
return true;
|
|
13340
|
+
} catch (error2) {
|
|
13341
|
+
console.error("Token refresh failed:", error2);
|
|
13342
|
+
}
|
|
13343
|
+
} else {
|
|
13344
|
+
await initiateOAuthFlow();
|
|
13345
|
+
}
|
|
13346
|
+
}
|
|
13347
|
+
return false;
|
|
13348
|
+
};
|
|
13349
|
+
const connect = async (_e, retryCount = 0) => {
|
|
13261
13350
|
try {
|
|
13262
13351
|
const client = new Client(
|
|
13263
13352
|
{
|
|
@@ -13311,10 +13400,11 @@ function useConnection({
|
|
|
13311
13400
|
await client.connect(clientTransport);
|
|
13312
13401
|
} catch (error) {
|
|
13313
13402
|
console.error("Failed to connect to MCP server:", error);
|
|
13403
|
+
const shouldRetry = await handleAuthError(error);
|
|
13404
|
+
if (shouldRetry) {
|
|
13405
|
+
return connect(void 0, retryCount + 1);
|
|
13406
|
+
}
|
|
13314
13407
|
if (error instanceof SseError && error.code === 401) {
|
|
13315
|
-
sessionStorage.setItem(SESSION_KEYS.SERVER_URL, sseUrl);
|
|
13316
|
-
const redirectUrl = await startOAuthFlow(sseUrl);
|
|
13317
|
-
window.location.href = redirectUrl;
|
|
13318
13408
|
return;
|
|
13319
13409
|
}
|
|
13320
13410
|
throw error;
|
|
@@ -13520,11 +13610,11 @@ var SlotClone = reactExports.forwardRef((props, forwardedRef) => {
|
|
|
13520
13610
|
const { children, ...slotProps } = props;
|
|
13521
13611
|
if (reactExports.isValidElement(children)) {
|
|
13522
13612
|
const childrenRef = getElementRef$1(children);
|
|
13523
|
-
|
|
13524
|
-
|
|
13525
|
-
|
|
13526
|
-
|
|
13527
|
-
|
|
13613
|
+
const props2 = mergeProps(slotProps, children.props);
|
|
13614
|
+
if (children.type !== reactExports.Fragment) {
|
|
13615
|
+
props2.ref = forwardedRef ? composeRefs(forwardedRef, childrenRef) : childrenRef;
|
|
13616
|
+
}
|
|
13617
|
+
return reactExports.cloneElement(children, props2);
|
|
13528
13618
|
}
|
|
13529
13619
|
return reactExports.Children.count(children) > 1 ? reactExports.Children.only(null) : null;
|
|
13530
13620
|
});
|
|
@@ -22560,7 +22650,7 @@ const useTheme = () => {
|
|
|
22560
22650
|
}, [])
|
|
22561
22651
|
];
|
|
22562
22652
|
};
|
|
22563
|
-
const version = "0.4.
|
|
22653
|
+
const version = "0.4.1";
|
|
22564
22654
|
const Sidebar = ({
|
|
22565
22655
|
connectionStatus,
|
|
22566
22656
|
transportType,
|
|
@@ -23012,7 +23102,7 @@ const PROXY_SERVER_URL = `http://localhost:${PROXY_PORT}`;
|
|
|
23012
23102
|
const App = () => {
|
|
23013
23103
|
if (window.location.pathname === "/oauth/callback") {
|
|
23014
23104
|
const OAuthCallback = React.lazy(
|
|
23015
|
-
() => __vitePreload(() => import("./OAuthCallback-
|
|
23105
|
+
() => __vitePreload(() => import("./OAuthCallback-DCSQTqKf.js"), true ? [] : void 0)
|
|
23016
23106
|
);
|
|
23017
23107
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthCallback, {}) });
|
|
23018
23108
|
}
|
package/client/dist/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/mcp.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>MCP Inspector</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-DVugRvpa.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-eOhPEcGC.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modelcontextprotocol/inspector",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Model Context Protocol inspector",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Anthropic, PBC (https://anthropic.com)",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"publish-all": "npm publish --workspaces --access public && npm publish --access public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@modelcontextprotocol/inspector-client": "0.
|
|
37
|
-
"@modelcontextprotocol/inspector-server": "0.
|
|
36
|
+
"@modelcontextprotocol/inspector-client": "0.4.1",
|
|
37
|
+
"@modelcontextprotocol/inspector-server": "0.4.1",
|
|
38
38
|
"concurrently": "^9.0.1",
|
|
39
39
|
"shell-quote": "^1.8.2",
|
|
40
40
|
"spawn-rx": "^5.1.0",
|
package/server/build/index.js
CHANGED
|
@@ -145,4 +145,15 @@ app.get("/config", (req, res) => {
|
|
|
145
145
|
}
|
|
146
146
|
});
|
|
147
147
|
const PORT = process.env.PORT || 3000;
|
|
148
|
-
|
|
148
|
+
try {
|
|
149
|
+
const server = app.listen(PORT);
|
|
150
|
+
server.on("listening", () => {
|
|
151
|
+
const addr = server.address();
|
|
152
|
+
const port = typeof addr === "string" ? addr : addr?.port;
|
|
153
|
+
console.log(`Proxy server listening on port ${port}`);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
console.error("Failed to start server:", error);
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|