@ttoss/http-server-mcp 0.14.0 → 0.15.0
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/README.md +88 -0
- package/dist/index.cjs +372 -0
- package/dist/index.d.cts +249 -3
- package/dist/index.d.mts +249 -3
- package/dist/index.mjs +372 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -665,8 +665,254 @@ declare namespace Application {
|
|
|
665
665
|
const HttpError: typeof HttpErrors.HttpError;
|
|
666
666
|
}
|
|
667
667
|
//#endregion
|
|
668
|
-
//#region src/
|
|
668
|
+
//#region src/authServerTypes.d.ts
|
|
669
669
|
type Context$1 = Application.Context;
|
|
670
|
+
/**
|
|
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.
|
|
816
|
+
*/
|
|
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
|
+
};
|
|
863
|
+
}
|
|
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;
|
|
670
916
|
/**
|
|
671
917
|
* Options for a single `apiCall` request.
|
|
672
918
|
*/
|
|
@@ -858,7 +1104,7 @@ interface McpRouterOptions {
|
|
|
858
1104
|
* getApiHeaders: () => ({ 'x-internal-key': process.env.INTERNAL_API_KEY! })
|
|
859
1105
|
* ```
|
|
860
1106
|
*/
|
|
861
|
-
getApiHeaders?: (ctx: Context$
|
|
1107
|
+
getApiHeaders?: (ctx: Context$2) => Record<string, string>;
|
|
862
1108
|
/**
|
|
863
1109
|
* OAuth / JWT authentication configuration for the MCP endpoint.
|
|
864
1110
|
*
|
|
@@ -1066,4 +1312,4 @@ declare const createProtectedResourceMetadataMiddleware: (args: {
|
|
|
1066
1312
|
authorizationServers: string[];
|
|
1067
1313
|
}) => Application.Middleware;
|
|
1068
1314
|
//#endregion
|
|
1069
|
-
export { ApiCallOptions, CognitoUserPoolConfig, JsonObjectSchema, McpAuthOptions, McpRouterOptions, McpServer, RegisterToolFromSchemaParams, apiCall, checkScopes, createMcpRouter, createProtectedResourceMetadataMiddleware, getIdentity, getWwwAuthenticateHeader, registerToolFromSchema, z };
|
|
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 };
|
package/dist/index.d.mts
CHANGED
|
@@ -665,8 +665,254 @@ declare namespace Application {
|
|
|
665
665
|
const HttpError: typeof HttpErrors.HttpError;
|
|
666
666
|
}
|
|
667
667
|
//#endregion
|
|
668
|
-
//#region src/
|
|
668
|
+
//#region src/authServerTypes.d.ts
|
|
669
669
|
type Context$1 = Application.Context;
|
|
670
|
+
/**
|
|
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.
|
|
816
|
+
*/
|
|
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
|
+
};
|
|
863
|
+
}
|
|
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;
|
|
670
916
|
/**
|
|
671
917
|
* Options for a single `apiCall` request.
|
|
672
918
|
*/
|
|
@@ -858,7 +1104,7 @@ interface McpRouterOptions {
|
|
|
858
1104
|
* getApiHeaders: () => ({ 'x-internal-key': process.env.INTERNAL_API_KEY! })
|
|
859
1105
|
* ```
|
|
860
1106
|
*/
|
|
861
|
-
getApiHeaders?: (ctx: Context$
|
|
1107
|
+
getApiHeaders?: (ctx: Context$2) => Record<string, string>;
|
|
862
1108
|
/**
|
|
863
1109
|
* OAuth / JWT authentication configuration for the MCP endpoint.
|
|
864
1110
|
*
|
|
@@ -1066,4 +1312,4 @@ declare const createProtectedResourceMetadataMiddleware: (args: {
|
|
|
1066
1312
|
authorizationServers: string[];
|
|
1067
1313
|
}) => Application.Middleware;
|
|
1068
1314
|
//#endregion
|
|
1069
|
-
export { ApiCallOptions, CognitoUserPoolConfig, JsonObjectSchema, McpAuthOptions, McpRouterOptions, McpServer, RegisterToolFromSchemaParams, apiCall, checkScopes, createMcpRouter, createProtectedResourceMetadataMiddleware, getIdentity, getWwwAuthenticateHeader, registerToolFromSchema, z };
|
|
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 };
|