@softure-ai/mcp-access 0.1.7 → 0.1.9
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 +25 -0
- package/README.md +42 -4
- package/dist/index.d.ts +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/next/actions.d.ts.map +1 -1
- package/dist/next/actions.js +4 -2
- package/dist/next/actions.js.map +1 -1
- package/dist/next/context.d.ts +7 -1
- package/dist/next/context.d.ts.map +1 -1
- package/dist/next/context.js +12 -10
- package/dist/next/context.js.map +1 -1
- package/dist/next/index.d.ts +1 -0
- package/dist/next/index.d.ts.map +1 -1
- package/dist/next/index.js +1 -0
- package/dist/next/index.js.map +1 -1
- package/dist/next/oauth-page.d.ts.map +1 -1
- package/dist/next/oauth-page.js +3 -2
- package/dist/next/oauth-page.js.map +1 -1
- package/dist/next/oauth-routes.d.ts +5 -2
- package/dist/next/oauth-routes.d.ts.map +1 -1
- package/dist/next/oauth-routes.js +9 -6
- package/dist/next/oauth-routes.js.map +1 -1
- package/dist/options.d.ts +26 -0
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +71 -0
- package/dist/options.js.map +1 -1
- package/dist/origins.d.ts +27 -0
- package/dist/origins.d.ts.map +1 -0
- package/dist/origins.js +32 -0
- package/dist/origins.js.map +1 -0
- package/dist/server/context.d.ts +4 -0
- package/dist/server/context.d.ts.map +1 -0
- package/dist/server/context.js +13 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/endpoint.d.ts.map +1 -1
- package/dist/server/endpoint.js +5 -3
- package/dist/server/endpoint.js.map +1 -1
- package/dist/server/index.d.ts +5 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +4 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/oauth-http.d.ts +30 -16
- package/dist/server/oauth-http.d.ts.map +1 -1
- package/dist/server/oauth-http.js +102 -47
- package/dist/server/oauth-http.js.map +1 -1
- package/dist/server/options.d.ts +3 -2
- package/dist/server/options.d.ts.map +1 -1
- package/dist/server/options.js +3 -3
- package/dist/server/options.js.map +1 -1
- package/dist/server/origins.d.ts +8 -0
- package/dist/server/origins.d.ts.map +1 -0
- package/dist/server/origins.js +15 -0
- package/dist/server/origins.js.map +1 -0
- package/module.json +1 -1
- package/package.json +1 -1
- package/src/index.ts +7 -2
- package/src/next/actions.ts +4 -2
- package/src/next/context.ts +15 -8
- package/src/next/index.ts +1 -0
- package/src/next/oauth-page.tsx +3 -2
- package/src/next/oauth-routes.ts +13 -5
- package/src/options.ts +80 -0
- package/src/origins.ts +48 -0
- package/src/server/context.ts +14 -0
- package/src/server/endpoint.ts +5 -3
- package/src/server/index.ts +6 -0
- package/src/server/oauth-http.ts +129 -46
- package/src/server/options.ts +4 -3
- package/src/server/origins.ts +19 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,31 @@ Newest first. Each version lists what changed for an app that uses `@softure-ai/
|
|
|
4
4
|
production, the version gets a line `verified in: <app>@<commit>` ([docs/05](../../docs/05-adoption-playbook.md),
|
|
5
5
|
"Definition of done"). Versions before the first one below are described in their GitHub Releases (`mcp-access@x.y.z`).
|
|
6
6
|
|
|
7
|
+
## 0.1.9
|
|
8
|
+
|
|
9
|
+
- The OAuth registration, token and consent decision routes read their body through `readSmallBody`
|
|
10
|
+
with a cap, `oauth.maxBodyBytes` (default 16 KiB, 1 KiB to 1 MiB). A larger body, announced or
|
|
11
|
+
streamed, is answered with `413` (`invalid_request` on registration and token, an empty `413` on
|
|
12
|
+
the decision) before it fills memory; an oversized token request still counts in the `mcp-oauth`
|
|
13
|
+
bucket, per address. Unreadable bodies (cut off, not UTF-8) get the answer each route gave before.
|
|
14
|
+
The consent form is parsed from the capped text, so urlencoded and multipart forms both work.
|
|
15
|
+
|
|
16
|
+
## 0.1.8
|
|
17
|
+
|
|
18
|
+
- OAuth URLs follow the request: `resolveAppOrigin(request)` (with `readRequestOrigin`, which reads
|
|
19
|
+
`Host` and `X-Forwarded-Proto`) sets the app origin per request for the issuer, the endpoints in
|
|
20
|
+
the metadata, `resource`, `resource_metadata` in the endpoint's `401`, `iss` and the consent
|
|
21
|
+
decision's `Origin` check. Without it nothing changes.
|
|
22
|
+
- `resourceOrigins`: other public hosts; the root protected resource metadata asked on one names it
|
|
23
|
+
as `resource`, and the authorization and token endpoints accept it.
|
|
24
|
+
- `oauth.metadata.authorizationServer` / `.protectedResource`: extra discovery keys (an object, or
|
|
25
|
+
a function of the request's origins); generated keys win, `resource_name` can be replaced.
|
|
26
|
+
- Discovery documents carry `Vary: host, x-forwarded-proto`; `getAuthorizationServerMetadataRoute`
|
|
27
|
+
now reads the request (re-exporting it as `GET` keeps working).
|
|
28
|
+
- New exports: `createMcpAccessContext` and `resolveMcpOrigins` (`/server`), `getMcpAccessContext`
|
|
29
|
+
(`/next`), `OAuthClientRow`, `McpOrigins` and `readRequestOrigin` (root and `/server`). URL
|
|
30
|
+
builders take the origins as an optional last argument.
|
|
31
|
+
|
|
7
32
|
## 0.1.7
|
|
8
33
|
|
|
9
34
|
- OAuth 2.1 for MCP clients, opt-in (`oauth.enabled`): protected resource and authorization server
|
package/README.md
CHANGED
|
@@ -84,7 +84,11 @@ mcpAccess({
|
|
|
84
84
|
| `oauth.accessTokenLifetimeMinutes` | `integer` 5–1440 | `60` | Lifetime of an access token issued through OAuth; the client refreshes it. |
|
|
85
85
|
| `oauth.refreshTokenLifetimeDays` | `integer` 1–365 | `90` | Lifetime of a refresh token, renewed on every rotation. An unused connection ends after it. |
|
|
86
86
|
| `oauth.authorizationCodeLifetimeMinutes` | `integer` 1–10 | `10` | Lifetime of an authorization code (single use). |
|
|
87
|
-
| `
|
|
87
|
+
| `oauth.maxBodyBytes` | `integer` 1024–1048576 | `16384` | The largest body the registration, token and consent decision routes read. Larger: `413` (`invalid_request` on registration and token), before it fills memory. Real bodies stay under 4 KiB. |
|
|
88
|
+
| `oauth.metadata` | `{ authorizationServer?, protectedResource? }`, each an object or `(origins) => object` | — | Extra keys of the discovery documents (`jwks_uri`, `service_documentation`, `resource_documentation`, `agent_auth`…). Generated keys win; a static object that sets one is refused at startup. The protected resource document takes the app's `resource_name` (default: `serverName`). |
|
|
89
|
+
| `resolveAppOrigin` | `(request) => string \| null` | — | The app origin of one request, when it is not the fixed `appOrigin` (an image built once and served elsewhere, a proxy). `readRequestOrigin` reads it from `Host`. Null keeps `appOrigin`; anything but a bare http(s) origin throws. |
|
|
90
|
+
| `resourceOrigins` | `string[]` (≤ 16 http(s) origins) | `[]` | Other public hosts of the app, e.g. the apex next to `app.`: the root protected resource metadata asked on one of them names it as `resource`, and the OAuth endpoints accept it as `resource`. |
|
|
91
|
+
| `routes` | `{ page?, endpoint?, oauthConsent?, oauthDecision?, oauthToken?, oauthRegister? }` | `/account/mcp`, `/api/mcp`, `/oauth/authorize`, `/api/oauth/authorize`, `/api/oauth/token`, `/api/oauth/register` | Move the page, the endpoint or the OAuth paths; URLs in the setup and the metadata are the app origin (`appOrigin`, or `resolveAppOrigin`'s) + the path. |
|
|
88
92
|
| `messages` | partial `en` / `pl` | — | Copy overrides. |
|
|
89
93
|
|
|
90
94
|
`allowWrites` is a deploy decision, so read it from the environment rather than hard-coding it:
|
|
@@ -94,7 +98,8 @@ keeps every token read-only.
|
|
|
94
98
|
`MCP_RATE_LIMIT_BUCKETS` is `{ mcp: { limit: 200, windowMinutes: 15 }, "mcp-oauth": { limit: 60, windowMinutes: 15 } }`
|
|
95
99
|
per client address. Every endpoint request counts, valid or not, and before the token lookup;
|
|
96
100
|
assistants behind one address share it. `mcp-oauth` counts the public OAuth requests:
|
|
97
|
-
registrations per address, token requests per address and client
|
|
101
|
+
registrations per address, token requests per address and client (a token request whose body
|
|
102
|
+
is over `oauth.maxBodyBytes` counts per address, since its client id is never read).
|
|
98
103
|
|
|
99
104
|
## 4. Mounting
|
|
100
105
|
|
|
@@ -163,10 +168,42 @@ export { getProtectedResourceMetadataRoute as GET, answerOAuthPreflight as OPTIO
|
|
|
163
168
|
`/.well-known/oauth-*`, `/api/oauth/token` and `/api/oauth/register` are public: keep them out of
|
|
164
169
|
a proxy guard, like `/api/mcp`. The consent page and the decision route check the session
|
|
165
170
|
themselves (the page sends a signed-out person to the login page and back); the decision route
|
|
166
|
-
also refuses a request whose `Origin` is not
|
|
171
|
+
also refuses a request whose `Origin` is not the app origin.
|
|
167
172
|
TypeScript's `**` skips dot folders: with an `include` list in `tsconfig.json`, add
|
|
168
173
|
`"app/.well-known/**/*.ts"`.
|
|
169
174
|
|
|
175
|
+
**Origins.** Every OAuth URL (issuer, endpoints, `resource`, `resource_metadata`, `iss`) and the
|
|
176
|
+
decision's `Origin` check use the app origin of the request: `appOrigin`, unless
|
|
177
|
+
`resolveAppOrigin` answers. The discovery routes read the request, so Next never renders them at
|
|
178
|
+
build time, and they answer with `Vary: host, x-forwarded-proto`.
|
|
179
|
+
|
|
180
|
+
- *An image built once and served under another origin* (a test stack on another port, a
|
|
181
|
+
production image against a local stack): `resolveAppOrigin: process.env.APP_ORIGIN ? undefined :
|
|
182
|
+
readRequestOrigin`. `readRequestOrigin` trusts `Host` and `X-Forwarded-Proto`, so use it only
|
|
183
|
+
behind a proxy that passes `Host` through and refuses hosts it does not serve. The consent page,
|
|
184
|
+
its decision and the token endpoint then agree on the origin the browser used.
|
|
185
|
+
- *A second public host* (product on `https://app.example.com`, site on `https://example.com`):
|
|
186
|
+
`resourceOrigins: ["https://example.com"]`, and route that host's `/.well-known/oauth-*` to the
|
|
187
|
+
app. Its root protected resource metadata names `https://example.com` as `resource` (RFC 9728
|
|
188
|
+
§3.3) with the authorization server on the app origin; `Host` only picks among the listed
|
|
189
|
+
origins.
|
|
190
|
+
- *Discovery extras:* keys the app adds and serves itself, computed from the request's origins:
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
oauth: {
|
|
194
|
+
enabled: true,
|
|
195
|
+
metadata: {
|
|
196
|
+
authorizationServer: ({ appOrigin }) => ({ jwks_uri: `${appOrigin}/.well-known/jwks.json` }),
|
|
197
|
+
protectedResource: { resource_name: "Acme MCP server", resource_documentation: "https://example.com/docs/mcp" },
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
An app that composes its own routes from `/server` builds the context with
|
|
203
|
+
`createMcpAccessContext(config)` (`getMcpAccessContext()` in `/next` reads the registered config),
|
|
204
|
+
resolves origins with `resolveMcpOrigins(config, request)` and passes them to the URL builders,
|
|
205
|
+
whose last argument they are; `OAuthClientRow` is exported from the package root.
|
|
206
|
+
|
|
170
207
|
## 5. Migrations and tables
|
|
171
208
|
|
|
172
209
|
`migrations/0001_create_access_tokens.sql` creates `mcp.access_tokens`:
|
|
@@ -260,7 +297,8 @@ to `@softure-ai/privacy` (`privacy` flags on):
|
|
|
260
297
|
## 12. Limitations / known gaps
|
|
261
298
|
|
|
262
299
|
- OAuth has no token introspection or revocation endpoint (RFC 7009) for clients: the person
|
|
263
|
-
disconnects an app on the token page. Access tokens are opaque;
|
|
300
|
+
disconnects an app on the token page. Access tokens are opaque; the package serves no JWKS (an
|
|
301
|
+
app that wants `jwks_uri` adds it through `oauth.metadata` and serves the empty set itself).
|
|
264
302
|
- Only `S256` PKCE and the `authorization_code` and `refresh_token` grants.
|
|
265
303
|
- Write access is per token, not per tool; finer scopes would be a new option.
|
|
266
304
|
- The rate limit is per client address, not per token.
|
package/dist/index.d.ts
CHANGED
|
@@ -151,17 +151,25 @@ export declare const mcpAccess: import("@softure-ai/core").ModuleFactory<{
|
|
|
151
151
|
maxTokensPerUser: import("zod").ZodDefault<import("zod").ZodInt>;
|
|
152
152
|
expiryWarningDays: import("zod").ZodDefault<import("zod").ZodInt>;
|
|
153
153
|
legacyTokenPattern: import("zod").ZodOptional<import("zod").ZodInstanceOf<RegExp>>;
|
|
154
|
+
resolveAppOrigin: import("zod").ZodOptional<import("zod").ZodCustom<import("./options.js").McpAppOriginResolver, import("./options.js").McpAppOriginResolver>>;
|
|
155
|
+
resourceOrigins: import("zod").ZodDefault<import("zod").ZodArray<import("zod").ZodPipe<import("zod").ZodString, import("zod").ZodTransform<string, string>>>>;
|
|
154
156
|
oauth: import("zod").ZodPrefault<import("zod").ZodObject<{
|
|
155
157
|
enabled: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
156
158
|
accessTokenLifetimeMinutes: import("zod").ZodDefault<import("zod").ZodInt>;
|
|
157
159
|
refreshTokenLifetimeDays: import("zod").ZodDefault<import("zod").ZodInt>;
|
|
158
160
|
authorizationCodeLifetimeMinutes: import("zod").ZodDefault<import("zod").ZodInt>;
|
|
161
|
+
maxBodyBytes: import("zod").ZodDefault<import("zod").ZodInt>;
|
|
162
|
+
metadata: import("zod").ZodPrefault<import("zod").ZodObject<{
|
|
163
|
+
authorizationServer: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodCustom<(origins: import("./origins.js").McpOrigins) => Readonly<Record<string, unknown>>, (origins: import("./origins.js").McpOrigins) => Readonly<Record<string, unknown>>>, import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>]>>;
|
|
164
|
+
protectedResource: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodCustom<(origins: import("./origins.js").McpOrigins) => Readonly<Record<string, unknown>>, (origins: import("./origins.js").McpOrigins) => Readonly<Record<string, unknown>>>, import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>]>>;
|
|
165
|
+
}, import("zod/v4/core").$strict>>;
|
|
159
166
|
}, import("zod/v4/core").$strict>>;
|
|
160
167
|
}, import("zod/v4/core").$strict>>;
|
|
161
168
|
export { getAuthorizationHeader, getClaudeCodeCommand, getClaudeCodeLink, getDesktopConfig, getJsonConfig, getMcpClientSetup, type McpClientSetupInput, } from "./client-setup.js";
|
|
162
169
|
export type { AccessTokenStatus, AccessTokenView, IssuedToken, IssueTokenFormState, McpAccessErrorCode, McpClientSetup, McpServerIdentity, OAuthGrantView, RevokeGrantFormState, RevokeTokenFormState, TokenFormErrorCode, } from "./contract.js";
|
|
163
170
|
export { getTokenErrorMessage, mcpAccessMessages, type McpAccessMessages } from "./messages/index.js";
|
|
164
|
-
export { MAX_PRESENTED_TOKEN_LENGTH, MAX_TOKEN_NAME_LENGTH, SERVER_NAME_PATTERN, TOOL_NAME_PATTERN, type McpAccessOptions, type McpAccessOptionsInput, type McpOAuthOptions, type McpToolAccess, type McpToolDefinition, type McpToolDefinitionInput, } from "./options.js";
|
|
165
|
-
export {
|
|
171
|
+
export { MAX_PRESENTED_TOKEN_LENGTH, MAX_TOKEN_NAME_LENGTH, SERVER_NAME_PATTERN, TOOL_NAME_PATTERN, GENERATED_AUTHORIZATION_SERVER_KEYS, GENERATED_PROTECTED_RESOURCE_KEYS, type McpAccessOptions, type McpAccessOptionsInput, type McpAppOriginResolver, type McpMetadataExtension, type McpOAuthOptions, type McpToolAccess, type McpToolDefinition, type McpToolDefinitionInput, } from "./options.js";
|
|
172
|
+
export { readRequestOrigin, type McpOriginRequest, type McpOrigins } from "./origins.js";
|
|
173
|
+
export { accessTokens, oauthAuthorizationCodes, oauthClients, oauthGrants, type OAuthClientRow, type OAuthTokenEndpointAuthMethod } from "./schema.js";
|
|
166
174
|
export { getAccessTokenStatus, type AccessTokenStatusOptions } from "./token-status.js";
|
|
167
175
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,SAAS,eAAe,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,sBAAsB;;;;;IAEjC;;;;OAIG;;;;;CAEK,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,SAAS
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,SAAS,eAAe,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,sBAAsB;;;;;IAEjC;;;;OAIG;;;;;CAEK,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kCAmCpB,CAAC;AAEH,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,KAAK,mBAAmB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACtG,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,mCAAmC,EACnC,iCAAiC,EACjC,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AACzF,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,cAAc,EAAE,KAAK,4BAA4B,EAAE,MAAM,aAAa,CAAC;AACvJ,OAAO,EAAE,oBAAoB,EAAE,KAAK,wBAAwB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -29,7 +29,7 @@ export const MCP_RATE_LIMIT_BUCKETS = {
|
|
|
29
29
|
export const mcpAccess = defineModule({
|
|
30
30
|
manifest: {
|
|
31
31
|
id: MODULE_ID,
|
|
32
|
-
version: "0.1.
|
|
32
|
+
version: "0.1.9",
|
|
33
33
|
dependsOn: { security: "^0.1.0", auth: "^0.1.0" },
|
|
34
34
|
dbSchema: "mcp",
|
|
35
35
|
tables: ["access_tokens", "oauth_clients", "oauth_authorization_codes", "oauth_grants"],
|
|
@@ -64,7 +64,8 @@ export const mcpAccess = defineModule({
|
|
|
64
64
|
});
|
|
65
65
|
export { getAuthorizationHeader, getClaudeCodeCommand, getClaudeCodeLink, getDesktopConfig, getJsonConfig, getMcpClientSetup, } from "./client-setup.js";
|
|
66
66
|
export { getTokenErrorMessage, mcpAccessMessages } from "./messages/index.js";
|
|
67
|
-
export { MAX_PRESENTED_TOKEN_LENGTH, MAX_TOKEN_NAME_LENGTH, SERVER_NAME_PATTERN, TOOL_NAME_PATTERN, } from "./options.js";
|
|
67
|
+
export { MAX_PRESENTED_TOKEN_LENGTH, MAX_TOKEN_NAME_LENGTH, SERVER_NAME_PATTERN, TOOL_NAME_PATTERN, GENERATED_AUTHORIZATION_SERVER_KEYS, GENERATED_PROTECTED_RESOURCE_KEYS, } from "./options.js";
|
|
68
|
+
export { readRequestOrigin } from "./origins.js";
|
|
68
69
|
export { accessTokens, oauthAuthorizationCodes, oauthClients, oauthGrants } from "./schema.js";
|
|
69
70
|
export { getAccessTokenStatus } from "./token-status.js";
|
|
70
71
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/next/actions.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AA+BtG,qGAAqG;AACrG,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,mBAAmB,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,mBAAmB,CAAC,
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/next/actions.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AA+BtG,qGAAqG;AACrG,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,mBAAmB,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAiCvH;AAED,wFAAwF;AACxF,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,oBAAoB,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAc1H;AAED,sGAAsG;AACtG,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,oBAAoB,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAc1H"}
|
package/dist/next/actions.js
CHANGED
|
@@ -12,7 +12,7 @@ import { MAX_TOKEN_NAME_LENGTH } from "../options.js";
|
|
|
12
12
|
import { getMcpAccessMessages, getMcpAccessOptions, getMcpAccessRoutes, getMcpEndpointUrl } from "../server/options.js";
|
|
13
13
|
import { revokeOAuthGrant } from "../server/oauth.js";
|
|
14
14
|
import { issueAccessToken, revokeAccessToken } from "../server/tokens.js";
|
|
15
|
-
import { getMcpAccessContext } from "./context.js";
|
|
15
|
+
import { getMcpAccessContext, getRequestOrigins } from "./context.js";
|
|
16
16
|
import { formatDate } from "./format.js";
|
|
17
17
|
/** Longer values are cut: the server functions refuse them anyway, and nothing huge is echoed back. */
|
|
18
18
|
const MAX_FIELD_LENGTH = MAX_TOKEN_NAME_LENGTH * 4;
|
|
@@ -42,6 +42,8 @@ export async function issueTokenAction(_previous, formData) {
|
|
|
42
42
|
// Every field has a `catch`, so parsing cannot fail.
|
|
43
43
|
const input = issueInput.parse({ name: formData.get("name"), canWrite: formData.get("canWrite") });
|
|
44
44
|
try {
|
|
45
|
+
// Resolved before issuing: a failure afterwards would leave a token nobody received.
|
|
46
|
+
const endpointUrl = getMcpEndpointUrl(config, await getRequestOrigins(config, getMcpAccessRoutes(config).page));
|
|
45
47
|
const result = await issueAccessToken(await getMcpAccessContext(config), { userId: user.id, name: input.name, canWrite: input.canWrite !== null });
|
|
46
48
|
if (!result.ok)
|
|
47
49
|
return { status: "error", error: result.error };
|
|
@@ -57,7 +59,7 @@ export async function issueTokenAction(_previous, formData) {
|
|
|
57
59
|
expiresText: formatMessage(messages.issued.expires, { date: formatDate(config, issued.expiresAt) }),
|
|
58
60
|
setup: getMcpClientSetup({
|
|
59
61
|
serverName: getMcpAccessOptions(config).serverName,
|
|
60
|
-
endpointUrl
|
|
62
|
+
endpointUrl,
|
|
61
63
|
token: issued.token,
|
|
62
64
|
promptTemplate: messages.setup.assistantPrompt,
|
|
63
65
|
}),
|
package/dist/next/actions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/next/actions.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,kGAAkG;AAClG,+FAA+F;AAC/F,2FAA2F;AAC3F,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,SAAS,EAAsB,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACxH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/next/actions.ts"],"names":[],"mappings":"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"}
|
package/dist/next/context.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { SoftureConfig } from "@softure-ai/core";
|
|
2
|
+
import type { McpOrigins } from "../origins.js";
|
|
2
3
|
import type { McpAccessContext } from "../server/tokens.js";
|
|
3
4
|
export declare function getMcpAccessContext(config?: SoftureConfig): Promise<McpAccessContext>;
|
|
5
|
+
/**
|
|
6
|
+
* The origins of the request a page or a server action runs in, from Next's `headers()`: the same
|
|
7
|
+
* ones the route handlers resolve, so the consent page and its decision agree.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getRequestOrigins(config: SoftureConfig, path: string): Promise<McpOrigins>;
|
|
4
10
|
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/next/context.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/next/context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,wBAAgB,mBAAmB,CAAC,MAAM,GAAE,aAAkC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAEzG;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAGhG"}
|
package/dist/next/context.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
// What the adapter hands the server functions: the registered config, the process-wide database
|
|
2
|
-
// handle and the wall clock.
|
|
3
|
-
import { systemClock } from "@softure-ai/core";
|
|
4
1
|
import { getSoftureConfig } from "@softure-ai/core/next";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
import { createMcpAccessContext } from "../server/context.js";
|
|
3
|
+
import { resolveMcpOrigins } from "../server/origins.js";
|
|
4
|
+
export function getMcpAccessContext(config = getSoftureConfig()) {
|
|
5
|
+
return createMcpAccessContext(config);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The origins of the request a page or a server action runs in, from Next's `headers()`: the same
|
|
9
|
+
* ones the route handlers resolve, so the consent page and its decision agree.
|
|
10
|
+
*/
|
|
11
|
+
export async function getRequestOrigins(config, path) {
|
|
12
|
+
const { headers } = await import("next/headers");
|
|
13
|
+
return resolveMcpOrigins(config, { url: new URL(path, config.appOrigin).toString(), headers: await headers() });
|
|
12
14
|
}
|
|
13
15
|
//# sourceMappingURL=context.js.map
|
package/dist/next/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/next/context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/next/context.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAGzD,MAAM,UAAU,mBAAmB,CAAC,SAAwB,gBAAgB,EAAE;IAC5E,OAAO,sBAAsB,CAAC,MAAM,CAAC,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAqB,EAAE,IAAY;IACzE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;IACjD,OAAO,iBAAiB,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,MAAM,OAAO,EAAE,EAAE,CAAC,CAAC;AAClH,CAAC"}
|
package/dist/next/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { issueTokenAction, revokeGrantAction, revokeTokenAction } from "./actions.js";
|
|
2
2
|
export { OAuthConsentPage, type OAuthConsentPageProps } from "./oauth-page.js";
|
|
3
3
|
export { answerOAuthPreflight, decideOAuthAuthorizationRoute, exchangeOAuthTokenRoute, getAuthorizationServerMetadataRoute, getProtectedResourceMetadataRoute, registerOAuthClientRoute, } from "./oauth-routes.js";
|
|
4
|
+
export { getMcpAccessContext } from "./context.js";
|
|
4
5
|
export { McpAccessPage } from "./pages.js";
|
|
5
6
|
export { createMcpRoute } from "./route.js";
|
|
6
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/next/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EACL,oBAAoB,EACpB,6BAA6B,EAC7B,uBAAuB,EACvB,mCAAmC,EACnC,iCAAiC,EACjC,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EACL,oBAAoB,EACpB,6BAA6B,EAC7B,uBAAuB,EACvB,mCAAmC,EACnC,iCAAiC,EACjC,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/next/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
export { issueTokenAction, revokeGrantAction, revokeTokenAction } from "./actions.js";
|
|
4
4
|
export { OAuthConsentPage } from "./oauth-page.js";
|
|
5
5
|
export { answerOAuthPreflight, decideOAuthAuthorizationRoute, exchangeOAuthTokenRoute, getAuthorizationServerMetadataRoute, getProtectedResourceMetadataRoute, registerOAuthClientRoute, } from "./oauth-routes.js";
|
|
6
|
+
export { getMcpAccessContext } from "./context.js";
|
|
6
7
|
export { McpAccessPage } from "./pages.js";
|
|
7
8
|
export { createMcpRoute } from "./route.js";
|
|
8
9
|
//# sourceMappingURL=index.js.map
|
package/dist/next/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,yFAAyF;AACzF,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAA8B,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EACL,oBAAoB,EACpB,6BAA6B,EAC7B,uBAAuB,EACvB,mCAAmC,EACnC,iCAAiC,EACjC,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,yFAAyF;AACzF,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAA8B,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EACL,oBAAoB,EACpB,6BAA6B,EAC7B,uBAAuB,EACvB,mCAAmC,EACnC,iCAAiC,EACjC,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-page.d.ts","sourceRoot":"","sources":["../../src/next/oauth-page.tsx"],"names":[],"mappings":"AAiBA,KAAK,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC;AAE3E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;CACtC;AAID,wBAAsB,gBAAgB,CAAC,EAAE,YAAY,EAAE,EAAE,qBAAqB,
|
|
1
|
+
{"version":3,"file":"oauth-page.d.ts","sourceRoot":"","sources":["../../src/next/oauth-page.tsx"],"names":[],"mappings":"AAiBA,KAAK,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC;AAE3E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;CACtC;AAID,wBAAsB,gBAAgB,CAAC,EAAE,YAAY,EAAE,EAAE,qBAAqB,wCA0C7E"}
|
package/dist/next/oauth-page.js
CHANGED
|
@@ -14,7 +14,7 @@ import { getConsentPath, isOAuthEnabled, readAuthorizationParams, validateAuthor
|
|
|
14
14
|
import { describeRedirectUri } from "../server/oauth-validation.js";
|
|
15
15
|
import { getMcpAccessMessages, getMcpAccessOptions, getMcpAccessRoutes } from "../server/options.js";
|
|
16
16
|
import { ConsentError, ConsentForm } from "../ui/consent-form.js";
|
|
17
|
-
import { getMcpAccessContext } from "./context.js";
|
|
17
|
+
import { getMcpAccessContext, getRequestOrigins } from "./context.js";
|
|
18
18
|
const LAYOUT_CLASS = "sft:mx-auto sft:box-border sft:w-full sft:sm:max-w-md sft:px-4 sft:py-4";
|
|
19
19
|
export async function OAuthConsentPage({ searchParams }) {
|
|
20
20
|
const config = getSoftureConfig();
|
|
@@ -24,7 +24,8 @@ export async function OAuthConsentPage({ searchParams }) {
|
|
|
24
24
|
const params = readAuthorizationParams({ get: (name) => query[name] });
|
|
25
25
|
const user = await requireUser({ next: getConsentPath(config, params), searchParams: query });
|
|
26
26
|
const messages = getMcpAccessMessages(config);
|
|
27
|
-
const
|
|
27
|
+
const origins = await getRequestOrigins(config, getMcpAccessRoutes(config).oauthConsent);
|
|
28
|
+
const outcome = await validateAuthorizationRequest(await getMcpAccessContext(config), params, origins);
|
|
28
29
|
if (outcome.kind !== "valid") {
|
|
29
30
|
const message = outcome.kind === "redirect-error" ? messages.consent.invalidRequest : outcome.reason === "unknown_client" ? messages.consent.unknownClient : messages.consent.redirectMismatch;
|
|
30
31
|
return (_jsx("main", { className: LAYOUT_CLASS, children: _jsx(Card, { title: messages.consent.errorTitle, children: _jsx(ConsentError, { message: message, ...(outcome.kind === "redirect-error" ? { backLocation: outcome.location, backTarget: describeRedirectUri(outcome.redirectUri) } : {}), messages: messages }) }) }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-page.js","sourceRoot":"","sources":["../../src/next/oauth-page.tsx"],"names":[],"mappings":";AAAA,wDAAwD;AACxD,+EAA+E;AAC/E,+FAA+F;AAC/F,kGAAkG;AAClG,oGAAoG;AACpG,mFAAmF;AACnF,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,uBAAuB,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AAChI,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrG,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"oauth-page.js","sourceRoot":"","sources":["../../src/next/oauth-page.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { answerOAuthPreflight } from "../server/oauth-http.js";
|
|
2
|
-
/**
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* `GET /.well-known/oauth-authorization-server`. Reads the request, so Next never renders it at
|
|
4
|
+
* build time with one origin baked in.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getAuthorizationServerMetadataRoute(request: Request): Response;
|
|
4
7
|
/**
|
|
5
8
|
* `GET /.well-known/oauth-protected-resource` and `…/oauth-protected-resource/api/mcp`: the same
|
|
6
9
|
* export at both paths; the request's path picks the variant.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-routes.d.ts","sourceRoot":"","sources":["../../src/next/oauth-routes.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,oBAAoB,
|
|
1
|
+
{"version":3,"file":"oauth-routes.d.ts","sourceRoot":"","sources":["../../src/next/oauth-routes.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,oBAAoB,EAQrB,MAAM,yBAAyB,CAAC;AAiBjC;;;GAGG;AACH,wBAAgB,mCAAmC,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAE9E;AAED;;;GAGG;AACH,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAO5E;AAED,kCAAkC;AAClC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAE5E;AAED,+BAA+B;AAC/B,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAE3E;AAED,qFAAqF;AACrF,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAKjF;AAED,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { getCurrentUser } from "@softure-ai/auth/next";
|
|
6
6
|
import { errorLogLabel } from "@softure-ai/core";
|
|
7
7
|
import { getSoftureConfig } from "@softure-ai/core/next";
|
|
8
|
-
import { answerOAuthPreflight, getAuthorizationServerMetadata, getProtectedResourceMetadata, handleAuthorizationDecision, handleClientRegistration, handleTokenRequest, serveDiscoveryDocument, } from "../server/oauth-http.js";
|
|
8
|
+
import { answerOAuthPreflight, getAuthorizationServerMetadata, getProtectedResourceMetadata, getRootProtectedResourceMetadata, handleAuthorizationDecision, handleClientRegistration, handleTokenRequest, serveDiscoveryDocument, } from "../server/oauth-http.js";
|
|
9
9
|
import { getMcpAccessContext } from "./context.js";
|
|
10
10
|
const UNAVAILABLE = { status: 503, headers: { "cache-control": "no-store" } };
|
|
11
11
|
async function withContext(request, handle) {
|
|
@@ -19,17 +19,20 @@ async function withContext(request, handle) {
|
|
|
19
19
|
}
|
|
20
20
|
return handle(ctx, request);
|
|
21
21
|
}
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
/**
|
|
23
|
+
* `GET /.well-known/oauth-authorization-server`. Reads the request, so Next never renders it at
|
|
24
|
+
* build time with one origin baked in.
|
|
25
|
+
*/
|
|
26
|
+
export function getAuthorizationServerMetadataRoute(request) {
|
|
27
|
+
return serveDiscoveryDocument(getSoftureConfig(), (config, origins) => getAuthorizationServerMetadata(config, origins), request);
|
|
25
28
|
}
|
|
26
29
|
/**
|
|
27
30
|
* `GET /.well-known/oauth-protected-resource` and `…/oauth-protected-resource/api/mcp`: the same
|
|
28
31
|
* export at both paths; the request's path picks the variant.
|
|
29
32
|
*/
|
|
30
33
|
export function getProtectedResourceMetadataRoute(request) {
|
|
31
|
-
const
|
|
32
|
-
return serveDiscoveryDocument(getSoftureConfig(), (config) => getProtectedResourceMetadata(config,
|
|
34
|
+
const isRoot = new URL(request.url).pathname.replace(/\/+$/, "").endsWith("/oauth-protected-resource");
|
|
35
|
+
return serveDiscoveryDocument(getSoftureConfig(), isRoot ? getRootProtectedResourceMetadata : (config, origins) => getProtectedResourceMetadata(config, "endpoint", origins), request);
|
|
33
36
|
}
|
|
34
37
|
/** `POST /api/oauth/register`. */
|
|
35
38
|
export function registerOAuthClientRoute(request) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-routes.js","sourceRoot":"","sources":["../../src/next/oauth-routes.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,mJAAmJ;AACnJ,gGAAgG;AAChG,6DAA6D;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EACL,oBAAoB,EACpB,8BAA8B,EAC9B,4BAA4B,EAC5B,2BAA2B,EAC3B,wBAAwB,EACxB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,WAAW,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,eAAe,EAAE,UAAU,EAAE,EAAE,CAAC;AAE9E,KAAK,UAAU,WAAW,CAAC,OAAgB,EAAE,MAAsE;IACjH,IAAI,GAAG,CAAC;IACR,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,mBAAmB,EAAE,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,wDAAwD,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9F,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,EAAE,WAAW,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAC9B,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"oauth-routes.js","sourceRoot":"","sources":["../../src/next/oauth-routes.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,mJAAmJ;AACnJ,gGAAgG;AAChG,6DAA6D;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EACL,oBAAoB,EACpB,8BAA8B,EAC9B,4BAA4B,EAC5B,gCAAgC,EAChC,2BAA2B,EAC3B,wBAAwB,EACxB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,WAAW,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,eAAe,EAAE,UAAU,EAAE,EAAE,CAAC;AAE9E,KAAK,UAAU,WAAW,CAAC,OAAgB,EAAE,MAAsE;IACjH,IAAI,GAAG,CAAC;IACR,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,mBAAmB,EAAE,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,wDAAwD,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9F,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,EAAE,WAAW,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mCAAmC,CAAC,OAAgB;IAClE,OAAO,sBAAsB,CAAC,gBAAgB,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,8BAA8B,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;AACnI,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iCAAiC,CAAC,OAAgB;IAChE,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAAC;IACvG,OAAO,sBAAsB,CAC3B,gBAAgB,EAAE,EAClB,MAAM,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,4BAA4B,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAC1H,OAAO,CACR,CAAC;AACJ,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,wBAAwB,CAAC,OAAgB;IACvD,OAAO,WAAW,CAAC,OAAO,EAAE,wBAAwB,CAAC,CAAC;AACxD,CAAC;AAED,+BAA+B;AAC/B,MAAM,UAAU,uBAAuB,CAAC,OAAgB;IACtD,OAAO,WAAW,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;AAClD,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,6BAA6B,CAAC,OAAgB;IAC5D,OAAO,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QAC7C,MAAM,IAAI,GAAG,MAAM,cAAc,EAAE,CAAC;QACpC,OAAO,2BAA2B,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,IAAI,IAAI,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
|
package/dist/options.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import type { McpOriginRequest, McpOrigins } from "./origins.js";
|
|
2
3
|
/** The name an MCP client lists the server under: no spaces, so a shell command needs no quotes. */
|
|
3
4
|
export declare const SERVER_NAME_PATTERN: RegExp;
|
|
4
5
|
/** The MCP rule for tool names: 1 to 128 of A-Z, a-z, 0-9, `_`, `-` and `.`. */
|
|
@@ -18,11 +19,29 @@ declare const toolSchema: z.ZodObject<{
|
|
|
18
19
|
pl: "pl";
|
|
19
20
|
}> & z.core.$partial, z.ZodString>;
|
|
20
21
|
}, z.core.$strict>;
|
|
22
|
+
/**
|
|
23
|
+
* Keys of the authorization server metadata the package generates. An extension cannot set them:
|
|
24
|
+
* they decide where a client sends a person and its secrets.
|
|
25
|
+
*/
|
|
26
|
+
export declare const GENERATED_AUTHORIZATION_SERVER_KEYS: readonly ["issuer", "authorization_endpoint", "token_endpoint", "registration_endpoint", "scopes_supported", "response_types_supported", "response_modes_supported", "grant_types_supported", "token_endpoint_auth_methods_supported", "code_challenge_methods_supported", "authorization_response_iss_parameter_supported"];
|
|
27
|
+
/** Keys of the protected resource metadata the package generates; `resource_name` is the app's to replace. */
|
|
28
|
+
export declare const GENERATED_PROTECTED_RESOURCE_KEYS: readonly ["resource", "authorization_servers", "scopes_supported", "bearer_methods_supported"];
|
|
29
|
+
/** Extra keys of a discovery document: a JSON object, or computed from the request's origins. */
|
|
30
|
+
export type McpMetadataExtension = Readonly<Record<string, unknown>> | ((origins: McpOrigins) => Readonly<Record<string, unknown>>);
|
|
31
|
+
/** The app origin of one request, or null for `appOrigin`. */
|
|
32
|
+
export type McpAppOriginResolver = (request: McpOriginRequest) => string | null;
|
|
33
|
+
/** A bare http(s) origin (no path, query, fragment or credentials), reduced to its origin. */
|
|
34
|
+
export declare function isBareOrigin(value: string): boolean;
|
|
21
35
|
declare const oauthSchema: z.ZodObject<{
|
|
22
36
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
23
37
|
accessTokenLifetimeMinutes: z.ZodDefault<z.ZodInt>;
|
|
24
38
|
refreshTokenLifetimeDays: z.ZodDefault<z.ZodInt>;
|
|
25
39
|
authorizationCodeLifetimeMinutes: z.ZodDefault<z.ZodInt>;
|
|
40
|
+
maxBodyBytes: z.ZodDefault<z.ZodInt>;
|
|
41
|
+
metadata: z.ZodPrefault<z.ZodObject<{
|
|
42
|
+
authorizationServer: z.ZodOptional<z.ZodUnion<readonly [z.ZodCustom<(origins: McpOrigins) => Readonly<Record<string, unknown>>, (origins: McpOrigins) => Readonly<Record<string, unknown>>>, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
|
|
43
|
+
protectedResource: z.ZodOptional<z.ZodUnion<readonly [z.ZodCustom<(origins: McpOrigins) => Readonly<Record<string, unknown>>, (origins: McpOrigins) => Readonly<Record<string, unknown>>>, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
|
|
44
|
+
}, z.core.$strict>>;
|
|
26
45
|
}, z.core.$strict>;
|
|
27
46
|
export declare const mcpAccessOptionsSchema: z.ZodObject<{
|
|
28
47
|
serverName: z.ZodString;
|
|
@@ -42,11 +61,18 @@ export declare const mcpAccessOptionsSchema: z.ZodObject<{
|
|
|
42
61
|
maxTokensPerUser: z.ZodDefault<z.ZodInt>;
|
|
43
62
|
expiryWarningDays: z.ZodDefault<z.ZodInt>;
|
|
44
63
|
legacyTokenPattern: z.ZodOptional<z.ZodInstanceOf<RegExp>>;
|
|
64
|
+
resolveAppOrigin: z.ZodOptional<z.ZodCustom<McpAppOriginResolver, McpAppOriginResolver>>;
|
|
65
|
+
resourceOrigins: z.ZodDefault<z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>>;
|
|
45
66
|
oauth: z.ZodPrefault<z.ZodObject<{
|
|
46
67
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
47
68
|
accessTokenLifetimeMinutes: z.ZodDefault<z.ZodInt>;
|
|
48
69
|
refreshTokenLifetimeDays: z.ZodDefault<z.ZodInt>;
|
|
49
70
|
authorizationCodeLifetimeMinutes: z.ZodDefault<z.ZodInt>;
|
|
71
|
+
maxBodyBytes: z.ZodDefault<z.ZodInt>;
|
|
72
|
+
metadata: z.ZodPrefault<z.ZodObject<{
|
|
73
|
+
authorizationServer: z.ZodOptional<z.ZodUnion<readonly [z.ZodCustom<(origins: McpOrigins) => Readonly<Record<string, unknown>>, (origins: McpOrigins) => Readonly<Record<string, unknown>>>, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
|
|
74
|
+
protectedResource: z.ZodOptional<z.ZodUnion<readonly [z.ZodCustom<(origins: McpOrigins) => Readonly<Record<string, unknown>>, (origins: McpOrigins) => Readonly<Record<string, unknown>>>, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
|
|
75
|
+
}, z.core.$strict>>;
|
|
50
76
|
}, z.core.$strict>>;
|
|
51
77
|
}, z.core.$strict>;
|
|
52
78
|
export type McpAccessOptionsInput = z.input<typeof mcpAccessOptionsSchema>;
|
package/dist/options.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEjE,oGAAoG;AACpG,eAAO,MAAM,mBAAmB,QAA2C,CAAC;AAE5E,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,QAA4B,CAAC;AAE3D,qEAAqE;AACrE,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAExC,sGAAsG;AACtG,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAK9C,QAAA,MAAM,UAAU;;;;;;;;;;kBAUd,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,mCAAmC,8TAYtC,CAAC;AAEX,8GAA8G;AAC9G,eAAO,MAAM,iCAAiC,gGAAiG,CAAC;AAEhJ,iGAAiG;AACjG,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,UAAU,KAAK,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AAEpI,8DAA8D;AAC9D,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,MAAM,GAAG,IAAI,CAAC;AAahF,8FAA8F;AAC9F,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAKnD;AAOD,QAAA,MAAM,WAAW;;;;;;;sFAtBM,UAAU,KAAK,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,YAAhD,UAAU,KAAK,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;oFAAhD,UAAU,KAAK,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,YAAhD,UAAU,KAAK,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;kBAkDrE,CAAC;AAQH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;0FA1DZ,UAAU,KAAK,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,YAAhD,UAAU,KAAK,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;wFAAhD,UAAU,KAAK,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,YAAhD,UAAU,KAAK,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;kBAoGnE,CAAC;AAEL,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAC3E,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,sBAAsB,CAAC,CAAC;AACvE,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAChE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAC5D,MAAM,MAAM,aAAa,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;AACxD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC"}
|
package/dist/options.js
CHANGED
|
@@ -22,6 +22,49 @@ const toolSchema = z.strictObject({
|
|
|
22
22
|
/** What the tool does, for the owner deciding which token to issue. */
|
|
23
23
|
description: localizedTextSchema.refine((text) => text.en !== undefined, "needs at least an en text"),
|
|
24
24
|
});
|
|
25
|
+
/**
|
|
26
|
+
* Keys of the authorization server metadata the package generates. An extension cannot set them:
|
|
27
|
+
* they decide where a client sends a person and its secrets.
|
|
28
|
+
*/
|
|
29
|
+
export const GENERATED_AUTHORIZATION_SERVER_KEYS = [
|
|
30
|
+
"issuer",
|
|
31
|
+
"authorization_endpoint",
|
|
32
|
+
"token_endpoint",
|
|
33
|
+
"registration_endpoint",
|
|
34
|
+
"scopes_supported",
|
|
35
|
+
"response_types_supported",
|
|
36
|
+
"response_modes_supported",
|
|
37
|
+
"grant_types_supported",
|
|
38
|
+
"token_endpoint_auth_methods_supported",
|
|
39
|
+
"code_challenge_methods_supported",
|
|
40
|
+
"authorization_response_iss_parameter_supported",
|
|
41
|
+
];
|
|
42
|
+
/** Keys of the protected resource metadata the package generates; `resource_name` is the app's to replace. */
|
|
43
|
+
export const GENERATED_PROTECTED_RESOURCE_KEYS = ["resource", "authorization_servers", "scopes_supported", "bearer_methods_supported"];
|
|
44
|
+
function metadataExtensionSchema(generated) {
|
|
45
|
+
return z.union([
|
|
46
|
+
z.custom((value) => typeof value === "function"),
|
|
47
|
+
z.record(z.string(), z.unknown()).superRefine((record, context) => {
|
|
48
|
+
for (const key of generated) {
|
|
49
|
+
if (Object.hasOwn(record, key))
|
|
50
|
+
context.addIssue({ code: "custom", path: [key], message: `"${key}" is generated by the module and cannot be set` });
|
|
51
|
+
}
|
|
52
|
+
}),
|
|
53
|
+
], { error: "must be an object of extra keys or a function (origins) => object" });
|
|
54
|
+
}
|
|
55
|
+
/** A bare http(s) origin (no path, query, fragment or credentials), reduced to its origin. */
|
|
56
|
+
export function isBareOrigin(value) {
|
|
57
|
+
if (!URL.canParse(value))
|
|
58
|
+
return false;
|
|
59
|
+
const url = new URL(value);
|
|
60
|
+
if (url.protocol !== "http:" && url.protocol !== "https:")
|
|
61
|
+
return false;
|
|
62
|
+
return url.username === "" && url.password === "" && (url.pathname === "/" || url.pathname === "") && !value.includes("?") && !value.includes("#");
|
|
63
|
+
}
|
|
64
|
+
const originSchema = z
|
|
65
|
+
.string()
|
|
66
|
+
.refine((value) => isBareOrigin(value), "must be an http(s) origin such as https://example.com, without a path, query or credentials")
|
|
67
|
+
.transform((value) => new URL(value).origin);
|
|
25
68
|
const oauthSchema = z.strictObject({
|
|
26
69
|
/**
|
|
27
70
|
* Makes the module an OAuth 2.1 authorization server for its endpoint: discovery metadata,
|
|
@@ -34,6 +77,22 @@ const oauthSchema = z.strictObject({
|
|
|
34
77
|
refreshTokenLifetimeDays: z.int().min(1).max(365).default(90),
|
|
35
78
|
/** How long an authorization code works; RFC 6749 §4.1.2 recommends at most ten minutes. */
|
|
36
79
|
authorizationCodeLifetimeMinutes: z.int().min(1).max(10).default(10),
|
|
80
|
+
/**
|
|
81
|
+
* The largest request body the registration, token and consent decision routes read, in bytes;
|
|
82
|
+
* a larger one is answered with 413 before it fills memory. Real bodies stay under 4 KiB.
|
|
83
|
+
*/
|
|
84
|
+
maxBodyBytes: z.int().min(1024).max(1_048_576).default(16_384),
|
|
85
|
+
/**
|
|
86
|
+
* Extra keys of the discovery documents (e.g. `jwks_uri`, `service_documentation`,
|
|
87
|
+
* `resource_documentation`, `agent_auth`). Generated keys win; the protected resource document
|
|
88
|
+
* takes the app's `resource_name`.
|
|
89
|
+
*/
|
|
90
|
+
metadata: z
|
|
91
|
+
.strictObject({
|
|
92
|
+
authorizationServer: metadataExtensionSchema(GENERATED_AUTHORIZATION_SERVER_KEYS).optional(),
|
|
93
|
+
protectedResource: metadataExtensionSchema(GENERATED_PROTECTED_RESOURCE_KEYS).optional(),
|
|
94
|
+
})
|
|
95
|
+
.prefault({}),
|
|
37
96
|
});
|
|
38
97
|
/** A pattern for tokens an app issued before adopting the module: anchored, and stateless. */
|
|
39
98
|
const legacyTokenPatternSchema = z
|
|
@@ -59,6 +118,18 @@ export const mcpAccessOptionsSchema = z
|
|
|
59
118
|
* looked up by its sha256 like a token of the module's own shape; new tokens keep the prefix.
|
|
60
119
|
*/
|
|
61
120
|
legacyTokenPattern: legacyTokenPatternSchema.optional(),
|
|
121
|
+
/**
|
|
122
|
+
* The app origin of a request, when it is not the fixed `appOrigin`: an image built once and
|
|
123
|
+
* served under another origin, or a proxy whose `request.url` does not carry the public host.
|
|
124
|
+
* `readRequestOrigin` (`/server`) reads it from `Host`. Null keeps `appOrigin`.
|
|
125
|
+
*/
|
|
126
|
+
resolveAppOrigin: z.custom((value) => typeof value === "function", "must be a function (request) => string | null").optional(),
|
|
127
|
+
/**
|
|
128
|
+
* Other public hosts of the app, e.g. the apex when the product runs on `app.`: their root
|
|
129
|
+
* protected resource metadata names that host as `resource` (RFC 9728 §3.3), and the
|
|
130
|
+
* authorization and token endpoints accept it as `resource`.
|
|
131
|
+
*/
|
|
132
|
+
resourceOrigins: z.array(originSchema).max(16, "takes at most 16 origins").default([]),
|
|
62
133
|
/** OAuth 2.1 for MCP clients that connect without a pasted token (claude.ai, ChatGPT). */
|
|
63
134
|
oauth: oauthSchema.prefault({}),
|
|
64
135
|
})
|