@cauthyhq/node 0.0.0 → 1.1.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/CHANGELOG.md +43 -0
- package/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +184 -1
- package/dist/cauthy-Bn-i7cKD.d.mts +1058 -0
- package/dist/cauthy-Wy-YDGrM.d.ts +1058 -0
- package/dist/express.d.mts +25 -0
- package/dist/express.d.ts +25 -0
- package/dist/express.js +103 -0
- package/dist/express.js.map +1 -0
- package/dist/express.mjs +77 -0
- package/dist/express.mjs.map +1 -0
- package/dist/fastify.d.mts +38 -0
- package/dist/fastify.d.ts +38 -0
- package/dist/fastify.js +105 -0
- package/dist/fastify.js.map +1 -0
- package/dist/fastify.mjs +79 -0
- package/dist/fastify.mjs.map +1 -0
- package/dist/hono.d.mts +24 -0
- package/dist/hono.d.ts +24 -0
- package/dist/hono.js +51 -0
- package/dist/hono.js.map +1 -0
- package/dist/hono.mjs +25 -0
- package/dist/hono.mjs.map +1 -0
- package/dist/index.d.mts +138 -0
- package/dist/index.d.ts +138 -0
- package/dist/index.js +3485 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3421 -0
- package/dist/index.mjs.map +1 -0
- package/dist/keys-D5k0omTb.d.mts +64 -0
- package/dist/keys-D5k0omTb.d.ts +64 -0
- package/dist/keys.d.mts +8 -0
- package/dist/keys.d.ts +8 -0
- package/dist/keys.js +157 -0
- package/dist/keys.js.map +1 -0
- package/dist/keys.mjs +129 -0
- package/dist/keys.mjs.map +1 -0
- package/dist/mcp.d.mts +151 -0
- package/dist/mcp.d.ts +151 -0
- package/dist/mcp.js +410 -0
- package/dist/mcp.js.map +1 -0
- package/dist/mcp.mjs +382 -0
- package/dist/mcp.mjs.map +1 -0
- package/dist/next.d.mts +24 -0
- package/dist/next.d.ts +24 -0
- package/dist/next.js +77 -0
- package/dist/next.js.map +1 -0
- package/dist/next.mjs +52 -0
- package/dist/next.mjs.map +1 -0
- package/dist/testing.d.mts +74 -0
- package/dist/testing.d.ts +74 -0
- package/dist/testing.js +270 -0
- package/dist/testing.js.map +1 -0
- package/dist/testing.mjs +243 -0
- package/dist/testing.mjs.map +1 -0
- package/dist/theme.d.mts +183 -0
- package/dist/theme.d.ts +183 -0
- package/dist/theme.js +531 -0
- package/dist/theme.js.map +1 -0
- package/dist/theme.mjs +496 -0
- package/dist/theme.mjs.map +1 -0
- package/package.json +190 -4
package/dist/mcp.d.mts
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { JWTVerifyGetKey } from 'jose';
|
|
2
|
+
|
|
3
|
+
/** The person an agent acts for, and what they allowed it. */
|
|
4
|
+
interface AgentIdentity {
|
|
5
|
+
/** The person. */
|
|
6
|
+
userId: string;
|
|
7
|
+
tenantId: string;
|
|
8
|
+
email?: string;
|
|
9
|
+
/** The person's roles in the workspace. */
|
|
10
|
+
roles: string[];
|
|
11
|
+
/** What the person allowed the agent to do here. */
|
|
12
|
+
scopes: string[];
|
|
13
|
+
/** The agent (its client_id at Cauthy). */
|
|
14
|
+
clientId: string;
|
|
15
|
+
/** UTC, ISO 8601. */
|
|
16
|
+
expiresAt: string;
|
|
17
|
+
/** The token as it arrived. */
|
|
18
|
+
token: string;
|
|
19
|
+
/**
|
|
20
|
+
* Set when the token came by token exchange: the server that called this
|
|
21
|
+
* one for the person (the `act` claim's subject).
|
|
22
|
+
*/
|
|
23
|
+
actor?: string;
|
|
24
|
+
}
|
|
25
|
+
interface McpAuthOptions {
|
|
26
|
+
/** This server's address, as registered in Cauthy. Default: `CAUTHY_MCP_RESOURCE`. */
|
|
27
|
+
resource?: string;
|
|
28
|
+
/** Cauthy's address. Default: `CAUTHY_ISSUER`. */
|
|
29
|
+
issuer?: string;
|
|
30
|
+
/** Scopes every call needs. Default: none. */
|
|
31
|
+
scopes?: string[];
|
|
32
|
+
/** The scopes this server understands, to tell agents (`scopes_supported`). Default: `scopes`. */
|
|
33
|
+
scopesSupported?: string[];
|
|
34
|
+
/** A name for the server, shown by some agents. */
|
|
35
|
+
resourceName?: string;
|
|
36
|
+
/** Cauthy's keys. Default: fetched from the issuer and cached. */
|
|
37
|
+
jwks?: JWTVerifyGetKey;
|
|
38
|
+
/** The moment to verify at. Default: now. */
|
|
39
|
+
now?: () => Date;
|
|
40
|
+
/**
|
|
41
|
+
* Ask Cauthy, besides checking the token here, whether the person still
|
|
42
|
+
* allows the agent (RFC 7662). Then an agent is cut off the moment it is
|
|
43
|
+
* disconnected, not when its token runs out, at the price of a call to
|
|
44
|
+
* Cauthy per token every `cacheSeconds` (default 30). Default: off.
|
|
45
|
+
*/
|
|
46
|
+
introspect?: boolean | {
|
|
47
|
+
cacheSeconds?: number;
|
|
48
|
+
};
|
|
49
|
+
/** The fetch to call Cauthy with. Default: the global one. */
|
|
50
|
+
fetch?: typeof fetch;
|
|
51
|
+
/** How long a call to Cauthy (introspection, token exchange) may take, in milliseconds. Default: 5000. */
|
|
52
|
+
timeoutMs?: number;
|
|
53
|
+
/**
|
|
54
|
+
* This server's client_id and secret at Cauthy, for token exchange (AI
|
|
55
|
+
* agents → the server → Server credentials). Defaults:
|
|
56
|
+
* `CAUTHY_MCP_CLIENT_ID`, `CAUTHY_MCP_CLIENT_SECRET`.
|
|
57
|
+
*/
|
|
58
|
+
clientId?: string;
|
|
59
|
+
clientSecret?: string;
|
|
60
|
+
}
|
|
61
|
+
/** What a token exchange answers. */
|
|
62
|
+
interface ExchangedToken {
|
|
63
|
+
/** The token for the other server, as the person. Send it as `Authorization: Bearer`. */
|
|
64
|
+
accessToken: string;
|
|
65
|
+
/** What it allows there. */
|
|
66
|
+
scopes: string[];
|
|
67
|
+
/** UTC, ISO 8601. Never later than the agent's own token. */
|
|
68
|
+
expiresAt: string;
|
|
69
|
+
}
|
|
70
|
+
/** A token exchange Cauthy refused, with the OAuth error it answered. */
|
|
71
|
+
declare class CauthyExchangeError extends Error {
|
|
72
|
+
readonly status: number;
|
|
73
|
+
readonly code: string;
|
|
74
|
+
readonly description: string;
|
|
75
|
+
constructor(status: number, code: string, description: string);
|
|
76
|
+
}
|
|
77
|
+
/** A token refused: `status` is 401 (no token, or not a good one) or 403 (a scope missing). */
|
|
78
|
+
declare class McpAuthError extends Error {
|
|
79
|
+
readonly status: 401 | 403;
|
|
80
|
+
readonly code: 'invalid_request' | 'invalid_token' | 'insufficient_scope';
|
|
81
|
+
readonly description: string;
|
|
82
|
+
constructor(status: 401 | 403, code: 'invalid_request' | 'invalid_token' | 'insufficient_scope', description: string);
|
|
83
|
+
}
|
|
84
|
+
/** What the MCP TypeScript SDK reads from `req.auth` (its AuthInfo). */
|
|
85
|
+
interface McpAuthInfo {
|
|
86
|
+
token: string;
|
|
87
|
+
clientId: string;
|
|
88
|
+
scopes: string[];
|
|
89
|
+
/** Seconds since the epoch. */
|
|
90
|
+
expiresAt: number;
|
|
91
|
+
resource: URL;
|
|
92
|
+
extra: {
|
|
93
|
+
userId: string;
|
|
94
|
+
tenantId: string;
|
|
95
|
+
email?: string;
|
|
96
|
+
roles: string[];
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
interface McpAuth {
|
|
100
|
+
/** This server's address, in the form Cauthy compares it in. */
|
|
101
|
+
resource: string;
|
|
102
|
+
/** Where the protected resource metadata is served. */
|
|
103
|
+
metadataUrl: string;
|
|
104
|
+
/** The protected resource metadata (RFC 9728). */
|
|
105
|
+
metadata(): Record<string, unknown>;
|
|
106
|
+
/** The metadata's paths: `/.well-known/oauth-protected-resource` plus this server's path. */
|
|
107
|
+
metadataPaths: string[];
|
|
108
|
+
/** Verifies the `Authorization: Bearer` of a request (or a token). Throws `McpAuthError`. */
|
|
109
|
+
verify(from: string | Request | Headers, needs?: string[]): Promise<AgentIdentity>;
|
|
110
|
+
/** The answer to a refused token: 401 or 403, with the `WWW-Authenticate` that points an agent at Cauthy. */
|
|
111
|
+
challenge(error?: McpAuthError): Response;
|
|
112
|
+
/** The metadata, when the request asks for it; `null` otherwise. */
|
|
113
|
+
handleMetadata(request: Request): Response | null;
|
|
114
|
+
/** Wraps a fetch-style handler: serves the metadata, refuses what has no good token, passes the rest with who it is. */
|
|
115
|
+
protect(handler: (request: Request, agent: AgentIdentity) => Response | Promise<Response>, needs?: string[]): (request: Request) => Promise<Response>;
|
|
116
|
+
/**
|
|
117
|
+
* Connect-style middleware (Express, Node's http): serves the metadata,
|
|
118
|
+
* refuses what has no good token, and sets `req.agent` and `req.auth` —
|
|
119
|
+
* what the MCP TypeScript SDK's transport hands its tools as `authInfo`.
|
|
120
|
+
*/
|
|
121
|
+
middleware(needs?: string[]): (req: NodeRequest, res: NodeResponse, next: (err?: unknown) => void) => void;
|
|
122
|
+
/**
|
|
123
|
+
* Trades the agent's token this server received for one for another of the
|
|
124
|
+
* workspace's servers, to call it for the person (RFC 8693). Needs this
|
|
125
|
+
* server's `clientId` and `clientSecret`. Answers are kept until shortly
|
|
126
|
+
* before they expire. Throws `CauthyExchangeError` when Cauthy refuses.
|
|
127
|
+
*/
|
|
128
|
+
exchange(from: string | AgentIdentity, target: string, scopes?: string[]): Promise<ExchangedToken>;
|
|
129
|
+
}
|
|
130
|
+
interface NodeRequest {
|
|
131
|
+
method?: string;
|
|
132
|
+
url?: string;
|
|
133
|
+
originalUrl?: string;
|
|
134
|
+
headers: Record<string, string | string[] | undefined>;
|
|
135
|
+
auth?: McpAuthInfo;
|
|
136
|
+
agent?: AgentIdentity;
|
|
137
|
+
}
|
|
138
|
+
interface NodeResponse {
|
|
139
|
+
statusCode: number;
|
|
140
|
+
setHeader(name: string, value: string): unknown;
|
|
141
|
+
end(body?: string): unknown;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* The address in the one form Cauthy keeps it: scheme and host in lower case,
|
|
145
|
+
* no default port, no trailing slash, no query, no fragment.
|
|
146
|
+
*/
|
|
147
|
+
declare function canonicalResource(raw: string): string;
|
|
148
|
+
/** Protects an MCP server with Cauthy. */
|
|
149
|
+
declare function mcpAuth(options?: McpAuthOptions): McpAuth;
|
|
150
|
+
|
|
151
|
+
export { type AgentIdentity, CauthyExchangeError, type ExchangedToken, type McpAuth, McpAuthError, type McpAuthInfo, type McpAuthOptions, canonicalResource, mcpAuth };
|
package/dist/mcp.d.ts
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { JWTVerifyGetKey } from 'jose';
|
|
2
|
+
|
|
3
|
+
/** The person an agent acts for, and what they allowed it. */
|
|
4
|
+
interface AgentIdentity {
|
|
5
|
+
/** The person. */
|
|
6
|
+
userId: string;
|
|
7
|
+
tenantId: string;
|
|
8
|
+
email?: string;
|
|
9
|
+
/** The person's roles in the workspace. */
|
|
10
|
+
roles: string[];
|
|
11
|
+
/** What the person allowed the agent to do here. */
|
|
12
|
+
scopes: string[];
|
|
13
|
+
/** The agent (its client_id at Cauthy). */
|
|
14
|
+
clientId: string;
|
|
15
|
+
/** UTC, ISO 8601. */
|
|
16
|
+
expiresAt: string;
|
|
17
|
+
/** The token as it arrived. */
|
|
18
|
+
token: string;
|
|
19
|
+
/**
|
|
20
|
+
* Set when the token came by token exchange: the server that called this
|
|
21
|
+
* one for the person (the `act` claim's subject).
|
|
22
|
+
*/
|
|
23
|
+
actor?: string;
|
|
24
|
+
}
|
|
25
|
+
interface McpAuthOptions {
|
|
26
|
+
/** This server's address, as registered in Cauthy. Default: `CAUTHY_MCP_RESOURCE`. */
|
|
27
|
+
resource?: string;
|
|
28
|
+
/** Cauthy's address. Default: `CAUTHY_ISSUER`. */
|
|
29
|
+
issuer?: string;
|
|
30
|
+
/** Scopes every call needs. Default: none. */
|
|
31
|
+
scopes?: string[];
|
|
32
|
+
/** The scopes this server understands, to tell agents (`scopes_supported`). Default: `scopes`. */
|
|
33
|
+
scopesSupported?: string[];
|
|
34
|
+
/** A name for the server, shown by some agents. */
|
|
35
|
+
resourceName?: string;
|
|
36
|
+
/** Cauthy's keys. Default: fetched from the issuer and cached. */
|
|
37
|
+
jwks?: JWTVerifyGetKey;
|
|
38
|
+
/** The moment to verify at. Default: now. */
|
|
39
|
+
now?: () => Date;
|
|
40
|
+
/**
|
|
41
|
+
* Ask Cauthy, besides checking the token here, whether the person still
|
|
42
|
+
* allows the agent (RFC 7662). Then an agent is cut off the moment it is
|
|
43
|
+
* disconnected, not when its token runs out, at the price of a call to
|
|
44
|
+
* Cauthy per token every `cacheSeconds` (default 30). Default: off.
|
|
45
|
+
*/
|
|
46
|
+
introspect?: boolean | {
|
|
47
|
+
cacheSeconds?: number;
|
|
48
|
+
};
|
|
49
|
+
/** The fetch to call Cauthy with. Default: the global one. */
|
|
50
|
+
fetch?: typeof fetch;
|
|
51
|
+
/** How long a call to Cauthy (introspection, token exchange) may take, in milliseconds. Default: 5000. */
|
|
52
|
+
timeoutMs?: number;
|
|
53
|
+
/**
|
|
54
|
+
* This server's client_id and secret at Cauthy, for token exchange (AI
|
|
55
|
+
* agents → the server → Server credentials). Defaults:
|
|
56
|
+
* `CAUTHY_MCP_CLIENT_ID`, `CAUTHY_MCP_CLIENT_SECRET`.
|
|
57
|
+
*/
|
|
58
|
+
clientId?: string;
|
|
59
|
+
clientSecret?: string;
|
|
60
|
+
}
|
|
61
|
+
/** What a token exchange answers. */
|
|
62
|
+
interface ExchangedToken {
|
|
63
|
+
/** The token for the other server, as the person. Send it as `Authorization: Bearer`. */
|
|
64
|
+
accessToken: string;
|
|
65
|
+
/** What it allows there. */
|
|
66
|
+
scopes: string[];
|
|
67
|
+
/** UTC, ISO 8601. Never later than the agent's own token. */
|
|
68
|
+
expiresAt: string;
|
|
69
|
+
}
|
|
70
|
+
/** A token exchange Cauthy refused, with the OAuth error it answered. */
|
|
71
|
+
declare class CauthyExchangeError extends Error {
|
|
72
|
+
readonly status: number;
|
|
73
|
+
readonly code: string;
|
|
74
|
+
readonly description: string;
|
|
75
|
+
constructor(status: number, code: string, description: string);
|
|
76
|
+
}
|
|
77
|
+
/** A token refused: `status` is 401 (no token, or not a good one) or 403 (a scope missing). */
|
|
78
|
+
declare class McpAuthError extends Error {
|
|
79
|
+
readonly status: 401 | 403;
|
|
80
|
+
readonly code: 'invalid_request' | 'invalid_token' | 'insufficient_scope';
|
|
81
|
+
readonly description: string;
|
|
82
|
+
constructor(status: 401 | 403, code: 'invalid_request' | 'invalid_token' | 'insufficient_scope', description: string);
|
|
83
|
+
}
|
|
84
|
+
/** What the MCP TypeScript SDK reads from `req.auth` (its AuthInfo). */
|
|
85
|
+
interface McpAuthInfo {
|
|
86
|
+
token: string;
|
|
87
|
+
clientId: string;
|
|
88
|
+
scopes: string[];
|
|
89
|
+
/** Seconds since the epoch. */
|
|
90
|
+
expiresAt: number;
|
|
91
|
+
resource: URL;
|
|
92
|
+
extra: {
|
|
93
|
+
userId: string;
|
|
94
|
+
tenantId: string;
|
|
95
|
+
email?: string;
|
|
96
|
+
roles: string[];
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
interface McpAuth {
|
|
100
|
+
/** This server's address, in the form Cauthy compares it in. */
|
|
101
|
+
resource: string;
|
|
102
|
+
/** Where the protected resource metadata is served. */
|
|
103
|
+
metadataUrl: string;
|
|
104
|
+
/** The protected resource metadata (RFC 9728). */
|
|
105
|
+
metadata(): Record<string, unknown>;
|
|
106
|
+
/** The metadata's paths: `/.well-known/oauth-protected-resource` plus this server's path. */
|
|
107
|
+
metadataPaths: string[];
|
|
108
|
+
/** Verifies the `Authorization: Bearer` of a request (or a token). Throws `McpAuthError`. */
|
|
109
|
+
verify(from: string | Request | Headers, needs?: string[]): Promise<AgentIdentity>;
|
|
110
|
+
/** The answer to a refused token: 401 or 403, with the `WWW-Authenticate` that points an agent at Cauthy. */
|
|
111
|
+
challenge(error?: McpAuthError): Response;
|
|
112
|
+
/** The metadata, when the request asks for it; `null` otherwise. */
|
|
113
|
+
handleMetadata(request: Request): Response | null;
|
|
114
|
+
/** Wraps a fetch-style handler: serves the metadata, refuses what has no good token, passes the rest with who it is. */
|
|
115
|
+
protect(handler: (request: Request, agent: AgentIdentity) => Response | Promise<Response>, needs?: string[]): (request: Request) => Promise<Response>;
|
|
116
|
+
/**
|
|
117
|
+
* Connect-style middleware (Express, Node's http): serves the metadata,
|
|
118
|
+
* refuses what has no good token, and sets `req.agent` and `req.auth` —
|
|
119
|
+
* what the MCP TypeScript SDK's transport hands its tools as `authInfo`.
|
|
120
|
+
*/
|
|
121
|
+
middleware(needs?: string[]): (req: NodeRequest, res: NodeResponse, next: (err?: unknown) => void) => void;
|
|
122
|
+
/**
|
|
123
|
+
* Trades the agent's token this server received for one for another of the
|
|
124
|
+
* workspace's servers, to call it for the person (RFC 8693). Needs this
|
|
125
|
+
* server's `clientId` and `clientSecret`. Answers are kept until shortly
|
|
126
|
+
* before they expire. Throws `CauthyExchangeError` when Cauthy refuses.
|
|
127
|
+
*/
|
|
128
|
+
exchange(from: string | AgentIdentity, target: string, scopes?: string[]): Promise<ExchangedToken>;
|
|
129
|
+
}
|
|
130
|
+
interface NodeRequest {
|
|
131
|
+
method?: string;
|
|
132
|
+
url?: string;
|
|
133
|
+
originalUrl?: string;
|
|
134
|
+
headers: Record<string, string | string[] | undefined>;
|
|
135
|
+
auth?: McpAuthInfo;
|
|
136
|
+
agent?: AgentIdentity;
|
|
137
|
+
}
|
|
138
|
+
interface NodeResponse {
|
|
139
|
+
statusCode: number;
|
|
140
|
+
setHeader(name: string, value: string): unknown;
|
|
141
|
+
end(body?: string): unknown;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* The address in the one form Cauthy keeps it: scheme and host in lower case,
|
|
145
|
+
* no default port, no trailing slash, no query, no fragment.
|
|
146
|
+
*/
|
|
147
|
+
declare function canonicalResource(raw: string): string;
|
|
148
|
+
/** Protects an MCP server with Cauthy. */
|
|
149
|
+
declare function mcpAuth(options?: McpAuthOptions): McpAuth;
|
|
150
|
+
|
|
151
|
+
export { type AgentIdentity, CauthyExchangeError, type ExchangedToken, type McpAuth, McpAuthError, type McpAuthInfo, type McpAuthOptions, canonicalResource, mcpAuth };
|