@haikit/mcp 0.33.0 → 0.34.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 +46 -7
- package/dist/auth.d.ts +107 -36
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +252 -37
- package/dist/auth.js.map +1 -1
- package/dist/credential.d.ts +55 -0
- package/dist/credential.d.ts.map +1 -0
- package/dist/credential.js +62 -0
- package/dist/credential.js.map +1 -0
- package/dist/errors.d.ts +7 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +66 -9
- package/dist/index.js.map +1 -1
- package/dist/oauth.d.ts +193 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +558 -0
- package/dist/oauth.js.map +1 -0
- package/dist/postgres.d.ts +25 -0
- package/dist/postgres.d.ts.map +1 -0
- package/dist/postgres.js +97 -0
- package/dist/postgres.js.map +1 -0
- package/dist/routes.d.ts +17 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +228 -0
- package/dist/routes.js.map +1 -0
- package/dist/seal.d.ts +25 -0
- package/dist/seal.d.ts.map +1 -0
- package/dist/seal.js +60 -0
- package/dist/seal.js.map +1 -0
- package/dist/store.d.ts +50 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +83 -0
- package/dist/store.js.map +1 -0
- package/dist/transports.d.ts +5 -1
- package/dist/transports.d.ts.map +1 -1
- package/dist/transports.js +2 -0
- package/dist/transports.js.map +1 -1
- package/package.json +6 -2
- package/src/auth.ts +354 -48
- package/src/credential.ts +78 -0
- package/src/errors.ts +7 -0
- package/src/index.ts +75 -12
- package/src/oauth.ts +659 -0
- package/src/postgres.ts +127 -0
- package/src/routes.ts +243 -0
- package/src/seal.ts +62 -0
- package/src/store.ts +118 -0
- package/src/transports.ts +7 -0
package/dist/oauth.d.ts
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { type AuthorizationServerMetadata, type FetchLike, type OAuthClientMetadata, type OAuthDiscoveryState, type StoredOAuthClientInformation, type StoredOAuthTokens } from "@modelcontextprotocol/client";
|
|
2
|
+
import { type Credential } from "./credential.js";
|
|
3
|
+
import { type Sealer } from "./seal.js";
|
|
4
|
+
import type { CredentialStore } from "./store.js";
|
|
5
|
+
/** How long a connect flow lasts: from the connect route to the callback. */
|
|
6
|
+
export declare const FLOW_MS = 600000;
|
|
7
|
+
export interface OAuthServerOptions {
|
|
8
|
+
/**
|
|
9
|
+
* The authorization server this server must use, as its metadata's
|
|
10
|
+
* `issuer`. Strongly advised for a third party's server: a server names its
|
|
11
|
+
* own authorization server, and one compromised could send users to a fake
|
|
12
|
+
* sign-in page.
|
|
13
|
+
*/
|
|
14
|
+
issuer?: string;
|
|
15
|
+
/** Asked for when connecting. Default: what the server's metadata asks for. */
|
|
16
|
+
scopes?: string[];
|
|
17
|
+
/**
|
|
18
|
+
* A client the app registered with the authorization server. Needs
|
|
19
|
+
* `issuer`. Without it, one is registered for the app: by its metadata
|
|
20
|
+
* document's URL where the authorization server takes one, else by dynamic
|
|
21
|
+
* client registration.
|
|
22
|
+
*/
|
|
23
|
+
client?: {
|
|
24
|
+
id: string;
|
|
25
|
+
secret?: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/** What every `oauth()` server of one `createMcpAuth` shares. */
|
|
29
|
+
export interface OAuthCore {
|
|
30
|
+
readonly store: CredentialStore;
|
|
31
|
+
readonly sealer: Sealer;
|
|
32
|
+
readonly redirectUri: string;
|
|
33
|
+
/** What a client is registered with, and the metadata document says. */
|
|
34
|
+
readonly clientMetadata: OAuthClientMetadata;
|
|
35
|
+
/** The metadata document's URL, when the redirect URI is https: an OAuth client can then be identified by it. */
|
|
36
|
+
readonly clientMetadataUrl: string | undefined;
|
|
37
|
+
}
|
|
38
|
+
/** What a user's credential holds, sealed. */
|
|
39
|
+
interface Kept {
|
|
40
|
+
/** As the authorization server issued them, stamped with its `issuer`. */
|
|
41
|
+
tokens: StoredOAuthTokens & {
|
|
42
|
+
issuer: string;
|
|
43
|
+
};
|
|
44
|
+
/** The client they were issued to: refreshed and revoked as it, whatever the store keeps for new connects. */
|
|
45
|
+
client: StoredOAuthClientInformation;
|
|
46
|
+
/** The scope granted, or asked for when the authorization server didn't say. */
|
|
47
|
+
scope: string | null;
|
|
48
|
+
/** When the user connected, epoch ms. A refresh keeps it. */
|
|
49
|
+
connectedAt: number;
|
|
50
|
+
}
|
|
51
|
+
/** A credential as the store holds it: the sealed value, and what it opened to. */
|
|
52
|
+
interface Held {
|
|
53
|
+
sealed: string;
|
|
54
|
+
kept: Kept;
|
|
55
|
+
}
|
|
56
|
+
/** A connect flow on its way, sealed in the store under its `state`. */
|
|
57
|
+
export interface Flow {
|
|
58
|
+
user: string;
|
|
59
|
+
server: string;
|
|
60
|
+
/** The conversation it came from, if the user owns it: `onConnected` is told. */
|
|
61
|
+
conversation: string | null;
|
|
62
|
+
/** The PKCE verifier. */
|
|
63
|
+
verifier: string;
|
|
64
|
+
/** The client the code is issued to: exchanged as it, though another connect replaced the one the store keeps. */
|
|
65
|
+
client: StoredOAuthClientInformation;
|
|
66
|
+
/** The SDK's discovery state, from the connect route: the callback is bound to its authorization server. */
|
|
67
|
+
discovery: OAuthDiscoveryState;
|
|
68
|
+
/** The scope asked for. */
|
|
69
|
+
scope: string | null;
|
|
70
|
+
expiresAt: number;
|
|
71
|
+
}
|
|
72
|
+
/** A server's authorization server, as discovered and checked. */
|
|
73
|
+
interface Where {
|
|
74
|
+
url: string;
|
|
75
|
+
issuer: string;
|
|
76
|
+
metadata: AuthorizationServerMetadata | undefined;
|
|
77
|
+
/** The RFC 8707 resource indicator: tokens are bound to this server. */
|
|
78
|
+
resource: string | undefined;
|
|
79
|
+
}
|
|
80
|
+
/** Loopback hosts, exempt from https: what the SDK exempts, and RFC 8252 does. */
|
|
81
|
+
export declare const isLoopback: (host: string) => boolean;
|
|
82
|
+
/** https, or http on this machine. */
|
|
83
|
+
export declare const isSecure: (url: string | URL) => boolean;
|
|
84
|
+
/** The connect flow a `state` names, once: null if there's none, it has expired, or it doesn't open. */
|
|
85
|
+
export declare function takeFlow(core: OAuthCore, state: string): Promise<Flow | null>;
|
|
86
|
+
/**
|
|
87
|
+
* One server's OAuth: its connect route and callback, each user's
|
|
88
|
+
* credential, refreshing, and revoking on disconnect.
|
|
89
|
+
*/
|
|
90
|
+
export declare class OAuthServer {
|
|
91
|
+
readonly core: OAuthCore;
|
|
92
|
+
private readonly options;
|
|
93
|
+
readonly name: string;
|
|
94
|
+
private readonly url;
|
|
95
|
+
private readonly baseFetch;
|
|
96
|
+
readonly timeoutMs: number;
|
|
97
|
+
/** Closes the user's connection to this server, so their next call dials with what's stored now. */
|
|
98
|
+
readonly forget: (userId: string) => Promise<void>;
|
|
99
|
+
/** The authorization server, discovered on the first refresh or revocation, or seeded by a callback. */
|
|
100
|
+
private found;
|
|
101
|
+
/** Each user's refresh on its way, which every 401 of theirs shares until it settles. */
|
|
102
|
+
private readonly refreshing;
|
|
103
|
+
constructor(core: OAuthCore, options: OAuthServerOptions, name: string, url: URL, baseFetch: FetchLike, timeoutMs: number,
|
|
104
|
+
/** Closes the user's connection to this server, so their next call dials with what's stored now. */
|
|
105
|
+
forget: (userId: string) => Promise<void>);
|
|
106
|
+
/** Every request to the authorization server, bounded by `timeoutMs`. */
|
|
107
|
+
readonly fetch: FetchLike;
|
|
108
|
+
credential(user: string): Credential;
|
|
109
|
+
/** A user's credential as the store holds it, or null if there's none, or none that opens. `known` is given back as it is if the store still holds it. */
|
|
110
|
+
read(user: string, known?: Held | null): Promise<Held | null>;
|
|
111
|
+
seal(user: string, kept: Kept): string;
|
|
112
|
+
/** The client configured, stamped with the pinned issuer: the SDK refuses it for any other. */
|
|
113
|
+
private configured;
|
|
114
|
+
/**
|
|
115
|
+
* The client to connect with at an authorization server: the one
|
|
116
|
+
* configured, or the one registered for the app. One registered for
|
|
117
|
+
* another redirect URI or metadata document, or that doesn't open, is no
|
|
118
|
+
* use, and is registered again.
|
|
119
|
+
*/
|
|
120
|
+
private client;
|
|
121
|
+
/** The client a flow or credential was issued to, as it's sent: the configured one with its secret as configured now. */
|
|
122
|
+
issuedTo(client: StoredOAuthClientInformation): StoredOAuthClientInformation;
|
|
123
|
+
private saveClient;
|
|
124
|
+
/**
|
|
125
|
+
* Checks what discovery found: the pinned issuer, and an authorization
|
|
126
|
+
* endpoint the browser can be sent to. Called by the SDK straight after
|
|
127
|
+
* discovery, before it looks up or registers a client, so a server that
|
|
128
|
+
* names another authorization server gets nothing from the app.
|
|
129
|
+
*/
|
|
130
|
+
check(state: OAuthDiscoveryState): Promise<Where>;
|
|
131
|
+
/**
|
|
132
|
+
* The authorization server, which must be the one that issued a credential:
|
|
133
|
+
* found again once if it isn't, in case the server moved since.
|
|
134
|
+
*/
|
|
135
|
+
where(issuer: string, resourceMetadataUrl?: URL): Promise<Where>;
|
|
136
|
+
/**
|
|
137
|
+
* The connect route: where to send the browser, with the flow stored under
|
|
138
|
+
* its `state` meanwhile. The SDK's `auth()` discovers the authorization
|
|
139
|
+
* server, registers a client if none is kept, and makes the PKCE challenge.
|
|
140
|
+
*/
|
|
141
|
+
start(user: string, conversation: string | null, asked: string | undefined): Promise<URL>;
|
|
142
|
+
/**
|
|
143
|
+
* The callback: exchanges the code with the authorization server and as
|
|
144
|
+
* the client the flow was started with, which checks `iss` (RFC 9207)
|
|
145
|
+
* before it asks for any token, stores the credential, and closes the
|
|
146
|
+
* user's connection.
|
|
147
|
+
*/
|
|
148
|
+
finish(flow: Flow, code: string, iss: string | undefined): Promise<void>;
|
|
149
|
+
/** Revokes the user's tokens where the authorization server takes it, then deletes them and closes the connection. */
|
|
150
|
+
disconnect(user: string): Promise<void>;
|
|
151
|
+
/** RFC 7009, at the authorization server's revocation endpoint, if it has one. */
|
|
152
|
+
private revoke;
|
|
153
|
+
/**
|
|
154
|
+
* After a 401: the credential to use instead of `before`. One refresh for
|
|
155
|
+
* each user at a time, shared until it settles, however long that takes,
|
|
156
|
+
* on whichever connection of theirs: a second would spend a refresh token
|
|
157
|
+
* the first may have spent already, and delete the credential when it's
|
|
158
|
+
* refused. Across processes, the store's lease does the same.
|
|
159
|
+
*/
|
|
160
|
+
refresh(user: string, before: Held, resourceMetadataUrl: URL | undefined): Promise<Held>;
|
|
161
|
+
/**
|
|
162
|
+
* The store's newer credential if another refresh wrote one, else a
|
|
163
|
+
* refresh of `before`, under the store's lease. A refusal deletes it,
|
|
164
|
+
* unless another write came first; an outage keeps it.
|
|
165
|
+
*/
|
|
166
|
+
private renew;
|
|
167
|
+
/**
|
|
168
|
+
* Writes a refresh's credential onto `before`, tried again while the
|
|
169
|
+
* store fails: the old refresh token is spent, so this is the only copy,
|
|
170
|
+
* and the lease is still held. False if another write or a delete came
|
|
171
|
+
* first. A try that landed, though its answer was lost, is written.
|
|
172
|
+
*/
|
|
173
|
+
private write;
|
|
174
|
+
/**
|
|
175
|
+
* Revokes the tokens a refresh got but couldn't store: its refresh token
|
|
176
|
+
* if the authorization server rotated it, else only its access token, as
|
|
177
|
+
* the one refresh token may be what the store holds now.
|
|
178
|
+
*/
|
|
179
|
+
private orphaned;
|
|
180
|
+
/**
|
|
181
|
+
* Takes the refresh lease of the user's credential, so one process at a
|
|
182
|
+
* time spends its refresh token. While another holds it: the credential
|
|
183
|
+
* that one writes, which is then the one to use, or the lease once it
|
|
184
|
+
* lapses, as it does when that process is gone.
|
|
185
|
+
*/
|
|
186
|
+
private lease;
|
|
187
|
+
/** The store's credential if it's newer than `before`, or null if it's still `before`. With none, the server's refusal stands. */
|
|
188
|
+
private newer;
|
|
189
|
+
/** Deletes the credential, if the store still holds `before`: never a newer one. */
|
|
190
|
+
private drop;
|
|
191
|
+
}
|
|
192
|
+
export {};
|
|
193
|
+
//# sourceMappingURL=oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
|