UNPKG

@nutrient-sdk/dws-mcp-server

Version:

MCP server for Nutrient DWS Processor API

74 lines (73 loc) 2.63 kB
import { getToken, invalidateCachedToken } from '../auth/nutrient-oauth.js'; /** Authenticates with static, per-product API keys — each key is pinned to its own tenant. */ export class StaticKeyCredentialProvider { keys; constructor(keys) { this.keys = keys; } async token(product) { const key = this.keys[product]; if (!key) { // Defensive: callers must gate on `supports` first. Reaching here is a bug at the call site. throw new Error(`No API key configured for product "${product}"`); } return key; } invalidate() { // Static keys don't expire or rotate; nothing to invalidate. } canRefresh() { // A rejected static key stays rejected — a 401 is terminal, not worth retrying. return false; } supports(product) { return Boolean(this.keys[product]); } } /** Authenticates with a Nutrient OAuth token. `product:all` scope covers both products with one token. */ export class OAuthCredentialProvider { config; constructor(config) { this.config = config; } async token() { return getToken(this.config); } async invalidate() { // Awaited by the client's 401 handler so the cached token is gone before the retry // re-resolves — otherwise the refetch could race the unlink and read the stale token. await invalidateCachedToken(this.config); } canRefresh() { return true; } supports() { return true; } } export function buildOAuthConfig(environment) { return { authorizeUrl: `${environment.authServerUrl}/oauth/authorize`, tokenUrl: `${environment.authServerUrl}/oauth/token`, registrationUrl: `${environment.authServerUrl}/oauth/register`, clientId: environment.clientId, scopes: ['mcp:invoke', 'product:all', 'offline_access'], resource: environment.dwsApiBaseUrl, }; } /** * Selects the credential strategy for an `Environment`. * * Any static key present locks the server into static-key mode: falling through to * OAuth here would silently discard the configured key and open a browser consent * flow on what may be a headless machine. */ export function createCredentialProvider(environment) { if (environment.nutrientApiKey || environment.nutrientExtractionApiKey) { return new StaticKeyCredentialProvider({ processor: environment.nutrientApiKey, extraction: environment.nutrientExtractionApiKey, }); } return new OAuthCredentialProvider(buildOAuthConfig(environment)); }