@aexol/spectral 0.9.254 → 0.9.255
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/dist/extensions/dataset-uploader/analyzer.d.ts +103 -0
- package/dist/extensions/dataset-uploader/analyzer.d.ts.map +1 -0
- package/dist/extensions/dataset-uploader/analyzer.js +266 -0
- package/dist/extensions/dataset-uploader/cleaner.d.ts +59 -0
- package/dist/extensions/dataset-uploader/cleaner.d.ts.map +1 -0
- package/dist/extensions/dataset-uploader/cleaner.js +118 -0
- package/dist/extensions/dataset-uploader/exporter.d.ts +147 -0
- package/dist/extensions/dataset-uploader/exporter.d.ts.map +1 -0
- package/dist/extensions/dataset-uploader/exporter.js +313 -0
- package/dist/extensions/dataset-uploader/extra-values.d.ts +17 -0
- package/dist/extensions/dataset-uploader/extra-values.d.ts.map +1 -0
- package/dist/extensions/dataset-uploader/extra-values.js +51 -0
- package/dist/extensions/dataset-uploader/index.d.ts +22 -0
- package/dist/extensions/dataset-uploader/index.d.ts.map +1 -0
- package/dist/extensions/dataset-uploader/index.js +247 -0
- package/dist/extensions/dataset-uploader/scrubber.d.ts +34 -0
- package/dist/extensions/dataset-uploader/scrubber.d.ts.map +1 -0
- package/dist/extensions/dataset-uploader/scrubber.js +91 -0
- package/dist/extensions/dataset-uploader/upload.d.ts +105 -0
- package/dist/extensions/dataset-uploader/upload.d.ts.map +1 -0
- package/dist/extensions/dataset-uploader/upload.js +274 -0
- package/dist/generated/zeus/const.d.ts.map +1 -1
- package/dist/generated/zeus/const.js +32 -0
- package/dist/generated/zeus/index.d.ts +166 -0
- package/dist/generated/zeus/index.d.ts.map +1 -1
- package/dist/mcp/commands.d.ts.map +1 -1
- package/dist/mcp/commands.js +3 -0
- package/dist/mcp/direct-tools.d.ts.map +1 -1
- package/dist/mcp/direct-tools.js +4 -3
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +5 -1
- package/dist/mcp/mcp-auth-flow.d.ts +1 -1
- package/dist/mcp/mcp-auth-flow.d.ts.map +1 -1
- package/dist/mcp/mcp-auth-flow.js +13 -0
- package/dist/mcp/mcp-auth-start.d.ts +64 -0
- package/dist/mcp/mcp-auth-start.d.ts.map +1 -0
- package/dist/mcp/mcp-auth-start.js +136 -0
- package/dist/mcp/proxy-modes.d.ts +7 -0
- package/dist/mcp/proxy-modes.d.ts.map +1 -1
- package/dist/mcp/proxy-modes.js +71 -11
- package/dist/mcp/server-manager.d.ts +2 -1
- package/dist/mcp/server-manager.d.ts.map +1 -1
- package/dist/mcp/server-manager.js +8 -4
- package/dist/sdk/coding-agent/core/extensions/native-extensions.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/extensions/native-extensions.js +10 -0
- package/dist/server/handlers/mcp-auth.d.ts +7 -4
- package/dist/server/handlers/mcp-auth.d.ts.map +1 -1
- package/dist/server/handlers/mcp-auth.js +15 -80
- package/package.json +1 -1
|
@@ -2,46 +2,19 @@
|
|
|
2
2
|
* Handler for `POST /api/mcp-auth`.
|
|
3
3
|
*
|
|
4
4
|
* Starts the OAuth flow for a locally configured MCP server managed by
|
|
5
|
-
* `spectral serve`.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* background once the local callback server
|
|
5
|
+
* `spectral serve`. Delegates to the shared non-blocking helper
|
|
6
|
+
* (`startMcpAuthFlow`) used by the agent `mcp` tool: `startAuth` captures
|
|
7
|
+
* the authorization URL through the provider's `onRedirect` hook, and the
|
|
8
|
+
* flow is completed in the background once the local callback server
|
|
9
|
+
* receives the code. `openBrowser: true` in the body launches the system
|
|
10
|
+
* browser (default: headless — the caller renders `authUrl`).
|
|
9
11
|
*
|
|
10
12
|
* Pure handler pattern — no framework, no side effects on the wire. The
|
|
11
13
|
* caller (the relay dispatcher) injects `McpExtensionState`; validation
|
|
12
14
|
* failures throw `BadRequestError` which `relay/rest.ts` maps to 400.
|
|
13
15
|
*/
|
|
14
|
-
import {
|
|
15
|
-
import { completeAuth, startAuth, supportsOAuth, } from "../../mcp/mcp-auth-flow.js";
|
|
16
|
-
import { clearOAuthState } from "../../mcp/mcp-auth.js";
|
|
17
|
-
import { reloadMcpConfig } from "../../mcp/init.js";
|
|
16
|
+
import { McpAuthStartError, startMcpAuthFlow, } from "../../mcp/mcp-auth-start.js";
|
|
18
17
|
import { BadRequestError } from "./errors.js";
|
|
19
|
-
/**
|
|
20
|
-
* Per-server in-flight guard. `startAuth` keys its pending transports and
|
|
21
|
-
* persisted OAuth state by server name, so two concurrent flows for the same
|
|
22
|
-
* server would clobber each other (the headless handler bypasses the
|
|
23
|
-
* `authenticate()` dedupe). Reject the second POST until the first
|
|
24
|
-
* flow's background chain finishes.
|
|
25
|
-
*/
|
|
26
|
-
const inFlightMcpAuths = new Set();
|
|
27
|
-
/**
|
|
28
|
-
* An authorization URL is about to be opened in the user's browser, so it
|
|
29
|
-
* must never be a `javascript:` / `data:` / malformed URL coming from a
|
|
30
|
-
* malicious MCP server's OAuth metadata. Defense in depth: the landing UI
|
|
31
|
-
* applies the same check before `window.open`.
|
|
32
|
-
*/
|
|
33
|
-
function assertSafeAuthorizationUrl(authUrl) {
|
|
34
|
-
let parsed;
|
|
35
|
-
try {
|
|
36
|
-
parsed = new URL(authUrl);
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
throw new BadRequestError("Invalid authorization URL");
|
|
40
|
-
}
|
|
41
|
-
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
42
|
-
throw new BadRequestError("Invalid authorization URL");
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
18
|
export async function handleStartMcpAuth(state, body) {
|
|
46
19
|
if (!state) {
|
|
47
20
|
throw new BadRequestError("MCP adapter not loaded");
|
|
@@ -50,57 +23,19 @@ export async function handleStartMcpAuth(state, body) {
|
|
|
50
23
|
if (typeof name !== "string" || name.length === 0) {
|
|
51
24
|
throw new BadRequestError("name is required");
|
|
52
25
|
}
|
|
53
|
-
const definition = state.config.mcpServers[name];
|
|
54
|
-
if (!definition) {
|
|
55
|
-
throw new BadRequestError(`Unknown MCP server: ${name}`);
|
|
56
|
-
}
|
|
57
|
-
if (!definition.url || !supportsOAuth(definition)) {
|
|
58
|
-
throw new BadRequestError(`MCP server "${name}" does not support OAuth`);
|
|
59
|
-
}
|
|
60
|
-
if (inFlightMcpAuths.has(name)) {
|
|
61
|
-
throw new BadRequestError("OAuth authentication already in progress for this server");
|
|
62
|
-
}
|
|
63
|
-
inFlightMcpAuths.add(name);
|
|
64
|
-
let authorizationUrl;
|
|
65
|
-
let oauthState;
|
|
66
26
|
try {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
27
|
+
const result = await startMcpAuthFlow(state, name, {
|
|
28
|
+
openBrowser: body?.openBrowser === true,
|
|
29
|
+
});
|
|
30
|
+
if (result.status === "already-authenticated") {
|
|
70
31
|
return { status: "already-authenticated" };
|
|
71
32
|
}
|
|
72
|
-
|
|
73
|
-
// its persisted state could never be completed nor cleanly aborted.
|
|
74
|
-
if (!oauthState) {
|
|
75
|
-
throw new BadRequestError("OAuth state missing after authorization start");
|
|
76
|
-
}
|
|
77
|
-
assertSafeAuthorizationUrl(authorizationUrl);
|
|
33
|
+
return { status: "auth_url_ready", authUrl: result.authUrl };
|
|
78
34
|
}
|
|
79
35
|
catch (error) {
|
|
80
|
-
|
|
81
|
-
|
|
36
|
+
if (error instanceof McpAuthStartError) {
|
|
37
|
+
throw new BadRequestError(error.message);
|
|
38
|
+
}
|
|
82
39
|
throw error;
|
|
83
40
|
}
|
|
84
|
-
// Complete the flow in the background from the local callback server:
|
|
85
|
-
// waitForCallback resolves with the authorization code, completeAuth
|
|
86
|
-
// exchanges it for tokens, and the MCP config is reloaded so the server
|
|
87
|
-
// comes up authenticated. Fire-and-forget — the response already carries
|
|
88
|
-
// the authUrl and auth progress is observable via GET /api/mcp-status,
|
|
89
|
-
// so failures are swallowed. The finally block releases the per-server
|
|
90
|
-
// in-flight guard and clears the now-stale OAuth state (idempotent) on
|
|
91
|
-
// every path.
|
|
92
|
-
waitForCallback(oauthState)
|
|
93
|
-
.then((code) => completeAuth(name, code))
|
|
94
|
-
.then(() => reloadMcpConfig(state))
|
|
95
|
-
.catch(() => { })
|
|
96
|
-
.finally(() => {
|
|
97
|
-
inFlightMcpAuths.delete(name);
|
|
98
|
-
try {
|
|
99
|
-
clearOAuthState(name);
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
// Storage errors must not surface as unhandled rejections.
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
return { status: "auth_url_ready", authUrl: authorizationUrl };
|
|
106
41
|
}
|