Implement MCP 2026-07-28 (#2286)
Co-authored-by: Matt <77928207+mattzcarey@users.noreply.github.com> Co-authored-by: Konstantin Konstantinov <KKonstantinov@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
e4227d135c
commit
1823aae891
1 changed files with 69131 additions and 9001 deletions
98
examples/oauth/simpleOAuthClientProvider.ts
Normal file
98
examples/oauth/simpleOAuthClientProvider.ts
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
import type {
|
||||
OAuthClientInformationMixed,
|
||||
OAuthClientMetadata,
|
||||
OAuthClientProvider,
|
||||
OAuthDiscoveryState,
|
||||
OAuthTokens
|
||||
} from '@modelcontextprotocol/client';
|
||||
import { validateClientMetadataUrl } from '@modelcontextprotocol/client';
|
||||
|
||||
/**
|
||||
* In-memory OAuth client provider for demonstration purposes.
|
||||
* In production, you should persist tokens and client credentials securely.
|
||||
*
|
||||
* Tokens and client credentials are stored as single-slot blobs. The SDK stamps an
|
||||
* `issuer` field onto every value it saves; round-tripping the blob unchanged means
|
||||
* a credential issued by one authorization server is never reused at another (the
|
||||
* SDK reads the stamp back as a key-not-found and re-registers / re-authorizes).
|
||||
* To hold credentials for several authorization servers at once, key your storage
|
||||
* on the `ctx.issuer` argument instead.
|
||||
*/
|
||||
export class InMemoryOAuthClientProvider implements OAuthClientProvider {
|
||||
private _clientInformation?: OAuthClientInformationMixed;
|
||||
private _tokens?: OAuthTokens;
|
||||
private _codeVerifier?: string;
|
||||
private _discoveryState?: OAuthDiscoveryState;
|
||||
|
||||
constructor(
|
||||
private readonly _redirectUrl: string | URL,
|
||||
private readonly _clientMetadata: OAuthClientMetadata,
|
||||
onRedirect?: (url: URL) => void,
|
||||
public readonly clientMetadataUrl?: string
|
||||
) {
|
||||
// Validate clientMetadataUrl at construction time (fail-fast)
|
||||
validateClientMetadataUrl(clientMetadataUrl);
|
||||
|
||||
this._onRedirect =
|
||||
onRedirect ||
|
||||
(url => {
|
||||
console.log(`Redirect to: ${url.toString()}`);
|
||||
});
|
||||
}
|
||||
|
||||
private _onRedirect: (url: URL) => void;
|
||||
|
||||
get redirectUrl(): string | URL {
|
||||
return this._redirectUrl;
|
||||
}
|
||||
|
||||
get clientMetadata(): OAuthClientMetadata {
|
||||
return this._clientMetadata;
|
||||
}
|
||||
|
||||
clientInformation(): OAuthClientInformationMixed | undefined {
|
||||
return this._clientInformation;
|
||||
}
|
||||
|
||||
saveClientInformation(clientInformation: OAuthClientInformationMixed): void {
|
||||
this._clientInformation = clientInformation;
|
||||
}
|
||||
|
||||
tokens(): OAuthTokens | undefined {
|
||||
return this._tokens;
|
||||
}
|
||||
|
||||
saveTokens(tokens: OAuthTokens): void {
|
||||
this._tokens = tokens;
|
||||
}
|
||||
|
||||
redirectToAuthorization(authorizationUrl: URL): void {
|
||||
this._onRedirect(authorizationUrl);
|
||||
}
|
||||
|
||||
saveCodeVerifier(codeVerifier: string): void {
|
||||
this._codeVerifier = codeVerifier;
|
||||
}
|
||||
|
||||
codeVerifier(): string {
|
||||
if (!this._codeVerifier) {
|
||||
throw new Error('No code verifier saved');
|
||||
}
|
||||
return this._codeVerifier;
|
||||
}
|
||||
|
||||
saveDiscoveryState(state: OAuthDiscoveryState): void {
|
||||
this._discoveryState = state;
|
||||
}
|
||||
|
||||
discoveryState(): OAuthDiscoveryState | undefined {
|
||||
return this._discoveryState;
|
||||
}
|
||||
|
||||
invalidateCredentials(scope: 'all' | 'client' | 'tokens' | 'verifier' | 'discovery'): void {
|
||||
if (scope === 'all' || scope === 'client') this._clientInformation = undefined;
|
||||
if (scope === 'all' || scope === 'tokens') this._tokens = undefined;
|
||||
if (scope === 'all' || scope === 'verifier') this._codeVerifier = undefined;
|
||||
if (scope === 'all' || scope === 'discovery') this._discoveryState = undefined;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue