TypeScript SDK for implementing the Model Context Protocol, enabling developers to build MCP servers and clients with support for multiple transports, tools, resources, prompts, and authentication
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Complete OAuth 2.0 support: authorization code flow with PKCE, client registration, token management, and revocation.
import { mcpAuthRouter } from '@modelcontextprotocol/sdk/server/auth/router.js';
function mcpAuthRouter(options: {
provider: OAuthServerProvider;
issuerUrl: URL;
baseUrl: URL;
serviceDocumentationUrl?: URL;
rateLimit?: RateLimitOptions;
}): express.Router;interface OAuthServerProvider {
get clientsStore(): OAuthRegisteredClientsStore;
authorize(client: OAuthClientInformationFull, params: AuthorizationParams, res: Response): Promise<void>;
challengeForAuthorizationCode(client: OAuthClientInformationFull, authorizationCode: string): Promise<string>;
exchangeAuthorizationCode(client: OAuthClientInformationFull, authorizationCode: string, codeVerifier?: string, redirectUri?: string, resource?: URL): Promise<OAuthTokens>;
exchangeRefreshToken(client: OAuthClientInformationFull, refreshToken: string, scopes?: string[], resource?: URL): Promise<OAuthTokens>;
verifyAccessToken(token: string): Promise<AuthInfo>;
revokeToken?(client: OAuthClientInformationFull, request: OAuthTokenRevocationRequest): Promise<void>;
skipLocalPkceValidation?: boolean;
}
interface AuthorizationParams {
state?: string;
scopes?: string[];
codeChallenge: string;
redirectUri: string;
resource?: URL;
}
interface OAuthTokenVerifier {
verifyAccessToken(token: string): Promise<AuthInfo>;
}import { ProxyOAuthServerProvider } from '@modelcontextprotocol/sdk/server/auth/providers/proxyProvider.js';
class ProxyOAuthServerProvider implements OAuthServerProvider {
constructor(options: {
endpoints: {
authorizationUrl: string;
tokenUrl: string;
revocationUrl: string;
};
verifyAccessToken: (token: string) => Promise<TokenInfo>;
getClient: (clientId: string) => Promise<OAuthClient | undefined>;
tokens?: OAuthTokens;
});
}import { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js';
function requireBearerAuth(options: {
verifier: OAuthTokenVerifier;
requiredScopes?: string[];
resourceMetadataUrl?: string;
}): express.RequestHandler;import express from 'express';
import { mcpAuthRouter } from '@modelcontextprotocol/sdk/server/auth/router.js';
import { ProxyOAuthServerProvider } from '@modelcontextprotocol/sdk/server/auth/providers/proxyProvider.js';
import { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js';
const app = express();
const provider = new ProxyOAuthServerProvider({
endpoints: {
authorizationUrl: 'https://auth.example.com/oauth2/authorize',
tokenUrl: 'https://auth.example.com/oauth2/token',
revocationUrl: 'https://auth.example.com/oauth2/revoke'
},
verifyAccessToken: async (token) => ({
token,
clientId: 'client-123',
scopes: ['openid', 'profile']
}),
getClient: async (clientId) => ({
client_id: clientId,
redirect_uris: ['http://localhost:3000/callback']
})
});
// Mount OAuth router
app.use(mcpAuthRouter({
provider,
issuerUrl: new URL('https://auth.example.com'),
baseUrl: new URL('https://mcp.example.com'),
serviceDocumentationUrl: new URL('https://docs.example.com')
}));
// Protect MCP endpoint
app.post('/mcp',
requireBearerAuth({
verifier: provider,
requiredScopes: ['mcp:read', 'mcp:write']
}),
async (req, res) => {
await transport.handleRequest(req, res, req.body);
}
);
app.listen(3000);interface OAuthClientProvider {
get redirectUrl(): string | URL;
get clientMetadata(): OAuthClientMetadata;
state?(): string | Promise<string>;
clientInformation(): OAuthClientInformation | undefined | Promise<OAuthClientInformation | undefined>;
saveClientInformation?(clientInformation: OAuthClientInformationFull): void | Promise<void>;
tokens(): OAuthTokens | undefined | Promise<OAuthTokens | undefined>;
saveTokens(tokens: OAuthTokens): void | Promise<void>;
redirectToAuthorization(authorizationUrl: URL): void | Promise<void>;
saveCodeVerifier(codeVerifier: string): void | Promise<void>;
codeVerifier(): string | Promise<string>;
addClientAuthentication?(headers: Headers, params: URLSearchParams, url: string | URL, metadata?: AuthorizationServerMetadata): void | Promise<void>;
validateResourceURL?(serverUrl: string | URL, resource?: string): Promise<URL | undefined>;
invalidateCredentials?(scope: 'all' | 'client' | 'tokens' | 'verifier'): void | Promise<void>;
}import { auth } from '@modelcontextprotocol/sdk/client/auth.js';
async function auth(
provider: OAuthClientProvider,
options: {
serverUrl: URL;
forceRefresh?: boolean;
fetch?: FetchLike;
}
): Promise<{
tokens: OAuthTokens;
metadata: OAuthMetadata | OAuthProtectedResourceMetadata;
}>;import { withOAuth } from '@modelcontextprotocol/sdk/client/middleware.js';
function withOAuth(provider: OAuthClientProvider, baseUrl?: string | URL): Middleware;import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
const transport = new StreamableHTTPClientTransport(
new URL('http://localhost:3000/mcp'),
{ authProvider: myOAuthProvider }
);
// OAuth is automatically handled by the transport
await client.connect(transport);interface OAuthTokens {
access_token: string;
token_type: string;
expires_in?: number;
refresh_token?: string;
scope?: string;
}
interface OAuthClientMetadata {
client_name?: string;
redirect_uris?: string[];
token_endpoint_auth_method?: string;
grant_types?: string[];
response_types?: string[];
client_uri?: string;
logo_uri?: string;
scope?: string;
contacts?: string[];
tos_uri?: string;
policy_uri?: string;
jwks_uri?: string;
software_id?: string;
software_version?: string;
}
interface OAuthClientInformation {
client_id: string;
redirect_uris?: string[];
}
interface OAuthClientInformationFull extends OAuthClientInformation {
client_secret?: string;
client_secret_expires_at?: number;
registration_access_token?: string;
registration_client_uri?: string;
}
interface OAuthMetadata {
issuer: string;
authorization_endpoint: string;
token_endpoint: string;
revocation_endpoint?: string;
registration_endpoint?: string;
scopes_supported?: string[];
response_types_supported: string[];
grant_types_supported?: string[];
token_endpoint_auth_methods_supported?: string[];
code_challenge_methods_supported?: string[];
service_documentation?: string;
}
interface OAuthProtectedResourceMetadata {
resource: string;
authorization_servers?: string[];
bearer_methods_supported?: string[];
resource_documentation?: string;
scopes_supported?: string[];
}
interface TokenInfo {
token: string;
clientId: string;
scopes: string[];
userId?: string;
expiresAt?: number;
}class OAuthError extends Error { }
class InvalidRequestError extends OAuthError { }
class InvalidClientError extends OAuthError { }
class InvalidGrantError extends OAuthError { }
class UnauthorizedClientError extends OAuthError { }
class UnsupportedGrantTypeError extends OAuthError { }
class InvalidScopeError extends OAuthError { }
class AccessDeniedError extends OAuthError { }
class ServerError extends OAuthError { }
class TemporarilyUnavailableError extends OAuthError { }
class UnsupportedResponseTypeError extends OAuthError { }
class UnsupportedTokenTypeError extends OAuthError { }
class InvalidTokenError extends OAuthError { }
class MethodNotAllowedError extends OAuthError { }
class TooManyRequestsError extends OAuthError { }
class InvalidClientMetadataError extends OAuthError { }
class InsufficientScopeError extends OAuthError { }import { extractResourceMetadataUrl } from '@modelcontextprotocol/sdk/client/auth.js';
import { resourceUrlFromServerUrl } from '@modelcontextprotocol/sdk/shared/auth-utils.js';
function extractResourceMetadataUrl(response: Response): URL | undefined;
function resourceUrlFromServerUrl(url: URL | string): URL;