@adcp/sdk 14.3.0 → 15.0.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/bin/adcp.js +8 -5
- package/dist/lib/auth/oauth/ClientCredentialsFlow.js +4 -1
- package/dist/lib/auth/oauth/ClientCredentialsFlow.mjs +4 -1
- package/dist/lib/auth/oauth/MCPOAuthProvider.d.mts +25 -8
- package/dist/lib/auth/oauth/MCPOAuthProvider.d.ts +25 -8
- package/dist/lib/auth/oauth/MCPOAuthProvider.js +144 -19
- package/dist/lib/auth/oauth/MCPOAuthProvider.mjs +157 -19
- package/dist/lib/auth/oauth/NonInteractiveFlowHandler.d.mts +1 -1
- package/dist/lib/auth/oauth/NonInteractiveFlowHandler.d.ts +1 -1
- package/dist/lib/auth/oauth/NonInteractiveFlowHandler.js +1 -1
- package/dist/lib/auth/oauth/NonInteractiveFlowHandler.mjs +1 -1
- package/dist/lib/auth/oauth/client-credentials-schema.d.mts +17 -0
- package/dist/lib/auth/oauth/client-credentials-schema.d.ts +17 -0
- package/dist/lib/auth/oauth/client-credentials-schema.js +37 -0
- package/dist/lib/auth/oauth/client-credentials-schema.mjs +13 -0
- package/dist/lib/auth/oauth/diagnose.js +14 -0
- package/dist/lib/auth/oauth/diagnose.mjs +14 -0
- package/dist/lib/auth/oauth/file-storage.d.mts +4 -2
- package/dist/lib/auth/oauth/file-storage.d.ts +4 -2
- package/dist/lib/auth/oauth/file-storage.js +14 -1
- package/dist/lib/auth/oauth/file-storage.mjs +14 -1
- package/dist/lib/auth/oauth/index.d.mts +10 -6
- package/dist/lib/auth/oauth/index.d.ts +10 -6
- package/dist/lib/auth/oauth/index.js +9 -3
- package/dist/lib/auth/oauth/index.mjs +8 -3
- package/dist/lib/auth/oauth/types.d.mts +17 -0
- package/dist/lib/auth/oauth/types.d.ts +17 -0
- package/dist/lib/auth/oauth/types.js +40 -0
- package/dist/lib/auth/oauth/types.mjs +38 -0
- package/dist/lib/auth/oauth/web-flow.d.mts +2 -0
- package/dist/lib/auth/oauth/web-flow.d.ts +2 -0
- package/dist/lib/auth/oauth/web-flow.js +48 -5
- package/dist/lib/auth/oauth/web-flow.mjs +57 -6
- package/dist/lib/index.d.mts +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.mjs +3 -1
- package/dist/lib/protocols/mcp.js +2 -0
- package/dist/lib/protocols/mcp.mjs +2 -0
- package/dist/lib/schemas/index.d.mts +2 -0
- package/dist/lib/schemas/index.d.ts +2 -0
- package/dist/lib/schemas/index.js +3 -0
- package/dist/lib/schemas/index.mjs +2 -0
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/testing/client.js +8 -3
- package/dist/lib/testing/client.mjs +8 -3
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/testing/types.d.mts +10 -1
- package/dist/lib/testing/types.d.ts +10 -1
- package/dist/lib/types/adcp.d.mts +6 -0
- package/dist/lib/types/adcp.d.ts +6 -0
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.mjs +3 -3
- package/docs/TYPE-SUMMARY.md +1 -1
- package/docs/ZOD-SCHEMAS.md +19 -0
- package/docs/guides/OAUTH-ISSUER-BINDING.md +46 -0
- package/docs/guides/WEB-OAUTH.md +58 -163
- package/docs/guides/account-resolution.md +1 -1
- package/docs/llms.txt +1 -1
- package/docs/migration-14.0-to-14.1.md +1 -1
- package/docs/migration-14.x-rc-worksheet.md +8 -8
- package/docs/migration-oauth-issuer-bindings.md +17 -0
- package/package.json +5 -5
package/bin/adcp.js
CHANGED
|
@@ -1386,9 +1386,7 @@ async function ensureOAuthTokensForAlias(alias, url, { quiet = false, allowHttp
|
|
|
1386
1386
|
return existing;
|
|
1387
1387
|
}
|
|
1388
1388
|
|
|
1389
|
-
//
|
|
1390
|
-
// flow the verifier lives on the saved record, and without it the MCP SDK
|
|
1391
|
-
// throws "No PKCE code verifier found" when the AS redirects back.
|
|
1389
|
+
// A fresh login starts a new PKCE leg and rediscovers the authorization server.
|
|
1392
1390
|
const tempAgent = {
|
|
1393
1391
|
id: alias,
|
|
1394
1392
|
name: alias,
|
|
@@ -1396,7 +1394,6 @@ async function ensureOAuthTokensForAlias(alias, url, { quiet = false, allowHttp
|
|
|
1396
1394
|
protocol: 'mcp',
|
|
1397
1395
|
...(existing?.oauth_client && { oauth_client: existing.oauth_client }),
|
|
1398
1396
|
...(existing?.oauth_tokens && { oauth_tokens: existing.oauth_tokens }),
|
|
1399
|
-
...(existing?.oauth_code_verifier && { oauth_code_verifier: existing.oauth_code_verifier }),
|
|
1400
1397
|
};
|
|
1401
1398
|
|
|
1402
1399
|
const { Client: MCPClient } = require('@modelcontextprotocol/sdk/client/index.js');
|
|
@@ -6662,7 +6659,12 @@ credential material — never sync or commit.
|
|
|
6662
6659
|
}
|
|
6663
6660
|
|
|
6664
6661
|
const agentConfig = getAgent(alias);
|
|
6665
|
-
if (
|
|
6662
|
+
if (
|
|
6663
|
+
!agentConfig.oauth_tokens &&
|
|
6664
|
+
!agentConfig.oauth_client &&
|
|
6665
|
+
!agentConfig.oauth_code_verifier &&
|
|
6666
|
+
!agentConfig.oauth_discovery_state
|
|
6667
|
+
) {
|
|
6666
6668
|
console.log(`\nAgent '${alias}' has no OAuth tokens to clear.\n`);
|
|
6667
6669
|
process.exit(0);
|
|
6668
6670
|
}
|
|
@@ -6671,6 +6673,7 @@ credential material — never sync or commit.
|
|
|
6671
6673
|
delete agentConfig.oauth_tokens;
|
|
6672
6674
|
delete agentConfig.oauth_client;
|
|
6673
6675
|
delete agentConfig.oauth_code_verifier;
|
|
6676
|
+
delete agentConfig.oauth_discovery_state;
|
|
6674
6677
|
saveAgent(alias, agentConfig);
|
|
6675
6678
|
|
|
6676
6679
|
console.log(`\n✅ Cleared OAuth tokens for '${alias}'`);
|
|
@@ -247,7 +247,10 @@ async function ensureClientCredentialsTokens(agent, options = {}) {
|
|
|
247
247
|
});
|
|
248
248
|
agent.oauth_tokens = tokens;
|
|
249
249
|
if (options.storage) {
|
|
250
|
-
|
|
250
|
+
const refreshedAgent = { ...agent };
|
|
251
|
+
delete refreshedAgent.oauth_code_verifier;
|
|
252
|
+
delete refreshedAgent.oauth_discovery_state;
|
|
253
|
+
await options.storage.saveAgent(refreshedAgent);
|
|
251
254
|
}
|
|
252
255
|
return tokens;
|
|
253
256
|
} finally {
|
|
@@ -222,7 +222,10 @@ async function ensureClientCredentialsTokens(agent, options = {}) {
|
|
|
222
222
|
});
|
|
223
223
|
agent.oauth_tokens = tokens;
|
|
224
224
|
if (options.storage) {
|
|
225
|
-
|
|
225
|
+
const refreshedAgent = { ...agent };
|
|
226
|
+
delete refreshedAgent.oauth_code_verifier;
|
|
227
|
+
delete refreshedAgent.oauth_discovery_state;
|
|
228
|
+
await options.storage.saveAgent(refreshedAgent);
|
|
226
229
|
}
|
|
227
230
|
return tokens;
|
|
228
231
|
} finally {
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* Implements the MCP SDK's OAuthClientProvider interface
|
|
5
5
|
* using AgentConfig for token storage.
|
|
6
6
|
*/
|
|
7
|
-
import type { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js';
|
|
7
|
+
import type { OAuthClientProvider, OAuthDiscoveryState } from '@modelcontextprotocol/sdk/client/auth.js';
|
|
8
8
|
import type { OAuthClientMetadata, OAuthClientInformation, OAuthClientInformationFull, OAuthTokens, OAuthFlowHandler, OAuthProviderConfig, OAuthConfigStorage, AgentConfig } from './types.mjs';
|
|
9
|
+
export declare function assertLegacyOAuthSdk(): void;
|
|
9
10
|
/**
|
|
10
11
|
* MCP OAuth Client Provider
|
|
11
12
|
*
|
|
@@ -19,13 +20,15 @@ import type { OAuthClientMetadata, OAuthClientInformation, OAuthClientInformatio
|
|
|
19
20
|
* name: 'My Agent',
|
|
20
21
|
* agent_uri: 'https://agent.example.com/mcp',
|
|
21
22
|
* protocol: 'mcp',
|
|
22
|
-
* //
|
|
23
|
-
* oauth_tokens: { access_token: '...', refresh_token: '...' }
|
|
23
|
+
* // A fresh interactive flow saves issuer-bound credentials afterward.
|
|
24
24
|
* };
|
|
25
25
|
*
|
|
26
|
+
* const flowHandler = new CLIFlowHandler();
|
|
26
27
|
* const provider = new MCPOAuthProvider({
|
|
27
28
|
* agent,
|
|
28
|
-
* flowHandler
|
|
29
|
+
* flowHandler,
|
|
30
|
+
* clientMetadata: { ...DEFAULT_CLIENT_METADATA, redirect_uris: [flowHandler.getRedirectUrl().toString()] },
|
|
31
|
+
* allowInteractiveAuthorization: true,
|
|
29
32
|
* storage: myConfigStorage // Optional: persists tokens
|
|
30
33
|
* });
|
|
31
34
|
*
|
|
@@ -41,6 +44,8 @@ export declare class MCPOAuthProvider implements OAuthClientProvider {
|
|
|
41
44
|
private readonly _clientMetadata;
|
|
42
45
|
private readonly allowHttp;
|
|
43
46
|
private readonly configuredResourceOverride?;
|
|
47
|
+
private readonly allowInteractiveAuthorization;
|
|
48
|
+
private pendingDiscoveryState?;
|
|
44
49
|
constructor(config: OAuthProviderConfig);
|
|
45
50
|
/**
|
|
46
51
|
* Create a provider for CLI usage
|
|
@@ -72,7 +77,9 @@ export declare class MCPOAuthProvider implements OAuthClientProvider {
|
|
|
72
77
|
/**
|
|
73
78
|
* Load client information from agent config
|
|
74
79
|
*/
|
|
75
|
-
clientInformation(
|
|
80
|
+
clientInformation(ctx?: {
|
|
81
|
+
issuer: string;
|
|
82
|
+
}): Promise<OAuthClientInformation | undefined>;
|
|
76
83
|
/**
|
|
77
84
|
* Save client information after dynamic registration
|
|
78
85
|
*/
|
|
@@ -80,7 +87,9 @@ export declare class MCPOAuthProvider implements OAuthClientProvider {
|
|
|
80
87
|
/**
|
|
81
88
|
* Load existing tokens from agent config
|
|
82
89
|
*/
|
|
83
|
-
tokens(
|
|
90
|
+
tokens(ctx?: {
|
|
91
|
+
issuer: string;
|
|
92
|
+
}): Promise<OAuthTokens | undefined>;
|
|
84
93
|
/**
|
|
85
94
|
* Save tokens after authorization
|
|
86
95
|
* Also cleans up the temporary code verifier
|
|
@@ -90,6 +99,12 @@ export declare class MCPOAuthProvider implements OAuthClientProvider {
|
|
|
90
99
|
* Redirect user to authorization URL
|
|
91
100
|
*/
|
|
92
101
|
redirectToAuthorization(authorizationUrl: URL): Promise<void>;
|
|
102
|
+
/** Persist the authorization-server identity across the callback leg. */
|
|
103
|
+
saveDiscoveryState(state: OAuthDiscoveryState): Promise<void>;
|
|
104
|
+
discoveryState(): Promise<OAuthDiscoveryState | undefined>;
|
|
105
|
+
private validateDiscoveryState;
|
|
106
|
+
private checkIssuerContext;
|
|
107
|
+
private ownerReauthorizationRequired;
|
|
93
108
|
/**
|
|
94
109
|
* Save PKCE code verifier
|
|
95
110
|
*/
|
|
@@ -103,10 +118,12 @@ export declare class MCPOAuthProvider implements OAuthClientProvider {
|
|
|
103
118
|
/**
|
|
104
119
|
* Invalidate credentials when server indicates they're invalid
|
|
105
120
|
*/
|
|
106
|
-
invalidateCredentials(scope: '
|
|
121
|
+
invalidateCredentials(scope: Parameters<NonNullable<OAuthClientProvider['invalidateCredentials']>>[0]): Promise<void>;
|
|
122
|
+
private clearCredentials;
|
|
107
123
|
/**
|
|
108
|
-
* Persist
|
|
124
|
+
* Persist a credential update without modifying independent browser state.
|
|
109
125
|
*/
|
|
126
|
+
private persistCredentials;
|
|
110
127
|
private persistAgent;
|
|
111
128
|
/**
|
|
112
129
|
* Wait for the OAuth callback
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* Implements the MCP SDK's OAuthClientProvider interface
|
|
5
5
|
* using AgentConfig for token storage.
|
|
6
6
|
*/
|
|
7
|
-
import type { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js';
|
|
7
|
+
import type { OAuthClientProvider, OAuthDiscoveryState } from '@modelcontextprotocol/sdk/client/auth.js';
|
|
8
8
|
import type { OAuthClientMetadata, OAuthClientInformation, OAuthClientInformationFull, OAuthTokens, OAuthFlowHandler, OAuthProviderConfig, OAuthConfigStorage, AgentConfig } from './types';
|
|
9
|
+
export declare function assertLegacyOAuthSdk(): void;
|
|
9
10
|
/**
|
|
10
11
|
* MCP OAuth Client Provider
|
|
11
12
|
*
|
|
@@ -19,13 +20,15 @@ import type { OAuthClientMetadata, OAuthClientInformation, OAuthClientInformatio
|
|
|
19
20
|
* name: 'My Agent',
|
|
20
21
|
* agent_uri: 'https://agent.example.com/mcp',
|
|
21
22
|
* protocol: 'mcp',
|
|
22
|
-
* //
|
|
23
|
-
* oauth_tokens: { access_token: '...', refresh_token: '...' }
|
|
23
|
+
* // A fresh interactive flow saves issuer-bound credentials afterward.
|
|
24
24
|
* };
|
|
25
25
|
*
|
|
26
|
+
* const flowHandler = new CLIFlowHandler();
|
|
26
27
|
* const provider = new MCPOAuthProvider({
|
|
27
28
|
* agent,
|
|
28
|
-
* flowHandler
|
|
29
|
+
* flowHandler,
|
|
30
|
+
* clientMetadata: { ...DEFAULT_CLIENT_METADATA, redirect_uris: [flowHandler.getRedirectUrl().toString()] },
|
|
31
|
+
* allowInteractiveAuthorization: true,
|
|
29
32
|
* storage: myConfigStorage // Optional: persists tokens
|
|
30
33
|
* });
|
|
31
34
|
*
|
|
@@ -41,6 +44,8 @@ export declare class MCPOAuthProvider implements OAuthClientProvider {
|
|
|
41
44
|
private readonly _clientMetadata;
|
|
42
45
|
private readonly allowHttp;
|
|
43
46
|
private readonly configuredResourceOverride?;
|
|
47
|
+
private readonly allowInteractiveAuthorization;
|
|
48
|
+
private pendingDiscoveryState?;
|
|
44
49
|
constructor(config: OAuthProviderConfig);
|
|
45
50
|
/**
|
|
46
51
|
* Create a provider for CLI usage
|
|
@@ -72,7 +77,9 @@ export declare class MCPOAuthProvider implements OAuthClientProvider {
|
|
|
72
77
|
/**
|
|
73
78
|
* Load client information from agent config
|
|
74
79
|
*/
|
|
75
|
-
clientInformation(
|
|
80
|
+
clientInformation(ctx?: {
|
|
81
|
+
issuer: string;
|
|
82
|
+
}): Promise<OAuthClientInformation | undefined>;
|
|
76
83
|
/**
|
|
77
84
|
* Save client information after dynamic registration
|
|
78
85
|
*/
|
|
@@ -80,7 +87,9 @@ export declare class MCPOAuthProvider implements OAuthClientProvider {
|
|
|
80
87
|
/**
|
|
81
88
|
* Load existing tokens from agent config
|
|
82
89
|
*/
|
|
83
|
-
tokens(
|
|
90
|
+
tokens(ctx?: {
|
|
91
|
+
issuer: string;
|
|
92
|
+
}): Promise<OAuthTokens | undefined>;
|
|
84
93
|
/**
|
|
85
94
|
* Save tokens after authorization
|
|
86
95
|
* Also cleans up the temporary code verifier
|
|
@@ -90,6 +99,12 @@ export declare class MCPOAuthProvider implements OAuthClientProvider {
|
|
|
90
99
|
* Redirect user to authorization URL
|
|
91
100
|
*/
|
|
92
101
|
redirectToAuthorization(authorizationUrl: URL): Promise<void>;
|
|
102
|
+
/** Persist the authorization-server identity across the callback leg. */
|
|
103
|
+
saveDiscoveryState(state: OAuthDiscoveryState): Promise<void>;
|
|
104
|
+
discoveryState(): Promise<OAuthDiscoveryState | undefined>;
|
|
105
|
+
private validateDiscoveryState;
|
|
106
|
+
private checkIssuerContext;
|
|
107
|
+
private ownerReauthorizationRequired;
|
|
93
108
|
/**
|
|
94
109
|
* Save PKCE code verifier
|
|
95
110
|
*/
|
|
@@ -103,10 +118,12 @@ export declare class MCPOAuthProvider implements OAuthClientProvider {
|
|
|
103
118
|
/**
|
|
104
119
|
* Invalidate credentials when server indicates they're invalid
|
|
105
120
|
*/
|
|
106
|
-
invalidateCredentials(scope: '
|
|
121
|
+
invalidateCredentials(scope: Parameters<NonNullable<OAuthClientProvider['invalidateCredentials']>>[0]): Promise<void>;
|
|
122
|
+
private clearCredentials;
|
|
107
123
|
/**
|
|
108
|
-
* Persist
|
|
124
|
+
* Persist a credential update without modifying independent browser state.
|
|
109
125
|
*/
|
|
126
|
+
private persistCredentials;
|
|
110
127
|
private persistAgent;
|
|
111
128
|
/**
|
|
112
129
|
* Wait for the OAuth callback
|
|
@@ -18,12 +18,40 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var MCPOAuthProvider_exports = {};
|
|
20
20
|
__export(MCPOAuthProvider_exports, {
|
|
21
|
-
MCPOAuthProvider: () => MCPOAuthProvider
|
|
21
|
+
MCPOAuthProvider: () => MCPOAuthProvider,
|
|
22
|
+
assertLegacyOAuthSdk: () => assertLegacyOAuthSdk
|
|
22
23
|
});
|
|
23
24
|
module.exports = __toCommonJS(MCPOAuthProvider_exports);
|
|
24
25
|
var import_types = require('./types.js');
|
|
25
26
|
var import_crypto = require("crypto");
|
|
27
|
+
var import_node_fs = require("node:fs");
|
|
28
|
+
var import_node_path = require("node:path");
|
|
29
|
+
var import_node_module = require("node:module");
|
|
26
30
|
var import_resource_url = require('./resource-url.js');
|
|
31
|
+
let legacyOAuthSdkChecked = false;
|
|
32
|
+
function assertLegacyOAuthSdk() {
|
|
33
|
+
if (legacyOAuthSdkChecked) return;
|
|
34
|
+
try {
|
|
35
|
+
const clientPath = (0, import_node_module.createRequire)((0, import_node_path.resolve)(__dirname, "MCPOAuthProvider.js")).resolve(
|
|
36
|
+
"@modelcontextprotocol/sdk/client/index.js"
|
|
37
|
+
);
|
|
38
|
+
const { version } = JSON.parse((0, import_node_fs.readFileSync)((0, import_node_path.resolve)((0, import_node_path.dirname)(clientPath), "../../../package.json"), "utf8"));
|
|
39
|
+
const match = typeof version === "string" && /^1\.(\d+)\.\d+$/.exec(version);
|
|
40
|
+
if (!match || Number(match[1]) < 31) {
|
|
41
|
+
throw new import_types.OAuthError(
|
|
42
|
+
"Legacy MCP OAuth requires @modelcontextprotocol/sdk >=1.31.0 within major 1. Upgrade the installed peer dependency.",
|
|
43
|
+
"mcp_oauth_sdk_upgrade_required"
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
} catch (error) {
|
|
47
|
+
if (error instanceof import_types.OAuthError) throw error;
|
|
48
|
+
throw new import_types.OAuthError(
|
|
49
|
+
"Cannot verify a patched legacy MCP SDK. Install @modelcontextprotocol/sdk ^1.31.0 and keep it external when bundling.",
|
|
50
|
+
"mcp_oauth_sdk_upgrade_required"
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
legacyOAuthSdkChecked = true;
|
|
54
|
+
}
|
|
27
55
|
class MCPOAuthProvider {
|
|
28
56
|
agent;
|
|
29
57
|
storage;
|
|
@@ -31,6 +59,8 @@ class MCPOAuthProvider {
|
|
|
31
59
|
_clientMetadata;
|
|
32
60
|
allowHttp;
|
|
33
61
|
configuredResourceOverride;
|
|
62
|
+
allowInteractiveAuthorization;
|
|
63
|
+
pendingDiscoveryState;
|
|
34
64
|
constructor(config) {
|
|
35
65
|
this.agent = config.agent;
|
|
36
66
|
this.storage = config.storage;
|
|
@@ -38,6 +68,7 @@ class MCPOAuthProvider {
|
|
|
38
68
|
this._clientMetadata = config.clientMetadata;
|
|
39
69
|
this.allowHttp = config.allowHttp === true;
|
|
40
70
|
this.configuredResourceOverride = config.resourceOverride;
|
|
71
|
+
this.allowInteractiveAuthorization = config.allowInteractiveAuthorization === true;
|
|
41
72
|
}
|
|
42
73
|
/**
|
|
43
74
|
* Create a provider for CLI usage
|
|
@@ -54,7 +85,8 @@ class MCPOAuthProvider {
|
|
|
54
85
|
storage,
|
|
55
86
|
clientMetadata,
|
|
56
87
|
allowHttp: options?.allowHttp,
|
|
57
|
-
resourceOverride: options?.resourceOverride
|
|
88
|
+
resourceOverride: options?.resourceOverride,
|
|
89
|
+
allowInteractiveAuthorization: true
|
|
58
90
|
});
|
|
59
91
|
}
|
|
60
92
|
// ========================================
|
|
@@ -95,8 +127,14 @@ class MCPOAuthProvider {
|
|
|
95
127
|
/**
|
|
96
128
|
* Load client information from agent config
|
|
97
129
|
*/
|
|
98
|
-
async clientInformation() {
|
|
130
|
+
async clientInformation(ctx) {
|
|
131
|
+
const issuer = this.checkIssuerContext(ctx);
|
|
132
|
+
if (issuer && !this.agent.oauth_client && !this.allowInteractiveAuthorization) {
|
|
133
|
+
throw this.ownerReauthorizationRequired();
|
|
134
|
+
}
|
|
99
135
|
if (this.agent.oauth_client) {
|
|
136
|
+
if (this.agent.oauth_client.client_secret) assertLegacyOAuthSdk();
|
|
137
|
+
(0, import_types.assertOAuthCredentialIssuer)(this.agent.oauth_client, void 0, !!this.agent.oauth_client.client_secret);
|
|
100
138
|
return (0, import_types.toMCPClientInfo)(this.agent.oauth_client);
|
|
101
139
|
}
|
|
102
140
|
return void 0;
|
|
@@ -106,13 +144,16 @@ class MCPOAuthProvider {
|
|
|
106
144
|
*/
|
|
107
145
|
async saveClientInformation(clientInfo) {
|
|
108
146
|
this.agent.oauth_client = (0, import_types.fromMCPClientInfo)(clientInfo);
|
|
109
|
-
await this.
|
|
147
|
+
await this.persistCredentials();
|
|
110
148
|
}
|
|
111
149
|
/**
|
|
112
150
|
* Load existing tokens from agent config
|
|
113
151
|
*/
|
|
114
|
-
async tokens() {
|
|
152
|
+
async tokens(ctx) {
|
|
153
|
+
this.checkIssuerContext(ctx);
|
|
115
154
|
if (this.agent.oauth_tokens) {
|
|
155
|
+
if (this.agent.oauth_tokens.refresh_token) assertLegacyOAuthSdk();
|
|
156
|
+
(0, import_types.assertOAuthCredentialIssuer)(this.agent.oauth_tokens, void 0, !!this.agent.oauth_tokens.refresh_token);
|
|
116
157
|
return (0, import_types.toMCPTokens)(this.agent.oauth_tokens);
|
|
117
158
|
}
|
|
118
159
|
return void 0;
|
|
@@ -123,19 +164,72 @@ class MCPOAuthProvider {
|
|
|
123
164
|
*/
|
|
124
165
|
async saveTokens(tokens) {
|
|
125
166
|
this.agent.oauth_tokens = (0, import_types.fromMCPTokens)(tokens);
|
|
126
|
-
|
|
127
|
-
|
|
167
|
+
if (this.allowInteractiveAuthorization) {
|
|
168
|
+
this.agent.oauth_code_verifier = void 0;
|
|
169
|
+
this.agent.oauth_discovery_state = void 0;
|
|
170
|
+
}
|
|
171
|
+
this.pendingDiscoveryState = void 0;
|
|
172
|
+
await this.persistCredentials();
|
|
128
173
|
}
|
|
129
174
|
/**
|
|
130
175
|
* Redirect user to authorization URL
|
|
131
176
|
*/
|
|
132
177
|
async redirectToAuthorization(authorizationUrl) {
|
|
133
|
-
|
|
178
|
+
if (!this.allowInteractiveAuthorization) throw this.ownerReauthorizationRequired("interactive_required");
|
|
179
|
+
try {
|
|
180
|
+
await this.flowHandler.redirectToAuthorization(authorizationUrl);
|
|
181
|
+
} catch (error) {
|
|
182
|
+
await this.invalidateCredentials("verifier");
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/** Persist the authorization-server identity across the callback leg. */
|
|
187
|
+
async saveDiscoveryState(state) {
|
|
188
|
+
this.validateDiscoveryState(state);
|
|
189
|
+
if (!this.agent.oauth_client && !this.allowInteractiveAuthorization) throw this.ownerReauthorizationRequired();
|
|
190
|
+
this.pendingDiscoveryState = structuredClone(state);
|
|
191
|
+
if (this.allowInteractiveAuthorization) {
|
|
192
|
+
this.agent.oauth_discovery_state = structuredClone(state);
|
|
193
|
+
await this.persistAgent();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
async discoveryState() {
|
|
197
|
+
if (!this.allowInteractiveAuthorization) return void 0;
|
|
198
|
+
if (!this.agent.oauth_code_verifier) return void 0;
|
|
199
|
+
const state = this.pendingDiscoveryState ?? this.agent.oauth_discovery_state;
|
|
200
|
+
if (!state) return void 0;
|
|
201
|
+
this.validateDiscoveryState(state);
|
|
202
|
+
this.pendingDiscoveryState = structuredClone(state);
|
|
203
|
+
return structuredClone(state);
|
|
204
|
+
}
|
|
205
|
+
validateDiscoveryState(state) {
|
|
206
|
+
(0, import_types.assertOAuthServerIssuer)(state.authorizationServerMetadata, String(state.authorizationServerUrl));
|
|
207
|
+
this.checkIssuerContext({ issuer: String(state.authorizationServerUrl) });
|
|
208
|
+
}
|
|
209
|
+
checkIssuerContext(ctx) {
|
|
210
|
+
const issuer = ctx?.issuer ?? this.pendingDiscoveryState?.authorizationServerUrl;
|
|
211
|
+
if (issuer !== void 0) {
|
|
212
|
+
if (this.agent.oauth_tokens) {
|
|
213
|
+
(0, import_types.assertOAuthCredentialIssuer)(this.agent.oauth_tokens, issuer, !!this.agent.oauth_tokens.refresh_token);
|
|
214
|
+
}
|
|
215
|
+
if (this.agent.oauth_client) {
|
|
216
|
+
(0, import_types.assertOAuthCredentialIssuer)(this.agent.oauth_client, issuer, !!this.agent.oauth_client.client_secret);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return issuer;
|
|
220
|
+
}
|
|
221
|
+
ownerReauthorizationRequired(code = "owner_reauthorization_required") {
|
|
222
|
+
return new import_types.OAuthError(
|
|
223
|
+
"OAuth owner reauthorization is required; this provider will not automatically clear credentials or register a new client. CLI: adcp <alias> --clear-oauth, then adcp <alias> --oauth.",
|
|
224
|
+
code,
|
|
225
|
+
this.agent.id
|
|
226
|
+
);
|
|
134
227
|
}
|
|
135
228
|
/**
|
|
136
229
|
* Save PKCE code verifier
|
|
137
230
|
*/
|
|
138
231
|
async saveCodeVerifier(codeVerifier) {
|
|
232
|
+
if (!this.allowInteractiveAuthorization) throw this.ownerReauthorizationRequired();
|
|
139
233
|
this.agent.oauth_code_verifier = codeVerifier;
|
|
140
234
|
await this.persistAgent();
|
|
141
235
|
}
|
|
@@ -145,6 +239,7 @@ class MCPOAuthProvider {
|
|
|
145
239
|
* retrieves it here during token exchange.
|
|
146
240
|
*/
|
|
147
241
|
async codeVerifier() {
|
|
242
|
+
if (!this.allowInteractiveAuthorization) throw this.ownerReauthorizationRequired();
|
|
148
243
|
if (!this.agent.oauth_code_verifier) {
|
|
149
244
|
throw new Error(
|
|
150
245
|
"No PKCE code verifier found. The OAuth flow may have been interrupted or the agent config was modified. Please try authenticating again."
|
|
@@ -156,20 +251,40 @@ class MCPOAuthProvider {
|
|
|
156
251
|
* Invalidate credentials when server indicates they're invalid
|
|
157
252
|
*/
|
|
158
253
|
async invalidateCredentials(scope) {
|
|
254
|
+
if (!this.allowInteractiveAuthorization && (scope === "discovery" || scope === "verifier")) {
|
|
255
|
+
this.pendingDiscoveryState = void 0;
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (!this.allowInteractiveAuthorization && (scope === "all" || scope === "client" || scope === "tokens")) {
|
|
259
|
+
throw this.ownerReauthorizationRequired();
|
|
260
|
+
}
|
|
261
|
+
await this.clearCredentials(scope);
|
|
262
|
+
}
|
|
263
|
+
async clearCredentials(scope) {
|
|
159
264
|
switch (scope) {
|
|
160
265
|
case "all":
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
266
|
+
this.pendingDiscoveryState = void 0;
|
|
267
|
+
this.agent.oauth_discovery_state = void 0;
|
|
268
|
+
this.agent.oauth_tokens = void 0;
|
|
269
|
+
this.agent.oauth_client = void 0;
|
|
270
|
+
this.agent.oauth_code_verifier = void 0;
|
|
164
271
|
break;
|
|
165
272
|
case "tokens":
|
|
166
|
-
|
|
273
|
+
this.agent.oauth_tokens = void 0;
|
|
167
274
|
break;
|
|
168
275
|
case "client":
|
|
169
|
-
|
|
276
|
+
this.pendingDiscoveryState = void 0;
|
|
277
|
+
this.agent.oauth_discovery_state = void 0;
|
|
278
|
+
this.agent.oauth_client = void 0;
|
|
279
|
+
break;
|
|
280
|
+
case "discovery":
|
|
281
|
+
this.pendingDiscoveryState = void 0;
|
|
282
|
+
this.agent.oauth_discovery_state = void 0;
|
|
170
283
|
break;
|
|
171
284
|
case "verifier":
|
|
172
|
-
|
|
285
|
+
this.pendingDiscoveryState = void 0;
|
|
286
|
+
this.agent.oauth_discovery_state = void 0;
|
|
287
|
+
this.agent.oauth_code_verifier = void 0;
|
|
173
288
|
break;
|
|
174
289
|
}
|
|
175
290
|
await this.persistAgent();
|
|
@@ -178,11 +293,20 @@ class MCPOAuthProvider {
|
|
|
178
293
|
// Additional methods
|
|
179
294
|
// ========================================
|
|
180
295
|
/**
|
|
181
|
-
* Persist
|
|
296
|
+
* Persist a credential update without modifying independent browser state.
|
|
182
297
|
*/
|
|
183
|
-
async
|
|
298
|
+
async persistCredentials() {
|
|
299
|
+
let savedAgent = this.agent;
|
|
300
|
+
if (!this.allowInteractiveAuthorization) {
|
|
301
|
+
savedAgent = { ...this.agent };
|
|
302
|
+
delete savedAgent.oauth_code_verifier;
|
|
303
|
+
delete savedAgent.oauth_discovery_state;
|
|
304
|
+
}
|
|
305
|
+
await this.persistAgent(savedAgent);
|
|
306
|
+
}
|
|
307
|
+
async persistAgent(agent = this.agent) {
|
|
184
308
|
if (this.storage) {
|
|
185
|
-
await this.storage.saveAgent(
|
|
309
|
+
await this.storage.saveAgent(agent);
|
|
186
310
|
}
|
|
187
311
|
}
|
|
188
312
|
/**
|
|
@@ -224,7 +348,7 @@ class MCPOAuthProvider {
|
|
|
224
348
|
* Clear all OAuth data for this agent
|
|
225
349
|
*/
|
|
226
350
|
async clearAuth() {
|
|
227
|
-
await this.
|
|
351
|
+
await this.clearCredentials("all");
|
|
228
352
|
}
|
|
229
353
|
/**
|
|
230
354
|
* Get the agent config this provider manages
|
|
@@ -243,5 +367,6 @@ class MCPOAuthProvider {
|
|
|
243
367
|
}
|
|
244
368
|
// Annotate the CommonJS export names for ESM import in node:
|
|
245
369
|
0 && (module.exports = {
|
|
246
|
-
MCPOAuthProvider
|
|
370
|
+
MCPOAuthProvider,
|
|
371
|
+
assertLegacyOAuthSdk
|
|
247
372
|
});
|