@superblocksteam/gateway 2.0.178-next.2 → 2.0.179-next.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/README.md +4 -1
- package/dist/auth/cli-session.d.ts +24 -0
- package/dist/auth/cli-session.d.ts.map +1 -0
- package/dist/auth/cli-session.js +46 -0
- package/dist/auth/cli-session.js.map +1 -0
- package/dist/auth/index.d.ts +4 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +4 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/login.d.ts +18 -0
- package/dist/auth/login.d.ts.map +1 -0
- package/dist/auth/login.js +124 -0
- package/dist/auth/login.js.map +1 -0
- package/dist/auth/mcp-oauth-session.d.ts +46 -0
- package/dist/auth/mcp-oauth-session.d.ts.map +1 -0
- package/dist/auth/mcp-oauth-session.js +247 -0
- package/dist/auth/mcp-oauth-session.js.map +1 -0
- package/dist/auth/mcp-server-selection.d.ts +42 -0
- package/dist/auth/mcp-server-selection.d.ts.map +1 -0
- package/dist/auth/mcp-server-selection.js +179 -0
- package/dist/auth/mcp-server-selection.js.map +1 -0
- package/dist/auth/native-oauth.d.ts +33 -0
- package/dist/auth/native-oauth.d.ts.map +1 -0
- package/dist/auth/native-oauth.js +181 -0
- package/dist/auth/native-oauth.js.map +1 -0
- package/dist/capabilities/branching.d.ts +139 -0
- package/dist/capabilities/branching.d.ts.map +1 -0
- package/dist/capabilities/branching.js +540 -0
- package/dist/capabilities/branching.js.map +1 -0
- package/dist/capabilities/lifecycle.d.ts +19 -0
- package/dist/capabilities/lifecycle.d.ts.map +1 -1
- package/dist/capabilities/lifecycle.js +60 -2
- package/dist/capabilities/lifecycle.js.map +1 -1
- package/dist/capabilities/types.d.ts +2 -0
- package/dist/capabilities/types.d.ts.map +1 -1
- package/dist/capabilities/types.js.map +1 -1
- package/dist/main.js +21 -3
- package/dist/main.js.map +1 -1
- package/dist/sabs/editor-client-methods.d.ts.map +1 -1
- package/dist/sabs/editor-client-methods.js +11 -1
- package/dist/sabs/editor-client-methods.js.map +1 -1
- package/dist/server/client.d.ts +125 -4
- package/dist/server/client.d.ts.map +1 -1
- package/dist/server/client.js +55 -4
- package/dist/server/client.js.map +1 -1
- package/dist/stdio/index.d.ts +2 -0
- package/dist/stdio/index.d.ts.map +1 -0
- package/dist/stdio/index.js +2 -0
- package/dist/stdio/index.js.map +1 -0
- package/dist/stdio/serve.d.ts +56 -0
- package/dist/stdio/serve.d.ts.map +1 -0
- package/dist/stdio/serve.js +208 -0
- package/dist/stdio/serve.js.map +1 -0
- package/dist/transports/mcp/mount.d.ts.map +1 -1
- package/dist/transports/mcp/mount.js +204 -2
- package/dist/transports/mcp/mount.js.map +1 -1
- package/dist/transports/mcp/tool-names.d.ts +1 -1
- package/dist/transports/mcp/tool-names.d.ts.map +1 -1
- package/dist/transports/mcp/tool-permissions.d.ts +13 -0
- package/dist/transports/mcp/tool-permissions.d.ts.map +1 -1
- package/dist/transports/mcp/tool-permissions.js +14 -0
- package/dist/transports/mcp/tool-permissions.js.map +1 -1
- package/package.json +24 -7
package/README.md
CHANGED
|
@@ -9,7 +9,10 @@ Builder tools (`upload_artifact`, `start_app`, `edit_app`,
|
|
|
9
9
|
`get_preview_status`, `get_integration_metadata`, `publish_app`) plus customer
|
|
10
10
|
Admin tools from `@superblocksteam/mcp-server` share this process.
|
|
11
11
|
|
|
12
|
-
The MCP host owns process lifecycle: it spawns `superblocks mcp serve
|
|
12
|
+
The MCP host owns process lifecycle: it spawns `superblocks mcp serve`, or this
|
|
13
|
+
package's `superblocks-gateway` bin, which runs the same stdio entry without the
|
|
14
|
+
CLI. Pass `--browser-login` (or set `SUPERBLOCKS_MCP_BROWSER_LOGIN=true`) to
|
|
15
|
+
offer browser sign-in when no session is saved. The
|
|
13
16
|
unified Gateway has no foreground HTTP `/mcp`, no OAuth resource server, and no
|
|
14
17
|
linked-grant exchange. Browser login uses authorization code + PKCE to obtain
|
|
15
18
|
Server-audience access tokens. Personal API keys remain supported through
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type CliGatewayAuth = {
|
|
2
|
+
superblocksBaseUrl?: string;
|
|
3
|
+
token?: string;
|
|
4
|
+
};
|
|
5
|
+
export type CliGatewaySession = {
|
|
6
|
+
apiKey: string;
|
|
7
|
+
getAccessToken?: () => Promise<string>;
|
|
8
|
+
serverUrl: string;
|
|
9
|
+
sessionKey?: string;
|
|
10
|
+
};
|
|
11
|
+
export declare const NOT_LOGGED_IN_MESSAGE = "Not logged in to Superblocks. Run: superblocks mcp login (or superblocks login for a personal API key).";
|
|
12
|
+
/**
|
|
13
|
+
* Identity for unified MCP tools: the already-logged-in CLI user. Does not mint a
|
|
14
|
+
* second PAT or talk to a grant-exchange endpoint.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveCliGatewaySession(auth: CliGatewayAuth | undefined, env?: NodeJS.ProcessEnv): CliGatewaySession;
|
|
17
|
+
/**
|
|
18
|
+
* Point the Gateway process at the same control plane the CLI session uses,
|
|
19
|
+
* unless the operator already set SUPERBLOCKS_SERVER_URL. For a remote login
|
|
20
|
+
* (EE / SaaS) also default GATEWAY_BASE_URL so edit/preview URLs are not
|
|
21
|
+
* localhost:3000. A loopback session keeps the split local UI port.
|
|
22
|
+
*/
|
|
23
|
+
export declare function applyCliGatewaySessionToEnv(session: CliGatewaySession, env?: NodeJS.ProcessEnv): void;
|
|
24
|
+
//# sourceMappingURL=cli-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-session.d.ts","sourceRoot":"","sources":["../../src/auth/cli-session.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,qBAAqB,4GACyE,CAAC;AAE5G;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,cAAc,GAAG,SAAS,EAChC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,iBAAiB,CAUnB;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,iBAAiB,EAC1B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,IAAI,CAcN"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export const NOT_LOGGED_IN_MESSAGE = "Not logged in to Superblocks. Run: superblocks mcp login (or superblocks login for a personal API key).";
|
|
2
|
+
/**
|
|
3
|
+
* Identity for unified MCP tools: the already-logged-in CLI user. Does not mint a
|
|
4
|
+
* second PAT or talk to a grant-exchange endpoint.
|
|
5
|
+
*/
|
|
6
|
+
export function resolveCliGatewaySession(auth, env = process.env) {
|
|
7
|
+
const apiKey = env.SUPERBLOCKS_API_TOKEN?.trim() || auth?.token?.trim();
|
|
8
|
+
if (!apiKey) {
|
|
9
|
+
throw new Error(NOT_LOGGED_IN_MESSAGE);
|
|
10
|
+
}
|
|
11
|
+
const serverUrl = env.SUPERBLOCKS_SERVER_URL?.trim() ||
|
|
12
|
+
auth?.superblocksBaseUrl?.trim() ||
|
|
13
|
+
"http://localhost:8080";
|
|
14
|
+
return { apiKey, serverUrl };
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Point the Gateway process at the same control plane the CLI session uses,
|
|
18
|
+
* unless the operator already set SUPERBLOCKS_SERVER_URL. For a remote login
|
|
19
|
+
* (EE / SaaS) also default GATEWAY_BASE_URL so edit/preview URLs are not
|
|
20
|
+
* localhost:3000. A loopback session keeps the split local UI port.
|
|
21
|
+
*/
|
|
22
|
+
export function applyCliGatewaySessionToEnv(session, env = process.env) {
|
|
23
|
+
if (!env.SUPERBLOCKS_SERVER_URL?.trim()) {
|
|
24
|
+
env.SUPERBLOCKS_SERVER_URL = session.serverUrl;
|
|
25
|
+
}
|
|
26
|
+
if (!env.GATEWAY_SERVER_URL?.trim()) {
|
|
27
|
+
env.GATEWAY_SERVER_URL = session.serverUrl;
|
|
28
|
+
}
|
|
29
|
+
if (!env.GATEWAY_UI_BASE_URL?.trim() &&
|
|
30
|
+
!env.GATEWAY_BASE_URL?.trim() &&
|
|
31
|
+
!isLoopbackOrigin(session.serverUrl)) {
|
|
32
|
+
env.GATEWAY_BASE_URL = session.serverUrl;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function isLoopbackOrigin(url) {
|
|
36
|
+
try {
|
|
37
|
+
const hostname = new URL(url).hostname;
|
|
38
|
+
return (hostname === "localhost" ||
|
|
39
|
+
hostname === "127.0.0.1" ||
|
|
40
|
+
hostname === "[::1]");
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=cli-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-session.js","sourceRoot":"","sources":["../../src/auth/cli-session.ts"],"names":[],"mappings":"AAYA,MAAM,CAAC,MAAM,qBAAqB,GAChC,yGAAyG,CAAC;AAE5G;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CACtC,IAAgC,EAChC,GAAG,GAAsB,OAAO,CAAC,GAAG;IAEpC,MAAM,MAAM,GAAG,GAAG,CAAC,qBAAqB,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACxE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IACD,MAAM,SAAS,GACb,GAAG,CAAC,sBAAsB,EAAE,IAAI,EAAE;QAClC,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE;QAChC,uBAAuB,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAC/B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B,CACzC,OAA0B,EAC1B,GAAG,GAAsB,OAAO,CAAC,GAAG;IAEpC,IAAI,CAAC,GAAG,CAAC,sBAAsB,EAAE,IAAI,EAAE,EAAE,CAAC;QACxC,GAAG,CAAC,sBAAsB,GAAG,OAAO,CAAC,SAAS,CAAC;IACjD,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE,EAAE,CAAC;QACpC,GAAG,CAAC,kBAAkB,GAAG,OAAO,CAAC,SAAS,CAAC;IAC7C,CAAC;IACD,IACE,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,EAAE;QAChC,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,EAAE;QAC7B,CAAC,gBAAgB,CAAC,OAAO,CAAC,SAAS,CAAC,EACpC,CAAC;QACD,GAAG,CAAC,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC;IAC3C,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW;IACnC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;QACvC,OAAO,CACL,QAAQ,KAAK,WAAW;YACxB,QAAQ,KAAK,WAAW;YACxB,QAAQ,KAAK,OAAO,CACrB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { McpOAuthSessionStore } from "./mcp-oauth-session.js";
|
|
2
|
+
import { McpServerSelectionStore } from "./mcp-server-selection.js";
|
|
3
|
+
export declare function runMcpLogin(options?: {
|
|
4
|
+
env?: NodeJS.ProcessEnv;
|
|
5
|
+
fetch?: typeof fetch;
|
|
6
|
+
forceLogin?: boolean;
|
|
7
|
+
loadAuth?: () => Promise<{
|
|
8
|
+
superblocksBaseUrl?: string;
|
|
9
|
+
} | undefined>;
|
|
10
|
+
oauthStore?: McpOAuthSessionStore;
|
|
11
|
+
openBrowser?: (url: string) => Promise<void>;
|
|
12
|
+
redirectPort?: number;
|
|
13
|
+
serverSelection?: McpServerSelectionStore;
|
|
14
|
+
serverUrl?: string;
|
|
15
|
+
sessionId?: string;
|
|
16
|
+
signal?: AbortSignal;
|
|
17
|
+
}): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=login.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/auth/login.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,oBAAoB,EAGrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAOpE,wBAAsB,WAAW,CAC/B,OAAO,GAAE;IACP,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,kBAAkB,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,CAAC;IACtE,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAClC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACjB,GACL,OAAO,CAAC,IAAI,CAAC,CAqHf"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import open from "open";
|
|
3
|
+
import { getLocalTokenWithUrlIfExists } from "@superblocksteam/util/login";
|
|
4
|
+
import { assertMcpOAuthServerConfig, McpOAuthSessionStore, normalizeMcpServerUrl, parseNativeOAuthConfig, } from "./mcp-oauth-session.js";
|
|
5
|
+
import { McpServerSelectionStore } from "./mcp-server-selection.js";
|
|
6
|
+
import { NativeOAuthClient, } from "./native-oauth.js";
|
|
7
|
+
export async function runMcpLogin(options = {}) {
|
|
8
|
+
if (options.signal?.aborted)
|
|
9
|
+
throw new Error("MCP browser login cancelled.");
|
|
10
|
+
const env = options.env ?? process.env;
|
|
11
|
+
const loadAuth = options.loadAuth ?? getLocalTokenWithUrlIfExists;
|
|
12
|
+
const oauthStore = options.oauthStore ?? new McpOAuthSessionStore();
|
|
13
|
+
const serverSelection = options.serverSelection ??
|
|
14
|
+
McpServerSelectionStore.beside(oauthStore.filePath);
|
|
15
|
+
const chosenServerUrl = options.serverUrl?.trim();
|
|
16
|
+
const pinnedServerUrl = env.SUPERBLOCKS_SERVER_URL?.trim() || env.SUPERBLOCKS_BASE_URL?.trim();
|
|
17
|
+
const serverUrl = normalizeMcpServerUrl(chosenServerUrl ||
|
|
18
|
+
pinnedServerUrl ||
|
|
19
|
+
(await serverSelection.resolve(oauthStore)) ||
|
|
20
|
+
(await loadAuth())?.superblocksBaseUrl ||
|
|
21
|
+
"https://app.superblocks.com");
|
|
22
|
+
const request = options.fetch ?? fetch;
|
|
23
|
+
let config;
|
|
24
|
+
let configStatus;
|
|
25
|
+
try {
|
|
26
|
+
const response = await request(`${serverUrl}/api/v1/mcp/oauth/config`, {
|
|
27
|
+
redirect: "error",
|
|
28
|
+
signal: AbortSignal.any([
|
|
29
|
+
AbortSignal.timeout(30_000),
|
|
30
|
+
...(options.signal ? [options.signal] : []),
|
|
31
|
+
]),
|
|
32
|
+
});
|
|
33
|
+
configStatus = response.status;
|
|
34
|
+
if (!response.ok)
|
|
35
|
+
throw new Error();
|
|
36
|
+
const body = await response.json();
|
|
37
|
+
config = parseNativeOAuthConfig(isRecord(body) ? body.data : undefined);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
if (options.signal?.aborted)
|
|
41
|
+
throw new Error("MCP browser login cancelled.");
|
|
42
|
+
const reason = configStatus === undefined
|
|
43
|
+
? "network error"
|
|
44
|
+
: configStatus >= 200 && configStatus < 300
|
|
45
|
+
? "invalid response"
|
|
46
|
+
: `HTTP ${configStatus}`;
|
|
47
|
+
throw new Error(`Could not load MCP browser login configuration. Check the server URL and OAuth setup. (${reason})`);
|
|
48
|
+
}
|
|
49
|
+
assertMcpOAuthServerConfig(serverUrl, config);
|
|
50
|
+
const client = new NativeOAuthClient(config, { fetch: request });
|
|
51
|
+
let tokens;
|
|
52
|
+
try {
|
|
53
|
+
tokens = await client.authorize({
|
|
54
|
+
forceLogin: options.forceLogin,
|
|
55
|
+
openBrowser: options.openBrowser ??
|
|
56
|
+
(async (url) => {
|
|
57
|
+
await open(url);
|
|
58
|
+
}),
|
|
59
|
+
redirectPort: options.redirectPort,
|
|
60
|
+
signal: options.signal,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (options.signal?.aborted)
|
|
65
|
+
throw new Error("MCP browser login cancelled.");
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
let identityStatus;
|
|
69
|
+
try {
|
|
70
|
+
const response = await request(`${serverUrl}/api/v1/users/me`, {
|
|
71
|
+
headers: { Authorization: `Bearer ${tokens.accessToken}` },
|
|
72
|
+
redirect: "error",
|
|
73
|
+
signal: AbortSignal.any([
|
|
74
|
+
AbortSignal.timeout(30_000),
|
|
75
|
+
...(options.signal ? [options.signal] : []),
|
|
76
|
+
]),
|
|
77
|
+
});
|
|
78
|
+
identityStatus = response.status;
|
|
79
|
+
if (!response.ok)
|
|
80
|
+
throw new Error();
|
|
81
|
+
const body = await response.json();
|
|
82
|
+
if (!isRecord(body) ||
|
|
83
|
+
!isRecord(body.data) ||
|
|
84
|
+
!isRecord(body.data.user) ||
|
|
85
|
+
typeof body.data.user.id !== "string" ||
|
|
86
|
+
!body.data.user.id.trim()) {
|
|
87
|
+
throw new Error();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
if (options.signal?.aborted)
|
|
92
|
+
throw new Error("MCP browser login cancelled.");
|
|
93
|
+
const reason = identityStatus === undefined
|
|
94
|
+
? "network error"
|
|
95
|
+
: identityStatus >= 200 && identityStatus < 300
|
|
96
|
+
? "invalid response"
|
|
97
|
+
: `HTTP ${identityStatus}`;
|
|
98
|
+
throw new Error(`Server did not accept the browser login. Check your account and deployment. (${reason})`);
|
|
99
|
+
}
|
|
100
|
+
if (options.signal?.aborted)
|
|
101
|
+
throw new Error("MCP browser login cancelled.");
|
|
102
|
+
const pinned = !chosenServerUrl && Boolean(pinnedServerUrl);
|
|
103
|
+
await oauthStore.save({
|
|
104
|
+
config,
|
|
105
|
+
...(pinned ? { pinned } : {}),
|
|
106
|
+
serverUrl,
|
|
107
|
+
sessionId: options.sessionId ?? randomUUID(),
|
|
108
|
+
tokens,
|
|
109
|
+
}, options.signal, pinned
|
|
110
|
+
? {}
|
|
111
|
+
: { alongside: () => saveChosenServer(serverSelection, serverUrl) });
|
|
112
|
+
}
|
|
113
|
+
async function saveChosenServer(serverSelection, serverUrl) {
|
|
114
|
+
try {
|
|
115
|
+
await serverSelection.save(serverUrl);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
throw new Error(`Could not save the chosen server to ${serverSelection.filePath}. Fix or remove that file, then sign in again.`, { cause: error });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function isRecord(value) {
|
|
122
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/auth/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type NativeOAuthConfig, type OAuthTokens } from "./native-oauth.js";
|
|
2
|
+
export type StoredMcpOAuthSession = {
|
|
3
|
+
config: NativeOAuthConfig;
|
|
4
|
+
/** The environment, not the user, chose this login's server. */
|
|
5
|
+
pinned?: true;
|
|
6
|
+
serverUrl: string;
|
|
7
|
+
sessionId: string;
|
|
8
|
+
tokens: OAuthTokens;
|
|
9
|
+
};
|
|
10
|
+
export declare const MCP_OAUTH_FILE_SUFFIX = ".mcp-oauth";
|
|
11
|
+
export declare class McpOAuthStoreReadError extends Error {
|
|
12
|
+
}
|
|
13
|
+
export declare class McpOAuthSessionStore {
|
|
14
|
+
private readonly options;
|
|
15
|
+
readonly filePath: string;
|
|
16
|
+
constructor(options?: {
|
|
17
|
+
fetch?: typeof fetch;
|
|
18
|
+
filePath?: string;
|
|
19
|
+
now?: () => number;
|
|
20
|
+
});
|
|
21
|
+
read(): Promise<StoredMcpOAuthSession | undefined>;
|
|
22
|
+
/**
|
|
23
|
+
* Saves the session. `alongside` runs first under the same lock, so a
|
|
24
|
+
* write that must agree with the session commits in the same order as it,
|
|
25
|
+
* and its failure leaves the previous session in place.
|
|
26
|
+
*/
|
|
27
|
+
save(session: StoredMcpOAuthSession, signal?: AbortSignal, { alongside }?: {
|
|
28
|
+
alongside?: () => Promise<void>;
|
|
29
|
+
}): Promise<void>;
|
|
30
|
+
clear(): Promise<void>;
|
|
31
|
+
getSession(serverUrl?: string): Promise<{
|
|
32
|
+
apiKey: string;
|
|
33
|
+
getAccessToken: () => Promise<string>;
|
|
34
|
+
serverUrl: string;
|
|
35
|
+
sessionKey: string;
|
|
36
|
+
} | undefined>;
|
|
37
|
+
private accessToken;
|
|
38
|
+
/** Runs `operation` while no other process can change the saved login. */
|
|
39
|
+
withLock<T>(operation: () => Promise<T>, signal?: AbortSignal): Promise<T>;
|
|
40
|
+
private acquireLock;
|
|
41
|
+
private write;
|
|
42
|
+
}
|
|
43
|
+
export declare function normalizeMcpServerUrl(value: string): string;
|
|
44
|
+
export declare function parseNativeOAuthConfig(value: unknown): NativeOAuthConfig;
|
|
45
|
+
export declare function assertMcpOAuthServerConfig(serverUrl: string, config: NativeOAuthConfig): void;
|
|
46
|
+
//# sourceMappingURL=mcp-oauth-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-oauth-session.d.ts","sourceRoot":"","sources":["../../src/auth/mcp-oauth-session.ts"],"names":[],"mappings":"AAUA,OAAO,EAEL,KAAK,iBAAiB,EAEtB,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,gEAAgE;IAChE,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,qBAAqB,eAAe,CAAC;AAElD,qBAAa,sBAAuB,SAAQ,KAAK;CAAG;AAEpD,qBAAa,oBAAoB;IAI7B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAH1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,YACmB,OAAO,GAAE;QACxB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;KACf,EAIP;IAEK,IAAI,IAAI,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAiDvD;IAED;;;;OAIG;IACG,IAAI,CACR,OAAO,EAAE,qBAAqB,EAC9B,MAAM,CAAC,EAAE,WAAW,EACpB,EAAE,SAAS,EAAE,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAAO,GACtD,OAAO,CAAC,IAAI,CAAC,CAMf;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAE3B;IAEK,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM;;;;;mBAclC;YAEa,WAAW;IA0BzB,0EAA0E;IACpE,QAAQ,CAAC,CAAC,EACd,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,CAAC,CAAC,CAUZ;YAEa,WAAW;YA+BX,KAAK;CAYpB;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAgB3D;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,CA8BxE;AAcD,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,iBAAiB,GACxB,IAAI,CAoCN"}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
import lockfile from "lockfile";
|
|
7
|
+
import { resolveAuthFilePath } from "@superblocksteam/util/login";
|
|
8
|
+
import { NativeOAuthClient, OAuthRefreshError, } from "./native-oauth.js";
|
|
9
|
+
export const MCP_OAUTH_FILE_SUFFIX = ".mcp-oauth";
|
|
10
|
+
export class McpOAuthStoreReadError extends Error {
|
|
11
|
+
}
|
|
12
|
+
export class McpOAuthSessionStore {
|
|
13
|
+
options;
|
|
14
|
+
filePath;
|
|
15
|
+
constructor(options = {}) {
|
|
16
|
+
this.options = options;
|
|
17
|
+
this.filePath =
|
|
18
|
+
options.filePath ?? `${resolveAuthFilePath()}${MCP_OAUTH_FILE_SUFFIX}`;
|
|
19
|
+
}
|
|
20
|
+
async read() {
|
|
21
|
+
let contents;
|
|
22
|
+
try {
|
|
23
|
+
contents = await readFile(this.filePath, "utf8");
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
27
|
+
return undefined;
|
|
28
|
+
throw new McpOAuthStoreReadError("Could not read MCP browser login. Run: superblocks mcp login");
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const value = JSON.parse(contents);
|
|
32
|
+
if (!isRecord(value) ||
|
|
33
|
+
typeof value.serverUrl !== "string" ||
|
|
34
|
+
typeof value.sessionId !== "string" ||
|
|
35
|
+
!value.sessionId ||
|
|
36
|
+
!isRecord(value.tokens))
|
|
37
|
+
throw new Error();
|
|
38
|
+
const { accessToken, expiresAt, refreshToken } = value.tokens;
|
|
39
|
+
if (typeof accessToken !== "string" ||
|
|
40
|
+
!accessToken ||
|
|
41
|
+
typeof expiresAt !== "number" ||
|
|
42
|
+
!Number.isFinite(expiresAt) ||
|
|
43
|
+
(refreshToken !== undefined &&
|
|
44
|
+
(typeof refreshToken !== "string" || !refreshToken.trim())))
|
|
45
|
+
throw new Error();
|
|
46
|
+
const config = parseNativeOAuthConfig(value.config);
|
|
47
|
+
assertMcpOAuthServerConfig(value.serverUrl, config);
|
|
48
|
+
return {
|
|
49
|
+
config,
|
|
50
|
+
...(value.pinned === true ? { pinned: true } : {}),
|
|
51
|
+
serverUrl: normalizeMcpServerUrl(value.serverUrl),
|
|
52
|
+
sessionId: value.sessionId,
|
|
53
|
+
tokens: {
|
|
54
|
+
accessToken,
|
|
55
|
+
expiresAt,
|
|
56
|
+
...(refreshToken !== undefined && { refreshToken }),
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
throw new McpOAuthStoreReadError("Invalid MCP browser login. Run: superblocks mcp login");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Saves the session. `alongside` runs first under the same lock, so a
|
|
66
|
+
* write that must agree with the session commits in the same order as it,
|
|
67
|
+
* and its failure leaves the previous session in place.
|
|
68
|
+
*/
|
|
69
|
+
async save(session, signal, { alongside } = {}) {
|
|
70
|
+
await this.withLock(async () => {
|
|
71
|
+
signal?.throwIfAborted();
|
|
72
|
+
await alongside?.();
|
|
73
|
+
return this.write(session);
|
|
74
|
+
}, signal);
|
|
75
|
+
}
|
|
76
|
+
async clear() {
|
|
77
|
+
await this.withLock(() => rm(this.filePath, { force: true }));
|
|
78
|
+
}
|
|
79
|
+
async getSession(serverUrl) {
|
|
80
|
+
const session = await this.read();
|
|
81
|
+
if (!session ||
|
|
82
|
+
(serverUrl && normalizeMcpServerUrl(serverUrl) !== session.serverUrl))
|
|
83
|
+
return undefined;
|
|
84
|
+
const getAccessToken = () => this.accessToken(session);
|
|
85
|
+
return {
|
|
86
|
+
apiKey: await getAccessToken(),
|
|
87
|
+
getAccessToken,
|
|
88
|
+
serverUrl: session.serverUrl,
|
|
89
|
+
sessionKey: `oauth:${session.sessionId}`,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
async accessToken(expected) {
|
|
93
|
+
return this.withLock(async () => {
|
|
94
|
+
const session = await this.read();
|
|
95
|
+
if (!session ||
|
|
96
|
+
session.sessionId !== expected.sessionId ||
|
|
97
|
+
session.serverUrl !== expected.serverUrl)
|
|
98
|
+
throw new Error("Saved Superblocks login changed outside this task. Call Login to confirm the account.");
|
|
99
|
+
if (session.tokens.expiresAt > (this.options.now ?? Date.now)() + 60_000)
|
|
100
|
+
return session.tokens.accessToken;
|
|
101
|
+
if (!session.tokens.refreshToken)
|
|
102
|
+
throw new OAuthRefreshError("MCP browser login required. Call the Login tool, or run superblocks mcp login and restart the MCP host.");
|
|
103
|
+
const tokens = await new NativeOAuthClient(session.config, this.options).refresh(session.tokens.refreshToken);
|
|
104
|
+
await this.write({ ...session, tokens });
|
|
105
|
+
return tokens.accessToken;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/** Runs `operation` while no other process can change the saved login. */
|
|
109
|
+
async withLock(operation, signal) {
|
|
110
|
+
await mkdir(dirname(this.filePath), { mode: 0o700, recursive: true });
|
|
111
|
+
const lockPath = `${this.filePath}.lock`;
|
|
112
|
+
await this.acquireLock(lockPath, signal);
|
|
113
|
+
try {
|
|
114
|
+
signal?.throwIfAborted();
|
|
115
|
+
return await operation();
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
await promisify(lockfile.unlock)(lockPath);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
async acquireLock(lockPath, signal) {
|
|
122
|
+
const expiresAt = Date.now() + 75_000;
|
|
123
|
+
while (true) {
|
|
124
|
+
signal?.throwIfAborted();
|
|
125
|
+
try {
|
|
126
|
+
await new Promise((resolve, reject) => {
|
|
127
|
+
lockfile.lock(lockPath, { stale: 120_000 }, (error) => {
|
|
128
|
+
if (error)
|
|
129
|
+
reject(error);
|
|
130
|
+
else
|
|
131
|
+
resolve();
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
if (!(error instanceof Error &&
|
|
138
|
+
"code" in error &&
|
|
139
|
+
error.code === "EEXIST"))
|
|
140
|
+
throw error;
|
|
141
|
+
if (Date.now() >= expiresAt)
|
|
142
|
+
throw new Error("MCP browser login is busy. Try again shortly.");
|
|
143
|
+
await delay(100, undefined, { signal });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async write(session) {
|
|
148
|
+
const temporaryPath = `${this.filePath}.${randomUUID()}.tmp`;
|
|
149
|
+
try {
|
|
150
|
+
await writeFile(temporaryPath, JSON.stringify(session), {
|
|
151
|
+
flag: "wx",
|
|
152
|
+
mode: 0o600,
|
|
153
|
+
});
|
|
154
|
+
await rename(temporaryPath, this.filePath);
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
await rm(temporaryPath, { force: true });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
export function normalizeMcpServerUrl(value) {
|
|
162
|
+
const url = new URL(value);
|
|
163
|
+
const loopback = ["127.0.0.1", "[::1]", "localhost"].includes(url.hostname);
|
|
164
|
+
if ((url.protocol !== "https:" && !(url.protocol === "http:" && loopback)) ||
|
|
165
|
+
url.username ||
|
|
166
|
+
url.password ||
|
|
167
|
+
url.search ||
|
|
168
|
+
url.hash ||
|
|
169
|
+
url.pathname !== "/") {
|
|
170
|
+
throw new Error("MCP server URL must be an HTTPS origin (HTTP is allowed only on loopback).");
|
|
171
|
+
}
|
|
172
|
+
return url.origin;
|
|
173
|
+
}
|
|
174
|
+
export function parseNativeOAuthConfig(value) {
|
|
175
|
+
if (!isRecord(value))
|
|
176
|
+
throw new Error("Invalid MCP OAuth configuration.");
|
|
177
|
+
const { audience, clientId, issuerUrl, organization } = value;
|
|
178
|
+
if (typeof audience !== "string" ||
|
|
179
|
+
!audience.trim() ||
|
|
180
|
+
typeof clientId !== "string" ||
|
|
181
|
+
!clientId.trim() ||
|
|
182
|
+
typeof issuerUrl !== "string" ||
|
|
183
|
+
!issuerUrl.trim() ||
|
|
184
|
+
(organization !== undefined &&
|
|
185
|
+
(typeof organization !== "string" || !organization.trim()))) {
|
|
186
|
+
throw new Error("Invalid MCP OAuth configuration.");
|
|
187
|
+
}
|
|
188
|
+
const issuer = new URL(issuerUrl);
|
|
189
|
+
if (issuer.protocol !== "https:" ||
|
|
190
|
+
issuer.username ||
|
|
191
|
+
issuer.password ||
|
|
192
|
+
issuer.hash ||
|
|
193
|
+
issuer.search)
|
|
194
|
+
throw new Error("MCP OAuth issuer must use HTTPS.");
|
|
195
|
+
return {
|
|
196
|
+
audience,
|
|
197
|
+
clientId,
|
|
198
|
+
issuerUrl,
|
|
199
|
+
...(organization ? { organization } : {}),
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
const FIRST_PARTY_AUDIENCE = "https://superblocks/api";
|
|
203
|
+
const FIRST_PARTY_CLIENTS = {
|
|
204
|
+
development: {
|
|
205
|
+
clientId: "kx2bGKgQVB2rPNROHa0MCTfS8ZPIqD5C",
|
|
206
|
+
issuerUrl: "https://login-dev.superblocks.com",
|
|
207
|
+
},
|
|
208
|
+
production: {
|
|
209
|
+
clientId: "iVC3LD0oU5kwvVP7SBUZIjRkjZyT9mAH",
|
|
210
|
+
issuerUrl: "https://login.superblocks.com",
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
export function assertMcpOAuthServerConfig(serverUrl, config) {
|
|
214
|
+
const hostname = new URL(serverUrl).hostname;
|
|
215
|
+
const issuer = new URL(config.issuerUrl);
|
|
216
|
+
const expected = [
|
|
217
|
+
"app.superblocks.com",
|
|
218
|
+
"eu.superblocks.com",
|
|
219
|
+
"app.superblockshq.com",
|
|
220
|
+
"api.superblocks.link",
|
|
221
|
+
].includes(hostname)
|
|
222
|
+
? FIRST_PARTY_CLIENTS.production
|
|
223
|
+
: hostname === "staging.superblocks.com" ||
|
|
224
|
+
hostname === "superblocks.dev" ||
|
|
225
|
+
hostname.endsWith(".superblocks.dev") ||
|
|
226
|
+
hostname === "superblocks.local" ||
|
|
227
|
+
hostname.endsWith(".superblocks.local") ||
|
|
228
|
+
["localhost", "127.0.0.1", "[::1]"].includes(hostname)
|
|
229
|
+
? FIRST_PARTY_CLIENTS.development
|
|
230
|
+
: undefined;
|
|
231
|
+
const firstPartyClient = expected ??
|
|
232
|
+
Object.values(FIRST_PARTY_CLIENTS).find((client) => config.clientId === client.clientId ||
|
|
233
|
+
issuer.hostname.replace(/\.+$/, "") ===
|
|
234
|
+
new URL(client.issuerUrl).hostname);
|
|
235
|
+
if (firstPartyClient &&
|
|
236
|
+
(issuer.origin !== firstPartyClient.issuerUrl ||
|
|
237
|
+
issuer.pathname !== "/" ||
|
|
238
|
+
config.clientId !== firstPartyClient.clientId ||
|
|
239
|
+
config.audience !== FIRST_PARTY_AUDIENCE ||
|
|
240
|
+
!expected)) {
|
|
241
|
+
throw new Error("MCP OAuth configuration does not match the server URL.");
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function isRecord(value) {
|
|
245
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=mcp-oauth-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-oauth-session.js","sourceRoot":"","sources":["../../src/auth/mcp-oauth-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type McpOAuthSessionStore } from "./mcp-oauth-session.js";
|
|
2
|
+
/**
|
|
3
|
+
* The Superblocks server this computer's MCP plugin uses, kept as `serverUrl`
|
|
4
|
+
* in the plugin settings file the plugin launcher also reads. It is kept apart
|
|
5
|
+
* from the browser login saved for that server, so a removed, expired, or
|
|
6
|
+
* unreadable login never sends the plugin back to the default server, and a
|
|
7
|
+
* server the user writes into the file is used even while the saved login
|
|
8
|
+
* belongs to another server.
|
|
9
|
+
*/
|
|
10
|
+
export declare class McpServerSelectionStore {
|
|
11
|
+
readonly filePath: string;
|
|
12
|
+
private readonly legacyFilePath?;
|
|
13
|
+
constructor(filePath: string, legacyFilePath?: string | undefined);
|
|
14
|
+
/**
|
|
15
|
+
* The plugin settings file in the browser login file's directory. A
|
|
16
|
+
* selection saved before that file existed is moved into it on first read.
|
|
17
|
+
*/
|
|
18
|
+
static beside(sessionFilePath: string): McpServerSelectionStore;
|
|
19
|
+
/**
|
|
20
|
+
* The server in use: the one the user chose, else the saved browser
|
|
21
|
+
* login's server, which is recorded as the choice unless the environment
|
|
22
|
+
* pinned it. The record is written under the login's lock so a concurrent
|
|
23
|
+
* sign-in cannot save a newer login between the read and the write.
|
|
24
|
+
*/
|
|
25
|
+
resolve(sessions: McpOAuthSessionStore): Promise<string | undefined>;
|
|
26
|
+
/**
|
|
27
|
+
* The server a sign-in uses once the saved browser login is gone. A login
|
|
28
|
+
* the user chose is recorded first; one the environment pinned is not.
|
|
29
|
+
*/
|
|
30
|
+
withoutLogin(sessions: McpOAuthSessionStore): Promise<string | undefined>;
|
|
31
|
+
/** The selected origin, or undefined when none is saved or it is unusable. */
|
|
32
|
+
read(): Promise<string | undefined>;
|
|
33
|
+
/** Saves the selection without failing the sign-in or switch that made it. */
|
|
34
|
+
remember(serverUrl: string): Promise<void>;
|
|
35
|
+
/** Writes `serverUrl` and keeps every other plugin setting as it was. */
|
|
36
|
+
save(serverUrl: string): Promise<void>;
|
|
37
|
+
/** Once plugin.json names a server, the old file must not bring back an older one. */
|
|
38
|
+
private dropLegacySelection;
|
|
39
|
+
private moveLegacySelection;
|
|
40
|
+
private static parse;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=mcp-server-selection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server-selection.d.ts","sourceRoot":"","sources":["../../src/auth/mcp-server-selection.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,oBAAoB,EAG1B,MAAM,wBAAwB,CAAC;AAIhC;;;;;;;GAOG;AACH,qBAAa,uBAAuB;IAEhC,QAAQ,CAAC,QAAQ,EAAE,MAAM;IACzB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;IAFlC,YACW,QAAQ,EAAE,MAAM,EACR,cAAc,CAAC,EAAE,MAAM,YAAA,EACtC;IAEJ;;;OAGG;IACH,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,GAAG,uBAAuB,CAQ9D;IAED;;;;;OAKG;IACG,OAAO,CAAC,QAAQ,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAWzE;IAED;;;OAGG;IACG,YAAY,CAChB,QAAQ,EAAE,oBAAoB,GAC7B,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAG7B;IAED,8EAA8E;IACxE,IAAI,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAaxC;IAED,8EAA8E;IACxE,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS/C;IAED,yEAAyE;IACnE,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB3C;IAED,sFAAsF;YACxE,mBAAmB;YAUnB,mBAAmB;IAejC,OAAO,CAAC,MAAM,CAAC,KAAK;CAKrB"}
|