@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.
Files changed (66) hide show
  1. package/bin/adcp.js +8 -5
  2. package/dist/lib/auth/oauth/ClientCredentialsFlow.js +4 -1
  3. package/dist/lib/auth/oauth/ClientCredentialsFlow.mjs +4 -1
  4. package/dist/lib/auth/oauth/MCPOAuthProvider.d.mts +25 -8
  5. package/dist/lib/auth/oauth/MCPOAuthProvider.d.ts +25 -8
  6. package/dist/lib/auth/oauth/MCPOAuthProvider.js +144 -19
  7. package/dist/lib/auth/oauth/MCPOAuthProvider.mjs +157 -19
  8. package/dist/lib/auth/oauth/NonInteractiveFlowHandler.d.mts +1 -1
  9. package/dist/lib/auth/oauth/NonInteractiveFlowHandler.d.ts +1 -1
  10. package/dist/lib/auth/oauth/NonInteractiveFlowHandler.js +1 -1
  11. package/dist/lib/auth/oauth/NonInteractiveFlowHandler.mjs +1 -1
  12. package/dist/lib/auth/oauth/client-credentials-schema.d.mts +17 -0
  13. package/dist/lib/auth/oauth/client-credentials-schema.d.ts +17 -0
  14. package/dist/lib/auth/oauth/client-credentials-schema.js +37 -0
  15. package/dist/lib/auth/oauth/client-credentials-schema.mjs +13 -0
  16. package/dist/lib/auth/oauth/diagnose.js +14 -0
  17. package/dist/lib/auth/oauth/diagnose.mjs +14 -0
  18. package/dist/lib/auth/oauth/file-storage.d.mts +4 -2
  19. package/dist/lib/auth/oauth/file-storage.d.ts +4 -2
  20. package/dist/lib/auth/oauth/file-storage.js +14 -1
  21. package/dist/lib/auth/oauth/file-storage.mjs +14 -1
  22. package/dist/lib/auth/oauth/index.d.mts +10 -6
  23. package/dist/lib/auth/oauth/index.d.ts +10 -6
  24. package/dist/lib/auth/oauth/index.js +9 -3
  25. package/dist/lib/auth/oauth/index.mjs +8 -3
  26. package/dist/lib/auth/oauth/types.d.mts +17 -0
  27. package/dist/lib/auth/oauth/types.d.ts +17 -0
  28. package/dist/lib/auth/oauth/types.js +40 -0
  29. package/dist/lib/auth/oauth/types.mjs +38 -0
  30. package/dist/lib/auth/oauth/web-flow.d.mts +2 -0
  31. package/dist/lib/auth/oauth/web-flow.d.ts +2 -0
  32. package/dist/lib/auth/oauth/web-flow.js +48 -5
  33. package/dist/lib/auth/oauth/web-flow.mjs +57 -6
  34. package/dist/lib/index.d.mts +1 -1
  35. package/dist/lib/index.d.ts +1 -1
  36. package/dist/lib/index.js +2 -0
  37. package/dist/lib/index.mjs +3 -1
  38. package/dist/lib/protocols/mcp.js +2 -0
  39. package/dist/lib/protocols/mcp.mjs +2 -0
  40. package/dist/lib/schemas/index.d.mts +2 -0
  41. package/dist/lib/schemas/index.d.ts +2 -0
  42. package/dist/lib/schemas/index.js +3 -0
  43. package/dist/lib/schemas/index.mjs +2 -0
  44. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  45. package/dist/lib/testing/client.js +8 -3
  46. package/dist/lib/testing/client.mjs +8 -3
  47. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  48. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  49. package/dist/lib/testing/types.d.mts +10 -1
  50. package/dist/lib/testing/types.d.ts +10 -1
  51. package/dist/lib/types/adcp.d.mts +6 -0
  52. package/dist/lib/types/adcp.d.ts +6 -0
  53. package/dist/lib/version.d.mts +3 -3
  54. package/dist/lib/version.d.ts +3 -3
  55. package/dist/lib/version.js +3 -3
  56. package/dist/lib/version.mjs +3 -3
  57. package/docs/TYPE-SUMMARY.md +1 -1
  58. package/docs/ZOD-SCHEMAS.md +19 -0
  59. package/docs/guides/OAUTH-ISSUER-BINDING.md +46 -0
  60. package/docs/guides/WEB-OAUTH.md +58 -163
  61. package/docs/guides/account-resolution.md +1 -1
  62. package/docs/llms.txt +1 -1
  63. package/docs/migration-14.0-to-14.1.md +1 -1
  64. package/docs/migration-14.x-rc-worksheet.md +8 -8
  65. package/docs/migration-oauth-issuer-bindings.md +17 -0
  66. 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
- // Spread the in-flight PKCE verifier too: if a prior attempt crashed mid-
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 (!agentConfig.oauth_tokens) {
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
- await options.storage.saveAgent(agent);
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
- await options.storage.saveAgent(agent);
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
- * // OAuth tokens stored here after auth flow
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: new CLIFlowHandler(),
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(): Promise<OAuthClientInformation | undefined>;
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(): Promise<OAuthTokens | undefined>;
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: 'all' | 'client' | 'tokens' | 'verifier'): Promise<void>;
121
+ invalidateCredentials(scope: Parameters<NonNullable<OAuthClientProvider['invalidateCredentials']>>[0]): Promise<void>;
122
+ private clearCredentials;
107
123
  /**
108
- * Persist agent config to storage if configured
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
- * // OAuth tokens stored here after auth flow
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: new CLIFlowHandler(),
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(): Promise<OAuthClientInformation | undefined>;
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(): Promise<OAuthTokens | undefined>;
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: 'all' | 'client' | 'tokens' | 'verifier'): Promise<void>;
121
+ invalidateCredentials(scope: Parameters<NonNullable<OAuthClientProvider['invalidateCredentials']>>[0]): Promise<void>;
122
+ private clearCredentials;
107
123
  /**
108
- * Persist agent config to storage if configured
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.persistAgent();
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
- delete this.agent.oauth_code_verifier;
127
- await this.persistAgent();
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
- await this.flowHandler.redirectToAuthorization(authorizationUrl);
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
- delete this.agent.oauth_tokens;
162
- delete this.agent.oauth_client;
163
- delete this.agent.oauth_code_verifier;
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
- delete this.agent.oauth_tokens;
273
+ this.agent.oauth_tokens = void 0;
167
274
  break;
168
275
  case "client":
169
- delete this.agent.oauth_client;
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
- delete this.agent.oauth_code_verifier;
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 agent config to storage if configured
296
+ * Persist a credential update without modifying independent browser state.
182
297
  */
183
- async persistAgent() {
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(this.agent);
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.invalidateCredentials("all");
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
  });