CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-modelcontextprotocol--sdk

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
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

authentication.mddocs/

Authentication

Complete OAuth 2.0 support: authorization code flow with PKCE, client registration, token management, and revocation.

Server-Side OAuth

OAuth Router

import { mcpAuthRouter } from '@modelcontextprotocol/sdk/server/auth/router.js';

function mcpAuthRouter(options: {
  provider: OAuthServerProvider;
  issuerUrl: URL;
  baseUrl: URL;
  serviceDocumentationUrl?: URL;
  rateLimit?: RateLimitOptions;
}): express.Router;

OAuth Server Provider Interface

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>;
}

Proxy OAuth Provider

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;
  });
}

OAuth Middleware

import { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js';

function requireBearerAuth(options: {
  verifier: OAuthTokenVerifier;
  requiredScopes?: string[];
  resourceMetadataUrl?: string;
}): express.RequestHandler;

Complete Server Example

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);

Client-Side OAuth

OAuth Client Provider Interface

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>;
}

OAuth Authentication Flow

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;
}>;

OAuth HTTP Middleware

import { withOAuth } from '@modelcontextprotocol/sdk/client/middleware.js';

function withOAuth(provider: OAuthClientProvider, baseUrl?: string | URL): Middleware;

Client Example

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);

OAuth Types

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;
}

OAuth Error Classes

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 { }

Metadata Discovery

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;

docs

authentication.md

client.md

index.md

server-advanced.md

server-prompts.md

server-resources.md

server-tools.md

transports.md

types.md

tile.json