align-mcp-remote 0.1.38 → 0.1.39
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/{chunk-MMS4PSEI.js → chunk-V2QU44UI.js} +96 -17
- package/dist/client.js +21 -3
- package/dist/proxy.js +21 -3
- package/package.json +1 -1
|
@@ -16410,6 +16410,17 @@ async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequ
|
|
|
16410
16410
|
}
|
|
16411
16411
|
return OAuthTokensSchema.parse(await response.json());
|
|
16412
16412
|
}
|
|
16413
|
+
async function exchangeAuthorization(authorizationServerUrl, { metadata, clientInformation, authorizationCode, codeVerifier, redirectUri, resource, addClientAuthentication, fetchFn }) {
|
|
16414
|
+
const tokenRequestParams = prepareAuthorizationCodeRequest(authorizationCode, codeVerifier, redirectUri);
|
|
16415
|
+
return executeTokenRequest(authorizationServerUrl, {
|
|
16416
|
+
metadata,
|
|
16417
|
+
tokenRequestParams,
|
|
16418
|
+
clientInformation,
|
|
16419
|
+
addClientAuthentication,
|
|
16420
|
+
resource,
|
|
16421
|
+
fetchFn
|
|
16422
|
+
});
|
|
16423
|
+
}
|
|
16413
16424
|
async function refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken, resource, addClientAuthentication, fetchFn }) {
|
|
16414
16425
|
const tokenRequestParams = new URLSearchParams({
|
|
16415
16426
|
grant_type: "refresh_token",
|
|
@@ -18072,41 +18083,92 @@ async function discoverOAuthServerInfo2(serverUrl, headers = {}) {
|
|
|
18072
18083
|
debugLog("No Protected Resource Metadata found, falling back to server URL as authorization server");
|
|
18073
18084
|
}
|
|
18074
18085
|
const authorizationServerMetadata = await fetchAuthorizationServerMetadata(authorizationServerUrl);
|
|
18086
|
+
const downstreamTokenHeader = protectedResourceMetadata?.x_downstream_resource?.token_header ?? "X-Downstream-Authorization";
|
|
18075
18087
|
return {
|
|
18076
18088
|
authorizationServerUrl,
|
|
18077
18089
|
authorizationServerMetadata,
|
|
18078
18090
|
protectedResourceMetadata,
|
|
18079
|
-
wwwAuthenticateScope
|
|
18091
|
+
wwwAuthenticateScope,
|
|
18092
|
+
downstreamTokenHeader: protectedResourceMetadata?.x_downstream_resource ? downstreamTokenHeader : void 0
|
|
18080
18093
|
};
|
|
18081
18094
|
}
|
|
18082
|
-
async function
|
|
18095
|
+
async function performDownstreamAuth(authProvider, downstreamResource, callbackPort, waitForAuthCode) {
|
|
18096
|
+
debugLog("Starting downstream OAuth flow", { downstreamResource });
|
|
18097
|
+
const downstreamServerMetadata = await fetchAuthorizationServerMetadata(downstreamResource.authorization_server);
|
|
18098
|
+
if (!downstreamServerMetadata) {
|
|
18099
|
+
throw new Error(`Failed to fetch downstream authorization server metadata from ${downstreamResource.authorization_server}`);
|
|
18100
|
+
}
|
|
18101
|
+
const redirectUrl = `http://${authProvider.options.host || "localhost"}:${callbackPort}/oauth/callback`;
|
|
18102
|
+
const scope = downstreamResource.scopes_required?.join(" ") ?? "";
|
|
18103
|
+
const { authorizationUrl, codeVerifier } = await startAuthorization(downstreamResource.authorization_server, {
|
|
18104
|
+
metadata: downstreamServerMetadata,
|
|
18105
|
+
clientInformation: await authProvider.clientInformation(),
|
|
18106
|
+
redirectUrl,
|
|
18107
|
+
scope,
|
|
18108
|
+
resource: new URL(downstreamResource.resource)
|
|
18109
|
+
});
|
|
18110
|
+
log(`
|
|
18111
|
+
Please authorize downstream resource by visiting:
|
|
18112
|
+
${authorizationUrl.toString()}
|
|
18113
|
+
`);
|
|
18114
|
+
try {
|
|
18115
|
+
const { default: open2 } = await import("open");
|
|
18116
|
+
await open2(authorizationUrl.toString());
|
|
18117
|
+
log("Browser opened automatically for downstream authorization.");
|
|
18118
|
+
} catch {
|
|
18119
|
+
log("Could not open browser automatically. Please copy and paste the URL above.");
|
|
18120
|
+
}
|
|
18121
|
+
const code = await waitForAuthCode();
|
|
18122
|
+
const tokens = await exchangeAuthorization(downstreamResource.authorization_server, {
|
|
18123
|
+
metadata: downstreamServerMetadata,
|
|
18124
|
+
clientInformation: await authProvider.clientInformation(),
|
|
18125
|
+
authorizationCode: code,
|
|
18126
|
+
codeVerifier,
|
|
18127
|
+
redirectUri: redirectUrl
|
|
18128
|
+
});
|
|
18129
|
+
await authProvider.saveDownstreamTokens(tokens);
|
|
18130
|
+
debugLog("Downstream OAuth flow completed, tokens saved");
|
|
18131
|
+
}
|
|
18132
|
+
async function connectToRemoteServer(client, serverUrl, authProvider, headers, authInitializer, transportStrategy = "http-first", downstreamTokenHeader, recursionReasons = /* @__PURE__ */ new Set()) {
|
|
18083
18133
|
log(`[${pid}] Connecting to remote server: ${serverUrl}`);
|
|
18084
18134
|
const url2 = new URL(serverUrl);
|
|
18135
|
+
const resolveDownstreamHeader = async () => {
|
|
18136
|
+
if (!downstreamTokenHeader) return {};
|
|
18137
|
+
const provider = authProvider;
|
|
18138
|
+
if (typeof provider.downstreamTokens !== "function") return {};
|
|
18139
|
+
const downstreamTokens = await provider.downstreamTokens();
|
|
18140
|
+
if (downstreamTokens?.access_token) {
|
|
18141
|
+
return { [downstreamTokenHeader]: `Bearer ${downstreamTokens.access_token}` };
|
|
18142
|
+
}
|
|
18143
|
+
return {};
|
|
18144
|
+
};
|
|
18085
18145
|
const eventSourceInit = {
|
|
18086
|
-
fetch: (url3, init) => {
|
|
18087
|
-
|
|
18088
|
-
|
|
18089
|
-
|
|
18090
|
-
|
|
18091
|
-
|
|
18092
|
-
|
|
18093
|
-
|
|
18094
|
-
|
|
18095
|
-
|
|
18096
|
-
}
|
|
18097
|
-
);
|
|
18146
|
+
fetch: async (url3, init) => {
|
|
18147
|
+
const [tokens, downstreamHeader2] = await Promise.all([authProvider?.tokens?.(), resolveDownstreamHeader()]);
|
|
18148
|
+
return fetch2(url3, {
|
|
18149
|
+
...init,
|
|
18150
|
+
headers: {
|
|
18151
|
+
...init?.headers instanceof Headers2 ? Object.fromEntries(init?.headers.entries()) : init?.headers || {},
|
|
18152
|
+
...headers,
|
|
18153
|
+
...tokens?.access_token ? { Authorization: `Bearer ${tokens.access_token}` } : {},
|
|
18154
|
+
...downstreamHeader2,
|
|
18155
|
+
Accept: "text/event-stream"
|
|
18156
|
+
}
|
|
18157
|
+
});
|
|
18098
18158
|
}
|
|
18099
18159
|
};
|
|
18100
18160
|
log(`Using transport strategy: ${transportStrategy}`);
|
|
18101
18161
|
const shouldAttemptFallback2 = transportStrategy === "http-first" || transportStrategy === "sse-first";
|
|
18102
18162
|
const sseTransport = transportStrategy === "sse-only" || transportStrategy === "sse-first";
|
|
18163
|
+
const downstreamHeader = await resolveDownstreamHeader();
|
|
18164
|
+
const mergedHeaders = { ...headers, ...downstreamHeader };
|
|
18103
18165
|
const transport = sseTransport ? new SSEClientTransport(url2, {
|
|
18104
18166
|
authProvider,
|
|
18105
|
-
requestInit: { headers },
|
|
18167
|
+
requestInit: { headers: mergedHeaders },
|
|
18106
18168
|
eventSourceInit
|
|
18107
18169
|
}) : new StreamableHTTPClientTransport(url2, {
|
|
18108
18170
|
authProvider,
|
|
18109
|
-
requestInit: { headers }
|
|
18171
|
+
requestInit: { headers: mergedHeaders }
|
|
18110
18172
|
});
|
|
18111
18173
|
try {
|
|
18112
18174
|
debugLog("Attempting to connect to remote server", { sseTransport });
|
|
@@ -18145,6 +18207,7 @@ async function connectToRemoteServer(client, serverUrl, authProvider, headers, a
|
|
|
18145
18207
|
headers,
|
|
18146
18208
|
authInitializer,
|
|
18147
18209
|
sseTransport ? "http-only" : "sse-only",
|
|
18210
|
+
downstreamTokenHeader,
|
|
18148
18211
|
recursionReasons
|
|
18149
18212
|
);
|
|
18150
18213
|
} else if (error2 instanceof UnauthorizedError || error2 instanceof Error && error2.message.includes("Unauthorized")) {
|
|
@@ -18179,7 +18242,7 @@ async function connectToRemoteServer(client, serverUrl, authProvider, headers, a
|
|
|
18179
18242
|
recursionReasons.add(REASON_AUTH_NEEDED);
|
|
18180
18243
|
log(`Recursively reconnecting for reason: ${REASON_AUTH_NEEDED}`);
|
|
18181
18244
|
debugLog("Recursively reconnecting after auth", { recursionReasons: Array.from(recursionReasons) });
|
|
18182
|
-
return connectToRemoteServer(client, serverUrl, authProvider, headers, authInitializer, transportStrategy, recursionReasons);
|
|
18245
|
+
return connectToRemoteServer(client, serverUrl, authProvider, headers, authInitializer, transportStrategy, downstreamTokenHeader, recursionReasons);
|
|
18183
18246
|
} catch (authError) {
|
|
18184
18247
|
log("Authorization error:", authError);
|
|
18185
18248
|
debugLog("Authorization error during finishAuth", {
|
|
@@ -18759,6 +18822,20 @@ ${authorizationUrl.toString()}
|
|
|
18759
18822
|
debugLog("Code verifier found:", !!verifier);
|
|
18760
18823
|
return verifier;
|
|
18761
18824
|
}
|
|
18825
|
+
/**
|
|
18826
|
+
* Gets the downstream OAuth tokens (Layer 2) if they exist
|
|
18827
|
+
*/
|
|
18828
|
+
async downstreamTokens() {
|
|
18829
|
+
debugLog("Reading downstream OAuth tokens");
|
|
18830
|
+
return readJsonFile(this.serverUrlHash, "downstream_tokens.json", OAuthTokensSchema);
|
|
18831
|
+
}
|
|
18832
|
+
/**
|
|
18833
|
+
* Saves downstream OAuth tokens (Layer 2)
|
|
18834
|
+
*/
|
|
18835
|
+
async saveDownstreamTokens(tokens) {
|
|
18836
|
+
debugLog("Saving downstream tokens", { hasAccessToken: !!tokens.access_token });
|
|
18837
|
+
await writeJsonFile(this.serverUrlHash, "downstream_tokens.json", tokens);
|
|
18838
|
+
}
|
|
18762
18839
|
/**
|
|
18763
18840
|
* Invalidates the specified credentials
|
|
18764
18841
|
* @param scope The scope of credentials to invalidate
|
|
@@ -18770,6 +18847,7 @@ ${authorizationUrl.toString()}
|
|
|
18770
18847
|
await Promise.all([
|
|
18771
18848
|
deleteConfigFile(this.serverUrlHash, "client_info.json"),
|
|
18772
18849
|
deleteConfigFile(this.serverUrlHash, "tokens.json"),
|
|
18850
|
+
deleteConfigFile(this.serverUrlHash, "downstream_tokens.json"),
|
|
18773
18851
|
deleteConfigFile(this.serverUrlHash, "code_verifier.txt")
|
|
18774
18852
|
]);
|
|
18775
18853
|
this._clientInfo = void 0;
|
|
@@ -18990,6 +19068,7 @@ export {
|
|
|
18990
19068
|
log,
|
|
18991
19069
|
mcpProxy,
|
|
18992
19070
|
discoverOAuthServerInfo2 as discoverOAuthServerInfo,
|
|
19071
|
+
performDownstreamAuth,
|
|
18993
19072
|
connectToRemoteServer,
|
|
18994
19073
|
parseCommandLineArgs,
|
|
18995
19074
|
setupSignalHandlers,
|
package/dist/client.js
CHANGED
|
@@ -10,9 +10,10 @@ import {
|
|
|
10
10
|
discoverOAuthServerInfo,
|
|
11
11
|
log,
|
|
12
12
|
parseCommandLineArgs,
|
|
13
|
+
performDownstreamAuth,
|
|
13
14
|
setupSignalHandlers,
|
|
14
15
|
version
|
|
15
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-V2QU44UI.js";
|
|
16
17
|
|
|
17
18
|
// src/client.ts
|
|
18
19
|
import { EventEmitter } from "events";
|
|
@@ -52,6 +53,7 @@ async function runClient(serverUrl, callbackPort, headers, transportStrategy = "
|
|
|
52
53
|
capabilities: {}
|
|
53
54
|
}
|
|
54
55
|
);
|
|
56
|
+
const downstreamResource = discoveryResult.protectedResourceMetadata?.x_downstream_resource;
|
|
55
57
|
let server = null;
|
|
56
58
|
const authInitializer = async () => {
|
|
57
59
|
const authState = await authCoordinator.initializeAuth();
|
|
@@ -61,12 +63,28 @@ async function runClient(serverUrl, callbackPort, headers, transportStrategy = "
|
|
|
61
63
|
await new Promise((res) => setTimeout(res, 1e3));
|
|
62
64
|
}
|
|
63
65
|
return {
|
|
64
|
-
waitForAuthCode:
|
|
66
|
+
waitForAuthCode: async () => {
|
|
67
|
+
const code = await authState.waitForAuthCode();
|
|
68
|
+
if (downstreamResource && !authState.skipBrowserAuth) {
|
|
69
|
+
log("Layer 1 auth complete. Starting downstream (Layer 2) OAuth flow...");
|
|
70
|
+
await performDownstreamAuth(authProvider, downstreamResource, callbackPort, authState.waitForAuthCode);
|
|
71
|
+
log("Layer 2 auth complete.");
|
|
72
|
+
}
|
|
73
|
+
return code;
|
|
74
|
+
},
|
|
65
75
|
skipBrowserAuth: authState.skipBrowserAuth
|
|
66
76
|
};
|
|
67
77
|
};
|
|
68
78
|
try {
|
|
69
|
-
const transport = await connectToRemoteServer(
|
|
79
|
+
const transport = await connectToRemoteServer(
|
|
80
|
+
client,
|
|
81
|
+
serverUrl,
|
|
82
|
+
authProvider,
|
|
83
|
+
headers,
|
|
84
|
+
authInitializer,
|
|
85
|
+
transportStrategy,
|
|
86
|
+
discoveryResult.downstreamTokenHeader
|
|
87
|
+
);
|
|
70
88
|
transport.onmessage = (message) => {
|
|
71
89
|
log("Received message:", JSON.stringify(message, null, 2));
|
|
72
90
|
};
|
package/dist/proxy.js
CHANGED
|
@@ -9,8 +9,9 @@ import {
|
|
|
9
9
|
log,
|
|
10
10
|
mcpProxy,
|
|
11
11
|
parseCommandLineArgs,
|
|
12
|
+
performDownstreamAuth,
|
|
12
13
|
setupSignalHandlers
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-V2QU44UI.js";
|
|
14
15
|
|
|
15
16
|
// src/proxy.ts
|
|
16
17
|
import { EventEmitter } from "events";
|
|
@@ -138,6 +139,7 @@ async function runProxy(serverUrl, callbackPort, headers, transportStrategy = "h
|
|
|
138
139
|
});
|
|
139
140
|
const localTransport = new StdioServerTransport();
|
|
140
141
|
let server = null;
|
|
142
|
+
const downstreamResource = discoveryResult.protectedResourceMetadata?.x_downstream_resource;
|
|
141
143
|
const authInitializer = async () => {
|
|
142
144
|
const authState = await authCoordinator.initializeAuth();
|
|
143
145
|
server = authState.server;
|
|
@@ -146,12 +148,28 @@ async function runProxy(serverUrl, callbackPort, headers, transportStrategy = "h
|
|
|
146
148
|
await new Promise((res) => setTimeout(res, 1e3));
|
|
147
149
|
}
|
|
148
150
|
return {
|
|
149
|
-
waitForAuthCode:
|
|
151
|
+
waitForAuthCode: async () => {
|
|
152
|
+
const code = await authState.waitForAuthCode();
|
|
153
|
+
if (downstreamResource && !authState.skipBrowserAuth) {
|
|
154
|
+
log("Layer 1 auth complete. Starting downstream (Layer 2) OAuth flow...");
|
|
155
|
+
await performDownstreamAuth(authProvider, downstreamResource, callbackPort, authState.waitForAuthCode);
|
|
156
|
+
log("Layer 2 auth complete.");
|
|
157
|
+
}
|
|
158
|
+
return code;
|
|
159
|
+
},
|
|
150
160
|
skipBrowserAuth: authState.skipBrowserAuth
|
|
151
161
|
};
|
|
152
162
|
};
|
|
153
163
|
try {
|
|
154
|
-
const remoteTransport = await connectToRemoteServer(
|
|
164
|
+
const remoteTransport = await connectToRemoteServer(
|
|
165
|
+
null,
|
|
166
|
+
serverUrl,
|
|
167
|
+
authProvider,
|
|
168
|
+
headers,
|
|
169
|
+
authInitializer,
|
|
170
|
+
transportStrategy,
|
|
171
|
+
discoveryResult.downstreamTokenHeader
|
|
172
|
+
);
|
|
155
173
|
mcpProxy({
|
|
156
174
|
transportToClient: localTransport,
|
|
157
175
|
transportToServer: remoteTransport,
|