@mcpjam/inspector 3.12.3 → 3.12.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -21
- package/bin/access-link.mjs +53 -0
- package/bin/start.js +47 -14
- package/dist/client/assets/OAuthDesktopReturnNotice-B_x9xTE-.css +2 -0
- package/dist/client/assets/OAuthDesktopReturnNotice-LlC451lX.js +11 -0
- package/dist/client/assets/{app-bootstrap-C1Jn01kP.js → app-bootstrap-2jatN7gw.js} +376 -374
- package/dist/client/assets/{button-RD2Dghjp.js → button-B2OH2ei2.js} +2 -2
- package/dist/client/assets/{chunk-YOKDWASO-DTTU1wSE.js → chunk-YOKDWASO-uJ3KOQV7.js} +5 -5
- package/dist/client/assets/{dead-clicks-autocapture-CDkbT21a.js → dead-clicks-autocapture-D055GjVp.js} +2 -2
- package/dist/client/assets/{error-reporting-Dg5b1JwS.js → error-reporting-DGP36KLx.js} +57 -57
- package/dist/client/assets/{error-reporting-_SEhX6IL.js → error-reporting-FWZKbZxG.js} +1 -1
- package/dist/client/assets/{exception-autocapture-CtxHwPtn.js → exception-autocapture-103gdJjL.js} +2 -2
- package/dist/client/assets/{failed-request-tracker-kUaJ-sVM.js → failed-request-tracker-Cp9_VFMm.js} +2 -2
- package/dist/client/assets/{highlighted-body-KPVGNVTW-CBC2hHHb.js → highlighted-body-KPVGNVTW-Dx70h1nm.js} +2 -2
- package/dist/client/assets/index-rskHnM3O.js +4 -0
- package/dist/client/assets/{jszip.min-B3Qii_az.js → jszip.min-CwJyI5tb.js} +2 -2
- package/dist/client/assets/{mermaid-HWGCJPDP-BzT3-9sO.js → mermaid-HWGCJPDP-Ck3prJKl.js} +1 -1
- package/dist/client/assets/{posthog-recorder-B06ULcLl.js → posthog-recorder-tKuMFijV.js} +2 -2
- package/dist/client/assets/{preload-helper-DvWwGI6x.js → preload-helper-DrcoTQ49.js} +2 -2
- package/dist/client/assets/{rolldown-runtime-DVMSi0Yr.js → rolldown-runtime-7FnpGOz6.js} +1 -1
- package/dist/client/assets/{surveys-D941hgn3.js → surveys-BsZYxM6N.js} +2 -2
- package/dist/client/assets/{trace-timeline-Bk3hAXNq.js → trace-timeline-BOZvHcOG.js} +1 -1
- package/dist/client/assets/{trace-timeline-DVZqlQSW.js → trace-timeline-Bf9Oai70.js} +8 -8
- package/dist/client/assets/{web-vitals-DZUBt4dL.js → web-vitals-DdzaVN3H.js} +2 -2
- package/dist/client/index.html +7 -7
- package/dist/server/chunk-3EDQFXTF.js +4801 -0
- package/dist/server/{chunk-5RE7KJ2M.js → chunk-4PYR7GMQ.js} +16 -197
- package/dist/server/{chunk-WGJHSGJP.js → chunk-QA6VJT6A.js} +961 -963
- package/dist/server/chunk-SH24KJBI.js +194 -0
- package/dist/server/{consent-lifetime-PTGAZQSU.js → consent-lifetime-M7PS6RUU.js} +3 -2
- package/dist/server/harness-install-cli.js +1 -1
- package/dist/server/index.js +15110 -16012
- package/dist/server/local-turn-XXOSZHMT.js +12 -0
- package/package.json +14 -11
- package/dist/client/assets/OAuthDesktopReturnNotice-C5D90OSm.js +0 -11
- package/dist/client/assets/OAuthDesktopReturnNotice-C95FI7VH.css +0 -2
- package/dist/client/assets/index-yOjxp36p.js +0 -4
package/README.md
CHANGED
|
@@ -78,32 +78,40 @@ Network access requires **Docker**. A native (`npx`) install binds to
|
|
|
78
78
|
`127.0.0.1` (localhost only) and has no bind-address override, so it is not
|
|
79
79
|
reachable from another machine. The Docker image binds `0.0.0.0`, so it is.
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
81
|
+
Open the private link printed in the terminal (or `docker logs <container>`) to
|
|
82
|
+
sign this browser in. A plain address displays instructions to open that link.
|
|
83
|
+
The browser remembers access for this origin until the Inspector restarts.
|
|
84
|
+
Keep the link private: it grants control of the local Inspector and its tools.
|
|
85
|
+
|
|
86
|
+
For another computer, set `MCPJAM_ALLOWED_HOSTS` to the hostname or IP you use,
|
|
87
|
+
and publish the port on your network interface (this exposes the port on all interfaces):
|
|
87
88
|
|
|
88
89
|
```bash
|
|
89
90
|
docker run -p 6274:6274 -e MCPJAM_ALLOWED_HOSTS=192.168.1.50 mcpjam/mcp-inspector:local
|
|
90
91
|
```
|
|
91
92
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
`
|
|
106
|
-
|
|
93
|
+
Alternatively, keep the remote port bound to loopback and use
|
|
94
|
+
`ssh -L 6274:127.0.0.1:6274 user@host`; open the terminal link at the forwarded address.
|
|
95
|
+
|
|
96
|
+
Open the printed Network link, or paste the link/code into the access screen at
|
|
97
|
+
that address. If ports are remapped, keep the `#token=…` fragment and change the
|
|
98
|
+
address. `MCPJAM_INSPECTOR_FRONTEND_URL=http://devbox.local:8080` sets the printed
|
|
99
|
+
browser address explicitly. Cross-tab continuation works only on the same origin.
|
|
100
|
+
|
|
101
|
+
For IPv6, bracket the allowlist entry: `MCPJAM_ALLOWED_HOSTS=[fd00::50]`.
|
|
102
|
+
Wildcards such as `*.lan` additionally require
|
|
103
|
+
`MCPJAM_ALLOW_WILDCARD_ORIGINS=true` for the request-origin check. The allowlist
|
|
104
|
+
never grants credentials by itself.
|
|
105
|
+
|
|
106
|
+
Optionally set `MCPJAM_SESSION_TOKEN` to a strong random URL-safe secret (at least
|
|
107
|
+
24 characters) to keep a link across restarts. Generate one with
|
|
108
|
+
`node -e "process.stdout.write(require('crypto').randomBytes(24).toString('base64url'))"`.
|
|
109
|
+
The default is a new random credential on each launch. Local CLI attachment reads
|
|
110
|
+
a same-user discovery file under `~/.mcpjam/inspector/`, readable only by its owner;
|
|
111
|
+
update `@mcpjam/cli` alongside the Inspector.
|
|
112
|
+
|
|
113
|
+
Set `MCPJAM_LOCAL_COMPUTER_ENABLED=false` and
|
|
114
|
+
`MCPJAM_LOCAL_BROWSER_ENABLED=false` to disable the local computer/browser tools.
|
|
107
115
|
|
|
108
116
|
# Key features
|
|
109
117
|
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
export function createLaunchToken(env = process.env) {
|
|
4
|
+
if (env.VITE_MCPJAM_HOSTED_MODE === "true") return undefined;
|
|
5
|
+
const token =
|
|
6
|
+
env.MCPJAM_SESSION_TOKEN ?? randomBytes(24).toString("base64url");
|
|
7
|
+
if (!/^[A-Za-z0-9_-]{24,}$/.test(token))
|
|
8
|
+
throw new Error(
|
|
9
|
+
"MCPJAM_SESSION_TOKEN must contain at least 24 URL-safe letters, digits, underscores or hyphens",
|
|
10
|
+
);
|
|
11
|
+
return token;
|
|
12
|
+
}
|
|
13
|
+
export function createAccessLink(base, token, tab) {
|
|
14
|
+
const url = new URL(base);
|
|
15
|
+
if (token)
|
|
16
|
+
url.hash = new URLSearchParams({
|
|
17
|
+
token,
|
|
18
|
+
...(tab ? { tab } : {}),
|
|
19
|
+
}).toString();
|
|
20
|
+
else if (tab) url.hash = tab;
|
|
21
|
+
return url.href;
|
|
22
|
+
}
|
|
23
|
+
export function networkAccessLinks(base, token, allowedHosts = "", tab) {
|
|
24
|
+
return allowedHosts
|
|
25
|
+
.split(",")
|
|
26
|
+
.map((host) => host.trim())
|
|
27
|
+
.filter((host) => host && !host.includes("*"))
|
|
28
|
+
.flatMap((host) => {
|
|
29
|
+
try {
|
|
30
|
+
// Configuration names hosts, not schemes, paths or credentials.
|
|
31
|
+
const authority = new URL(`http://${host}`);
|
|
32
|
+
if (
|
|
33
|
+
authority.username ||
|
|
34
|
+
authority.password ||
|
|
35
|
+
authority.pathname !== "/" ||
|
|
36
|
+
authority.search ||
|
|
37
|
+
authority.hash
|
|
38
|
+
)
|
|
39
|
+
return [];
|
|
40
|
+
const url = new URL(base);
|
|
41
|
+
url.hostname = authority.hostname;
|
|
42
|
+
if (authority.port) url.port = authority.port;
|
|
43
|
+
return [createAccessLink(url.href, token, tab)];
|
|
44
|
+
} catch {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** CLI-owned launches open their own link; redirected launcher logs stay credential-free. */
|
|
51
|
+
export function shouldPrintAccessLink(token, env = process.env) {
|
|
52
|
+
return Boolean(token) && env.MCPJAM_INSPECTOR_SUPPRESS_AUTO_OPEN !== "1";
|
|
53
|
+
}
|
package/bin/start.js
CHANGED
|
@@ -7,6 +7,12 @@ import { createServer, createConnection } from "net";
|
|
|
7
7
|
import { execSync } from "child_process";
|
|
8
8
|
import { existsSync, readFileSync } from "fs";
|
|
9
9
|
import open from "open";
|
|
10
|
+
import {
|
|
11
|
+
createLaunchToken,
|
|
12
|
+
shouldPrintAccessLink,
|
|
13
|
+
createAccessLink,
|
|
14
|
+
networkAccessLinks,
|
|
15
|
+
} from "./access-link.mjs";
|
|
10
16
|
import { launchWorkspaceCandidate } from "./launch-workspace.mjs";
|
|
11
17
|
|
|
12
18
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -1003,13 +1009,17 @@ async function main() {
|
|
|
1003
1009
|
// to become the installed package's root and the server would otherwise
|
|
1004
1010
|
// have no way back to where the user actually was.
|
|
1005
1011
|
const launchWorkspace = launchWorkspaceCandidate({ projectRoot });
|
|
1012
|
+
const launchToken = createLaunchToken();
|
|
1006
1013
|
const serverProcess = spawn("node", [distServerPath], {
|
|
1007
1014
|
env: {
|
|
1008
1015
|
...process.env,
|
|
1016
|
+
...(launchToken ? { MCPJAM_SESSION_TOKEN: launchToken } : {}),
|
|
1009
1017
|
MCPJAM_INSPECTOR_PARENT_PID: process.pid.toString(),
|
|
1010
1018
|
NODE_ENV: "production",
|
|
1011
1019
|
PORT: PORT,
|
|
1012
|
-
...(launchWorkspace
|
|
1020
|
+
...(launchWorkspace
|
|
1021
|
+
? { MCPJAM_LAUNCH_WORKSPACE: launchWorkspace }
|
|
1022
|
+
: {}),
|
|
1013
1023
|
...(verboseLogs && { VERBOSE_LOGS: "true" }),
|
|
1014
1024
|
},
|
|
1015
1025
|
cwd: projectRoot,
|
|
@@ -1095,21 +1105,44 @@ async function main() {
|
|
|
1095
1105
|
logWarning(
|
|
1096
1106
|
`Server did not become ready within 30s. Please visit ${apiBaseUrl} manually.`,
|
|
1097
1107
|
);
|
|
1098
|
-
} else if (!cancelled
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1108
|
+
} else if (!cancelled) {
|
|
1109
|
+
const base = await resolveBrowserBaseUrl(apiBaseUrl);
|
|
1110
|
+
const url = createAccessLink(base, launchToken, initialTab);
|
|
1111
|
+
const docker = process.env.DOCKER_CONTAINER === "true";
|
|
1112
|
+
let opened = false;
|
|
1113
|
+
if (openBrowser && !docker) {
|
|
1114
|
+
try {
|
|
1115
|
+
await open(url);
|
|
1116
|
+
opened = true;
|
|
1117
|
+
} catch {
|
|
1118
|
+
logWarning("Could not open your browser automatically.");
|
|
1119
|
+
}
|
|
1104
1120
|
}
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1121
|
+
if (shouldPrintAccessLink(launchToken)) {
|
|
1122
|
+
logSuccess("MCPJam Inspector is ready");
|
|
1123
|
+
log("");
|
|
1124
|
+
const printLink = (label, link) => {
|
|
1125
|
+
log(` ${colors.green}➜ ${colors.bright}${label}${colors.reset}`);
|
|
1126
|
+
log(link, colors.primary);
|
|
1127
|
+
};
|
|
1128
|
+
printLink(docker ? "Open MCPJam" : "Local", url);
|
|
1129
|
+
for (const link of networkAccessLinks(
|
|
1130
|
+
base,
|
|
1131
|
+
launchToken,
|
|
1132
|
+
process.env.MCPJAM_ALLOWED_HOSTS,
|
|
1133
|
+
initialTab,
|
|
1134
|
+
))
|
|
1135
|
+
printLink("Network", link);
|
|
1136
|
+
log("");
|
|
1137
|
+
log(
|
|
1138
|
+
opened
|
|
1139
|
+
? "Opened in your browser. Keep this link private: it signs a browser in."
|
|
1140
|
+
: "Open this link in your browser. Keep it private: it signs a browser in.",
|
|
1112
1141
|
);
|
|
1142
|
+
if (docker)
|
|
1143
|
+
log(
|
|
1144
|
+
"Using another port or computer? Keep the #token=… part and change the address.",
|
|
1145
|
+
);
|
|
1113
1146
|
}
|
|
1114
1147
|
}
|
|
1115
1148
|
}
|