@mcp-ts/sdk 2.3.3 → 2.3.4
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/adapters/agui-adapter.d.mts +1 -1
- package/dist/adapters/agui-adapter.d.ts +1 -1
- package/dist/adapters/agui-middleware.d.mts +1 -1
- package/dist/adapters/agui-middleware.d.ts +1 -1
- package/dist/adapters/ai-adapter.d.mts +1 -1
- package/dist/adapters/ai-adapter.d.ts +1 -1
- package/dist/adapters/langchain-adapter.d.mts +1 -1
- package/dist/adapters/langchain-adapter.d.ts +1 -1
- package/dist/adapters/mastra-adapter.d.mts +1 -1
- package/dist/adapters/mastra-adapter.d.ts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +11 -101
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +12 -102
- package/dist/index.mjs.map +1 -1
- package/dist/{multi-session-client-DYNe6az3.d.mts → multi-session-client-C7hGqzgM.d.mts} +7 -15
- package/dist/{multi-session-client-BYtguGJm.d.ts → multi-session-client-C_kPHpD5.d.ts} +7 -15
- package/dist/server/index.d.mts +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +11 -101
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +12 -102
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/server/mcp/oauth-client.ts +7 -126
- package/src/server/storage/neon-backend.ts +1 -1
- package/src/server/storage/supabase-backend.ts +1 -1
package/package.json
CHANGED
|
@@ -4,9 +4,6 @@ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/
|
|
|
4
4
|
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
|
|
5
5
|
import {
|
|
6
6
|
UnauthorizedError as SDKUnauthorizedError,
|
|
7
|
-
refreshAuthorization,
|
|
8
|
-
discoverOAuthProtectedResourceMetadata,
|
|
9
|
-
discoverAuthorizationServerMetadata,
|
|
10
7
|
} from '@modelcontextprotocol/sdk/client/auth.js';
|
|
11
8
|
import {
|
|
12
9
|
ListToolsRequest,
|
|
@@ -28,7 +25,6 @@ import {
|
|
|
28
25
|
ReadResourceResult,
|
|
29
26
|
ReadResourceResultSchema,
|
|
30
27
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
31
|
-
import type { OAuthTokens, OAuthClientInformationFull } from '@modelcontextprotocol/sdk/shared/auth.js';
|
|
32
28
|
import { StorageOAuthClientProvider, type AgentsOAuthProvider } from './storage-oauth-provider.js';
|
|
33
29
|
import { sanitizeServerLabel } from '../../shared/utils.js';
|
|
34
30
|
import { Emitter, type McpConnectionEvent, type McpObservabilityEvent, type McpConnectionState } from '../../shared/events.js';
|
|
@@ -60,20 +56,6 @@ interface McpAppClientCapabilities extends Omit<ClientCapabilities, 'extensions'
|
|
|
60
56
|
};
|
|
61
57
|
}
|
|
62
58
|
|
|
63
|
-
function isInvalidRefreshTokenError(error: unknown): boolean {
|
|
64
|
-
if (!(error instanceof Error)) {
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const text = `${error.name} ${error.message}`.toLowerCase();
|
|
69
|
-
return (
|
|
70
|
-
text.includes('invalidgrant') ||
|
|
71
|
-
text.includes('invalid_grant') ||
|
|
72
|
-
text.includes('invalid refresh token') ||
|
|
73
|
-
/refresh\s+token\s+(?:is\s+)?(?:invalid|expired|revoked)/i.test(text)
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
59
|
export interface MCPOAuthClientOptions {
|
|
78
60
|
serverUrl?: string;
|
|
79
61
|
serverName?: string;
|
|
@@ -504,9 +486,6 @@ export class MCPClient {
|
|
|
504
486
|
}
|
|
505
487
|
|
|
506
488
|
try {
|
|
507
|
-
this.emitProgress('Validating OAuth tokens...');
|
|
508
|
-
await this.getValidTokens();
|
|
509
|
-
|
|
510
489
|
this.emitStateChange('CONNECTING');
|
|
511
490
|
|
|
512
491
|
/** Use the tryConnect loop to handle transport fallbacks */
|
|
@@ -947,79 +926,6 @@ export class MCPClient {
|
|
|
947
926
|
return await this.client.request(request, ReadResourceResultSchema);
|
|
948
927
|
}
|
|
949
928
|
|
|
950
|
-
/**
|
|
951
|
-
* Refreshes the OAuth access token using the refresh token
|
|
952
|
-
* Discovers OAuth metadata from server and exchanges refresh token for new access token
|
|
953
|
-
* @returns True if refresh was successful, false otherwise
|
|
954
|
-
*/
|
|
955
|
-
async refreshToken(): Promise<boolean> {
|
|
956
|
-
await this.initialize();
|
|
957
|
-
|
|
958
|
-
if (!this.oauthProvider) {
|
|
959
|
-
return false;
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
const tokens = await this.oauthProvider.tokens();
|
|
963
|
-
if (!tokens || !tokens.refresh_token) {
|
|
964
|
-
return false;
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
const clientInformation = await this.oauthProvider.clientInformation();
|
|
968
|
-
if (!clientInformation) {
|
|
969
|
-
return false;
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
try {
|
|
973
|
-
const resourceMetadata = await discoverOAuthProtectedResourceMetadata(this.serverUrl!);
|
|
974
|
-
const authServerUrl = resourceMetadata?.authorization_servers?.[0] || this.serverUrl!;
|
|
975
|
-
const authMetadata = await discoverAuthorizationServerMetadata(authServerUrl);
|
|
976
|
-
|
|
977
|
-
const newTokens = await refreshAuthorization(authServerUrl, {
|
|
978
|
-
metadata: authMetadata,
|
|
979
|
-
clientInformation,
|
|
980
|
-
refreshToken: tokens.refresh_token,
|
|
981
|
-
});
|
|
982
|
-
|
|
983
|
-
await this.oauthProvider.saveTokens(newTokens);
|
|
984
|
-
return true;
|
|
985
|
-
} catch (error) {
|
|
986
|
-
console.error('[OAuth] Token refresh failed:', error);
|
|
987
|
-
if (isInvalidRefreshTokenError(error)) {
|
|
988
|
-
try {
|
|
989
|
-
await this.oauthProvider.invalidateCredentials?.('tokens');
|
|
990
|
-
this.emitProgress('OAuth refresh token is invalid; requesting reauthorization...');
|
|
991
|
-
} catch (invalidateError) {
|
|
992
|
-
console.warn('[OAuth] Failed to invalidate stale refresh token credentials:', invalidateError);
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
return false;
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
|
|
999
|
-
/**
|
|
1000
|
-
* Ensures OAuth tokens are valid, refreshing them if expired
|
|
1001
|
-
* Called automatically by connect() - rarely needs to be called manually
|
|
1002
|
-
* @returns True if valid tokens are available, false otherwise
|
|
1003
|
-
*/
|
|
1004
|
-
async getValidTokens(): Promise<boolean> {
|
|
1005
|
-
await this.initialize();
|
|
1006
|
-
|
|
1007
|
-
if (!this.oauthProvider) {
|
|
1008
|
-
return false;
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
const tokens = await this.oauthProvider.tokens();
|
|
1012
|
-
if (!tokens) {
|
|
1013
|
-
return false;
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
if (this.oauthProvider.isTokenExpired()) {
|
|
1017
|
-
return await this.refreshToken();
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
return true;
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
929
|
/**
|
|
1024
930
|
* Reconnects to MCP server using existing OAuth provider from Redis
|
|
1025
931
|
* Used for session restoration in serverless environments
|
|
@@ -1176,10 +1082,14 @@ export class MCPClient {
|
|
|
1176
1082
|
|
|
1177
1083
|
/**
|
|
1178
1084
|
* Gets MCP server configuration for all active user sessions
|
|
1179
|
-
* Loads sessions from
|
|
1180
|
-
*
|
|
1085
|
+
* Loads sessions from storage and returns server connection metadata.
|
|
1086
|
+
* OAuth refresh is handled by SDK transports through their authProvider.
|
|
1087
|
+
* @deprecated This returns legacy connection metadata only and does not
|
|
1088
|
+
* include OAuth tokens or generated Authorization headers. Prefer
|
|
1089
|
+
* MultiSessionClient or explicit MCPClient instances so SDK transports can
|
|
1090
|
+
* own OAuth refresh and reauthorization.
|
|
1181
1091
|
* @param userId - User ID to fetch sessions for
|
|
1182
|
-
* @returns Object keyed by sanitized server labels containing transport
|
|
1092
|
+
* @returns Object keyed by sanitized server labels containing transport and url.
|
|
1183
1093
|
* @static
|
|
1184
1094
|
*/
|
|
1185
1095
|
static async getMcpServerConfig(userId: string): Promise<Record<string, any>> {
|
|
@@ -1202,34 +1112,6 @@ export class MCPClient {
|
|
|
1202
1112
|
return;
|
|
1203
1113
|
}
|
|
1204
1114
|
|
|
1205
|
-
// Get OAuth headers if session requires authentication
|
|
1206
|
-
let headers: Record<string, string> | undefined;
|
|
1207
|
-
try {
|
|
1208
|
-
// Inject existing session data to avoid redundant session store reads in initialize()
|
|
1209
|
-
const client = new MCPClient({
|
|
1210
|
-
userId,
|
|
1211
|
-
sessionId,
|
|
1212
|
-
serverId: sessionData.serverId,
|
|
1213
|
-
serverUrl: sessionData.serverUrl,
|
|
1214
|
-
callbackUrl: sessionData.callbackUrl,
|
|
1215
|
-
serverName: sessionData.serverName,
|
|
1216
|
-
transportType: sessionData.transportType,
|
|
1217
|
-
headers: sessionData.headers,
|
|
1218
|
-
});
|
|
1219
|
-
|
|
1220
|
-
await client.initialize();
|
|
1221
|
-
|
|
1222
|
-
const hasValidTokens = await client.getValidTokens();
|
|
1223
|
-
if (hasValidTokens && client.oauthProvider) {
|
|
1224
|
-
const tokens = await client.oauthProvider.tokens();
|
|
1225
|
-
if (tokens?.access_token) {
|
|
1226
|
-
headers = { Authorization: `Bearer ${tokens.access_token}` };
|
|
1227
|
-
}
|
|
1228
|
-
}
|
|
1229
|
-
} catch (error) {
|
|
1230
|
-
console.warn(`[MCP] Failed to get OAuth tokens for ${sessionId}:`, error);
|
|
1231
|
-
}
|
|
1232
|
-
|
|
1233
1115
|
// Build server config
|
|
1234
1116
|
const label = sanitizeServerLabel(
|
|
1235
1117
|
sessionData.serverName || sessionData.serverId || 'server'
|
|
@@ -1242,7 +1124,6 @@ export class MCPClient {
|
|
|
1242
1124
|
serverName: sessionData.serverName,
|
|
1243
1125
|
serverLabel: label,
|
|
1244
1126
|
}),
|
|
1245
|
-
...(headers && { headers }),
|
|
1246
1127
|
};
|
|
1247
1128
|
} catch (error) {
|
|
1248
1129
|
await sessions.delete(userId, sessionId);
|
|
@@ -180,7 +180,7 @@ export class NeonStorageBackend implements SessionStore {
|
|
|
180
180
|
updatedSession.active ?? false,
|
|
181
181
|
encryptObject(updatedSession.headers),
|
|
182
182
|
updatedSession.clientInformation,
|
|
183
|
-
encryptObject(updatedSession.tokens),
|
|
183
|
+
updatedSession.tokens === undefined ? null : encryptObject(updatedSession.tokens),
|
|
184
184
|
updatedSession.codeVerifier,
|
|
185
185
|
updatedSession.clientId,
|
|
186
186
|
expiresAt,
|
|
@@ -107,7 +107,7 @@ export class SupabaseStorageBackend implements SessionStore {
|
|
|
107
107
|
if ('active' in data) updateData.active = data.active;
|
|
108
108
|
if ('headers' in data) updateData.headers = encryptObject(data.headers);
|
|
109
109
|
if ('clientInformation' in data) updateData.client_information = data.clientInformation;
|
|
110
|
-
if ('tokens' in data) updateData.tokens = encryptObject(data.tokens);
|
|
110
|
+
if ('tokens' in data) updateData.tokens = data.tokens === undefined ? null : encryptObject(data.tokens);
|
|
111
111
|
if ('codeVerifier' in data) updateData.code_verifier = data.codeVerifier;
|
|
112
112
|
if ('clientId' in data) updateData.client_id = data.clientId;
|
|
113
113
|
|