@ttoss/http-server-mcp 0.15.0 → 0.16.1

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.
package/dist/index.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
 
2
2
  /// <reference types="node" />
3
3
  import { Router } from "@ttoss/http-server";
4
+ import { OAuthVerifyOptions } from "@ttoss/http-server-oauth";
4
5
  import { z } from "zod";
5
6
  import { McpServer, McpServer as McpServer$1 } from "@modelcontextprotocol/sdk/server/mcp.js";
6
7
  import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
@@ -665,254 +666,23 @@ declare namespace Application {
665
666
  const HttpError: typeof HttpErrors.HttpError;
666
667
  }
667
668
  //#endregion
668
- //#region src/authServerTypes.d.ts
669
+ //#region src/index.d.ts
669
670
  type Context$1 = Application.Context;
670
671
  /**
671
- * OAuth 2.0 client metadata as supplied by a client during Dynamic Client
672
- * Registration (RFC 7591). Apps may persist additional fields verbatim.
673
- */
674
- interface OAuthClientMetadata {
675
- /** Allowed redirect URIs. At least one is required for the auth-code flow. */
676
- redirect_uris: string[];
677
- /** Human-readable client name shown on consent screens. */
678
- client_name?: string;
679
- /** OAuth grant types the client will use. Defaults to auth-code + refresh. */
680
- grant_types?: string[];
681
- /** OAuth response types the client will use. Defaults to `['code']`. */
682
- response_types?: string[];
683
- /**
684
- * Client authentication method at the token endpoint. `'none'` registers a
685
- * public client (no secret issued); anything else registers a confidential
686
- * client and a `client_secret` is generated.
687
- */
688
- token_endpoint_auth_method?: string;
689
- /** Space-separated scopes the client may request. */
690
- scope?: string;
691
- [key: string]: unknown;
692
- }
693
- /**
694
- * A registered OAuth client as persisted by the app's {@link ClientStore}.
695
- */
696
- interface OAuthClient extends OAuthClientMetadata {
697
- /** Unique client identifier issued by the authorization server. */
698
- client_id: string;
699
- /** Client secret for confidential clients. Absent for public clients. */
700
- client_secret?: string;
701
- /** Unix timestamp (seconds) when the client was registered. */
702
- client_id_issued_at?: number;
703
- }
704
- /**
705
- * App-provided store for OAuth clients. ttoss owns protocol mechanics; the app
706
- * owns persistence (DynamoDB, Postgres, in-memory, …).
707
- */
708
- interface ClientStore {
709
- /** Look up a client by its `client_id`. Return `undefined` if unknown. */
710
- get: (clientId: string) => Promise<OAuthClient | undefined> | OAuthClient | undefined;
711
- /** Persist a newly registered client. */
712
- register: (client: OAuthClient) => Promise<void> | void;
713
- }
714
- /**
715
- * A short-lived authorization code with its bound PKCE challenge and the
716
- * details needed to issue tokens when the code is later exchanged.
717
- */
718
- interface StoredAuthorizationCode {
719
- /** The opaque authorization code value. */
720
- code: string;
721
- /** The `client_id` the code was issued to. */
722
- clientId: string;
723
- /** The redirect URI the code was issued for (must match on exchange). */
724
- redirectUri: string;
725
- /** The PKCE `code_challenge` (S256) bound to this code. */
726
- codeChallenge: string;
727
- /** The scopes granted to this code. */
728
- scopes: string[];
729
- /** The authenticated end-user subject identifier. */
730
- subject: string;
731
- /** Unix timestamp (milliseconds) after which the code is invalid. */
732
- expiresAt: number;
733
- }
734
- /**
735
- * App-provided store for authorization codes. Codes are single-use and
736
- * short-lived; the app decides where to persist them.
737
- */
738
- interface AuthCodeStore {
739
- /** Persist an authorization code. */
740
- save: (code: StoredAuthorizationCode) => Promise<void> | void;
741
- /** Look up an authorization code by its value. */
742
- get: (code: string) => Promise<StoredAuthorizationCode | undefined> | StoredAuthorizationCode | undefined;
743
- /** Remove an authorization code (called on exchange to enforce single use). */
744
- delete: (code: string) => Promise<void> | void;
745
- }
746
- /** Tokens returned by the app's {@link McpAuthServerOptions.issueTokens} hook. */
747
- interface IssuedTokens {
748
- /** The access token string (JWT, opaque, …). */
749
- accessToken: string;
750
- /** Optional refresh token enabling the `refresh_token` grant. */
751
- refreshToken?: string;
752
- /** Access token lifetime in seconds, surfaced as `expires_in`. */
753
- expiresIn?: number;
754
- /** Granted scopes as a space-separated string. Defaults to the bound scopes. */
755
- scope?: string;
756
- }
757
- /** Arguments passed to {@link McpAuthServerOptions.issueTokens}. */
758
- interface IssueTokensArgs {
759
- /** The authenticated end-user subject identifier. */
760
- subject: string;
761
- /** The scopes granted to the token. */
762
- scopes: string[];
763
- /** The client the tokens are being issued to. */
764
- client: OAuthClient;
765
- }
766
- /** The validated authorization request passed to the consent/login hook. */
767
- interface AuthorizeRequest {
768
- /** The requesting `client_id`. */
769
- clientId: string;
770
- /** The validated redirect URI. */
771
- redirectUri: string;
772
- /** The requested scopes. */
773
- scopes: string[];
774
- /** Opaque CSRF/state value to echo back on redirect. */
775
- state?: string;
776
- /** The PKCE `code_challenge`. */
777
- codeChallenge: string;
778
- /** The PKCE challenge method (always `'S256'`). */
779
- codeChallengeMethod: string;
780
- }
781
- /** Arguments passed to {@link McpAuthServerOptions.onAuthorize}. */
782
- interface OnAuthorizeArgs {
783
- /** The Koa context, so the app can read cookies/session or write a response. */
784
- ctx: Context$1;
785
- /** The resolved client making the request. */
786
- client: OAuthClient;
787
- /** The validated authorization request. */
788
- request: AuthorizeRequest;
789
- }
790
- /**
791
- * Result of the app's consent/login hook.
792
- *
793
- * `approved: true` means the end-user is authenticated and has consented — the
794
- * authorization server issues a code and redirects. `approved: false` means the
795
- * app has taken over the response (e.g. redirected to its own login/consent
796
- * page); the authorization server does nothing further.
797
- */
798
- type OnAuthorizeResult = {
799
- approved: true;
800
- subject: string;
801
- scopes?: string[];
802
- } | {
803
- approved: false;
804
- };
805
- /** Arguments passed to {@link McpAuthServerOptions.onRefreshToken}. */
806
- interface OnRefreshTokenArgs {
807
- /** The refresh token presented by the client. */
808
- refreshToken: string;
809
- /** The authenticated client. */
810
- client: OAuthClient;
811
- /** Scopes requested in the refresh request (may be empty). */
812
- scopes: string[];
813
- }
814
- /**
815
- * Result of validating a refresh token. Return `undefined` to reject the token.
672
+ * Authentication options for the MCP endpoint. Extends the `@ttoss/http-server`
673
+ * OAuth verification options with the optional protected-resource metadata
674
+ * endpoint that MCP clients fetch for discovery.
816
675
  */
817
- type OnRefreshTokenResult = {
818
- subject: string;
819
- scopes: string[];
820
- } | undefined;
821
- /** Configuration for {@link createMcpAuthServer}. */
822
- interface McpAuthServerOptions {
823
- /** The authorization server's issuer identifier (its base URL). */
824
- issuer: string;
825
- /** App-provided store for dynamic clients. */
826
- clientStore: ClientStore;
827
- /** App-provided store for short-lived authorization codes. */
828
- authCodeStore: AuthCodeStore;
829
- /**
830
- * App-owned token minting. ttoss never sees the user model or signing keys —
831
- * it hands you the subject/scopes/client and you return the tokens.
832
- */
833
- issueTokens: (args: IssueTokensArgs) => Promise<IssuedTokens> | IssuedTokens;
834
- /**
835
- * App-owned login/consent. Called on every `/authorize` request; return the
836
- * authenticated subject to approve, or take over the response to show your
837
- * own login/consent UI and return `{ approved: false }`.
838
- */
839
- onAuthorize: (args: OnAuthorizeArgs) => Promise<OnAuthorizeResult> | OnAuthorizeResult;
840
- /**
841
- * App-owned refresh-token validation. Required to support the `refresh_token`
842
- * grant; when omitted, refresh requests get `unsupported_grant_type`.
843
- */
844
- onRefreshToken?: (args: OnRefreshTokenArgs) => Promise<OnRefreshTokenResult> | OnRefreshTokenResult;
845
- /** Scopes advertised in discovery metadata (`scopes_supported`). */
846
- scopesSupported?: string[];
847
- /**
848
- * When set, also serves `/.well-known/oauth-protected-resource` (RFC 9728)
849
- * pairing this resource URL with the issuer as its authorization server.
850
- */
851
- resource?: string;
852
- /**
853
- * Authorization code lifetime in seconds.
854
- * @default 600
855
- */
856
- authorizationCodeTtl?: number;
857
- /** Override the default endpoint paths. */
858
- endpoints?: {
859
- /** @default '/authorize' */authorize?: string; /** @default '/token' */
860
- token?: string; /** @default '/register' */
861
- register?: string;
862
- };
676
+ interface McpAuthOptions extends OAuthVerifyOptions {
677
+ /**
678
+ * URL of this MCP server, surfaced in the OAuth Protected Resource Metadata
679
+ * response. Both this and `authorizationServerUrl` must be set to serve
680
+ * `/.well-known/oauth-protected-resource`.
681
+ */
682
+ resourceServerUrl?: string;
683
+ /** URL of the OAuth Authorization Server that issues tokens for this resource. */
684
+ authorizationServerUrl?: string;
863
685
  }
864
- //#endregion
865
- //#region src/authServer.d.ts
866
- /**
867
- * Creates transport-agnostic OAuth 2.1 Authorization Server primitives for MCP.
868
- *
869
- * Mounts the authorization endpoint (`/authorize`, PKCE S256 required), token
870
- * endpoint (`/token`, `authorization_code` + `refresh_token` grants), Dynamic
871
- * Client Registration (`/register`, RFC 7591), and AS metadata discovery
872
- * (`/.well-known/oauth-authorization-server`, RFC 8414). When `resource` is
873
- * set, it also serves the protected-resource metadata (RFC 9728).
874
- *
875
- * ttoss owns only the protocol mechanics — the app supplies its own stores,
876
- * token signing/verification, and login/consent UI through the option hooks, so
877
- * the user model, JWT/IAM, and authentication never leave the consuming app.
878
- *
879
- * @param options - Authorization server configuration and pluggable hooks.
880
- * @returns A Koa `Router` exposing `routes()` / `allowedMethods()`.
881
- *
882
- * @example
883
- * ```typescript
884
- * import { App, bodyParser } from '@ttoss/http-server';
885
- * import { createMcpAuthServer } from '@ttoss/http-server-mcp';
886
- *
887
- * const authServer = createMcpAuthServer({
888
- * issuer: 'https://api.soat.dev',
889
- * clientStore,
890
- * authCodeStore,
891
- * issueTokens: async ({ subject, scopes }) => ({
892
- * accessToken: signJwt({ sub: subject, scope: scopes.join(' ') }),
893
- * refreshToken: createRefreshToken(subject),
894
- * expiresIn: 3600,
895
- * }),
896
- * onAuthorize: async ({ ctx }) => {
897
- * const session = await getSession(ctx);
898
- * if (!session) {
899
- * ctx.redirect('/login');
900
- * return { approved: false };
901
- * }
902
- * return { approved: true, subject: session.userId };
903
- * },
904
- * scopesSupported: ['mcp:access'],
905
- * });
906
- *
907
- * const app = new App();
908
- * app.use(bodyParser());
909
- * app.use(authServer.routes());
910
- * ```
911
- */
912
- declare const createMcpAuthServer: (options: McpAuthServerOptions) => Router;
913
- //#endregion
914
- //#region src/index.d.ts
915
- type Context$2 = Application.Context;
916
686
  /**
917
687
  * Options for a single `apiCall` request.
918
688
  */
@@ -1004,58 +774,6 @@ declare const getIdentity: () => unknown;
1004
774
  * ```
1005
775
  */
1006
776
  declare const checkScopes: (required: string[]) => void;
1007
- /** Amazon Cognito user pool configuration for JWT verification. */
1008
- interface CognitoUserPoolConfig {
1009
- /** The Cognito User Pool ID (e.g. `us-east-1_abc123`). */
1010
- userPoolId: string;
1011
- /**
1012
- * Which token type to verify.
1013
- * @default 'access'
1014
- */
1015
- tokenUse?: 'access' | 'id';
1016
- /** The app client ID registered in the User Pool. */
1017
- clientId: string;
1018
- }
1019
- /**
1020
- * Authentication options for the MCP router.
1021
- *
1022
- * Supply either `cognitoUserPool` (uses `CognitoJwtVerifier` from
1023
- * `@ttoss/auth-core`) or a custom `verifyToken` function — not both.
1024
- */
1025
- interface McpAuthOptions {
1026
- /**
1027
- * Amazon Cognito user pool config. When provided, the router creates a
1028
- * `CognitoJwtVerifier` and validates every incoming Bearer token against it.
1029
- */
1030
- cognitoUserPool?: CognitoUserPoolConfig;
1031
- /**
1032
- * Custom token verifier for non-Cognito providers (Auth0, Keycloak, …).
1033
- * Receives the raw Bearer token string. Should resolve with the verified
1034
- * payload or reject/throw on failure.
1035
- */
1036
- verifyToken?: (token: string) => Promise<unknown>;
1037
- /**
1038
- * Router-level scope guard. All listed scopes must be present on the token
1039
- * for any MCP request to be allowed. Returns 403 if any scope is missing.
1040
- *
1041
- * Cognito encodes scopes as a space-separated string in `payload.scope`.
1042
- *
1043
- * @example ['mcp:access']
1044
- */
1045
- requiredScopes?: string[];
1046
- /**
1047
- * URL of this MCP server, used in the OAuth Protected Resource Metadata
1048
- * response (`/.well-known/oauth-protected-resource`). Both this field and
1049
- * `authorizationServerUrl` must be provided to enable the endpoint.
1050
- */
1051
- resourceServerUrl?: string;
1052
- /**
1053
- * URL of the OAuth Authorization Server that issues tokens for this resource.
1054
- * Enables `/.well-known/oauth-protected-resource` for MCP client auto-discovery
1055
- * (RFC 9728) when combined with `resourceServerUrl`.
1056
- */
1057
- authorizationServerUrl?: string;
1058
- }
1059
777
  /**
1060
778
  * Options for configuring the MCP router
1061
779
  */
@@ -1104,14 +822,17 @@ interface McpRouterOptions {
1104
822
  * getApiHeaders: () => ({ 'x-internal-key': process.env.INTERNAL_API_KEY! })
1105
823
  * ```
1106
824
  */
1107
- getApiHeaders?: (ctx: Context$2) => Record<string, string>;
825
+ getApiHeaders?: (ctx: Context$1) => Record<string, string>;
1108
826
  /**
1109
827
  * OAuth / JWT authentication configuration for the MCP endpoint.
1110
828
  *
1111
- * When set, every incoming MCP request must include a valid Bearer token in
1112
- * the `Authorization` header. Invalid or missing tokens receive a `401`
1113
- * response with `WWW-Authenticate: Bearer`. Tokens that fail a
1114
- * `requiredScopes` check receive `403`.
829
+ * When set, incoming MCP requests must include a valid Bearer token in the
830
+ * `Authorization` header except for `publicMethods` (by default
831
+ * `initialize` and `tools/list`), which bypass verification so clients can
832
+ * discover the server before authenticating. Invalid or missing tokens
833
+ * receive a `401` response with `WWW-Authenticate: Bearer` (or
834
+ * `Bearer resource_metadata="..."` when `resourceMetadataUrl` is set, per
835
+ * RFC 9728). Tokens that fail a `requiredScopes` check receive `403`.
1115
836
  *
1116
837
  * The verified token payload is accessible inside tool handlers via
1117
838
  * {@link getIdentity}. Fine-grained per-tool scope checks can be done with
@@ -1252,64 +973,5 @@ interface RegisterToolFromSchemaParams {
1252
973
  * ```
1253
974
  */
1254
975
  declare const registerToolFromSchema: (server: McpServer$1, params: RegisterToolFromSchemaParams) => void;
1255
- /**
1256
- * Returns the `WWW-Authenticate` header value for a 401 response on a
1257
- * protected resource, following the MCP auth spec requirement that
1258
- * unauthorized responses advertise the resource metadata URL so MCP
1259
- * clients can bootstrap OAuth discovery.
1260
- *
1261
- * Use this in your own auth middleware when you are not using the built-in
1262
- * `auth` option on `createMcpRouter`.
1263
- *
1264
- * @example
1265
- * ```typescript
1266
- * import { getWwwAuthenticateHeader } from '@ttoss/http-server-mcp';
1267
- *
1268
- * // Inside a Koa middleware
1269
- * ctx.status = 401;
1270
- * ctx.set('WWW-Authenticate', getWwwAuthenticateHeader({ resource: 'https://mcp.example.com' }));
1271
- * ```
1272
- */
1273
- declare const getWwwAuthenticateHeader: (args: {
1274
- /**
1275
- * The resource server URL. The metadata URL is derived as
1276
- * `<resource>/.well-known/oauth-protected-resource` per RFC 9728.
1277
- */
1278
- resource: string;
1279
- }) => string;
1280
- /**
1281
- * Creates a standalone Koa middleware that serves
1282
- * `GET /.well-known/oauth-protected-resource` (RFC 9728) without requiring
1283
- * the built-in `auth` option on `createMcpRouter`.
1284
- *
1285
- * Mount this **before** your own auth middleware so the discovery endpoint
1286
- * remains unauthenticated (MCP clients fetch it before they have a token).
1287
- *
1288
- * @example
1289
- * ```typescript
1290
- * import Koa from 'koa';
1291
- * import { createProtectedResourceMetadataMiddleware } from '@ttoss/http-server-mcp';
1292
- *
1293
- * const app = new Koa();
1294
- * app.use(
1295
- * createProtectedResourceMetadataMiddleware({
1296
- * resource: 'https://mcp.example.com',
1297
- * authorizationServers: ['https://api.example.com'],
1298
- * })
1299
- * );
1300
- * app.use(myOwnAuthMiddleware);
1301
- * ```
1302
- */
1303
- declare const createProtectedResourceMetadataMiddleware: (args: {
1304
- /**
1305
- * The protected resource's identifier URI (the MCP server URL).
1306
- */
1307
- resource: string;
1308
- /**
1309
- * List of authorization server issuer URIs that issue tokens for this
1310
- * resource.
1311
- */
1312
- authorizationServers: string[];
1313
- }) => Application.Middleware;
1314
976
  //#endregion
1315
- export { ApiCallOptions, AuthCodeStore, AuthorizeRequest, ClientStore, CognitoUserPoolConfig, Context$1 as Context, IssueTokensArgs, IssuedTokens, JsonObjectSchema, McpAuthOptions, McpAuthServerOptions, McpRouterOptions, McpServer, OAuthClient, OAuthClientMetadata, OnAuthorizeArgs, OnAuthorizeResult, OnRefreshTokenArgs, OnRefreshTokenResult, RegisterToolFromSchemaParams, StoredAuthorizationCode, apiCall, checkScopes, createMcpAuthServer, createMcpRouter, createProtectedResourceMetadataMiddleware, getIdentity, getWwwAuthenticateHeader, registerToolFromSchema, z };
977
+ export { ApiCallOptions, JsonObjectSchema, McpAuthOptions, McpRouterOptions, McpServer, RegisterToolFromSchemaParams, apiCall, checkScopes, createMcpRouter, getIdentity, registerToolFromSchema, z };