@softure-ai/mcp-access 0.2.6 → 0.2.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 +45 -0
- package/README.md +141 -10
- package/dist/index.d.ts +16 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/messages/en.d.ts +10 -1
- package/dist/messages/en.d.ts.map +1 -1
- package/dist/messages/en.js +10 -1
- package/dist/messages/en.js.map +1 -1
- package/dist/messages/index.d.ts +10 -1
- package/dist/messages/index.d.ts.map +1 -1
- package/dist/next/oauth-page.d.ts +6 -1
- package/dist/next/oauth-page.d.ts.map +1 -1
- package/dist/next/oauth-page.js +6 -5
- package/dist/next/oauth-page.js.map +1 -1
- package/dist/server/endpoint.d.ts.map +1 -1
- package/dist/server/endpoint.js +6 -4
- package/dist/server/endpoint.js.map +1 -1
- package/dist/server/index.d.ts +5 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +5 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/oauth-http.d.ts +5 -0
- package/dist/server/oauth-http.d.ts.map +1 -1
- package/dist/server/oauth-http.js +11 -7
- package/dist/server/oauth-http.js.map +1 -1
- package/dist/server/server-factory.d.ts +31 -0
- package/dist/server/server-factory.d.ts.map +1 -0
- package/dist/server/server-factory.js +49 -0
- package/dist/server/server-factory.js.map +1 -0
- package/dist/server/server-info.d.ts +34 -0
- package/dist/server/server-info.d.ts.map +1 -0
- package/dist/server/server-info.js +30 -0
- package/dist/server/server-info.js.map +1 -0
- package/dist/server/strict-input.d.ts +17 -0
- package/dist/server/strict-input.d.ts.map +1 -0
- package/dist/server/strict-input.js +157 -0
- package/dist/server/strict-input.js.map +1 -0
- package/dist/server/tool-list.d.ts +35 -0
- package/dist/server/tool-list.d.ts.map +1 -0
- package/dist/server/tool-list.js +68 -0
- package/dist/server/tool-list.js.map +1 -0
- package/dist/server/writes-switch.d.ts +8 -0
- package/dist/server/writes-switch.d.ts.map +1 -0
- package/dist/server/writes-switch.js +25 -0
- package/dist/server/writes-switch.js.map +1 -0
- package/dist/stdio/serve.d.ts.map +1 -1
- package/dist/stdio/serve.js +5 -7
- package/dist/stdio/serve.js.map +1 -1
- package/dist/testing/catalog.d.ts +8 -0
- package/dist/testing/catalog.d.ts.map +1 -1
- package/dist/testing/catalog.js +8 -19
- package/dist/testing/catalog.js.map +1 -1
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +1 -1
- package/dist/testing/index.js.map +1 -1
- package/dist/ui/consent-form.d.ts +2 -2
- package/dist/ui/consent-form.d.ts.map +1 -1
- package/dist/ui/consent-form.js +3 -2
- package/dist/ui/consent-form.js.map +1 -1
- package/module.json +2 -2
- package/package.json +1 -1
- package/src/index.ts +9 -2
- package/src/messages/en.ts +11 -1
- package/src/next/oauth-page.tsx +12 -6
- package/src/server/endpoint.ts +6 -4
- package/src/server/index.ts +23 -0
- package/src/server/oauth-http.ts +16 -7
- package/src/server/server-factory.ts +78 -0
- package/src/server/server-info.ts +76 -0
- package/src/server/strict-input.ts +191 -0
- package/src/server/tool-list.ts +105 -0
- package/src/server/writes-switch.ts +24 -0
- package/src/stdio/serve.ts +5 -7
- package/src/testing/catalog.ts +14 -23
- package/src/testing/index.ts +7 -1
- package/src/ui/consent-form.tsx +12 -8
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,51 @@ 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.2.9
|
|
8
|
+
|
|
9
|
+
- A runtime kill switch for writes (#904): the manifest switch `mcp-access.writes_enabled` (`WRITES_ENABLED_SWITCH`)
|
|
10
|
+
is read through `readSwitch` on every request. Writes need `allowWrites`, the token's write access and the switch;
|
|
11
|
+
off, write tools are not served, the `WWW-Authenticate` challenge and the default OAuth scope name only `mcp:read`,
|
|
12
|
+
the consent page offers no write tick and a decision grants read only. `isWritingEnabled(ctx)` (`/server`) answers
|
|
13
|
+
the app's side, and `AuthorizationRequest.isWriteOffered` the consent page's. Migrate: nothing; an app that does
|
|
14
|
+
not define the switch behaves as before. To use it, define it in `@softure-ai/feature-switches` (README §7
|
|
15
|
+
recommends `failMode: "closed"`, `override: "towards-fail-mode"`) and drop an app-level write switch.
|
|
16
|
+
- The consent page shows where the access code goes as a row of its own (#906): `consent.redirectLabel` and the
|
|
17
|
+
host (or the whole native-scheme URI) in monospace, with the hint `consent.redirectHint` that the app name is
|
|
18
|
+
self-declared and the address is not. `ConsentForm` gains the `target` slot; `note` now styles the hint.
|
|
19
|
+
`OAuthConsentPage` takes `classNames` and `unstyled` and passes them to `ConsentForm` and `ConsentError`.
|
|
20
|
+
Migrate: `consent.returnsTo` is gone; an app that overrides it moves its text to `consent.redirectLabel`, and an
|
|
21
|
+
app that recomposed the page to show the host can mount `OAuthConsentPage` again.
|
|
22
|
+
|
|
23
|
+
## 0.2.8
|
|
24
|
+
|
|
25
|
+
- The content of 0.2.7, which was never published: its release stopped at the gates (ESLint ran out of memory in
|
|
26
|
+
`release.yml`) before publishing, and a tag is never moved.
|
|
27
|
+
|
|
28
|
+
## 0.2.7
|
|
29
|
+
|
|
30
|
+
- A `get_server_info` tool (#885): `serverInfoTool: { buildInfo, changelog?, description? }` on
|
|
31
|
+
`createMcpServerFactory` (`/server`) adds a read-only tool with no input fields for every token that answers the
|
|
32
|
+
build info (pass `readBuildInfo` of `@softure-ai/ops/server`), the optional changelog and the served name and
|
|
33
|
+
version, so an assistant checks which build answers in one call. `registerServerInfoTool(server, { buildInfo,
|
|
34
|
+
server: { name, version } })` registers it on a hand-built server. Its description is
|
|
35
|
+
`mcpAccessMessages.en.serverInfoTool.description`. Migrate: nothing; opt in to use it.
|
|
36
|
+
- Strict tool input (#876): `withStrictToolInput(server, { renamedFields?, coerceTextScalars?, messages? })`
|
|
37
|
+
(`/server`), or `strictToolInput` on `createMcpServerFactory`, rewrites every input schema at registration. Unknown
|
|
38
|
+
fields are refused at every level with the fields the object accepts, a field under its old name is refused as
|
|
39
|
+
`input.field_renamed` with the new name, and boolean and number fields also take their exact text. Texts live in
|
|
40
|
+
`mcpAccessMessages.en.toolInput`. The listed schemas gain `additionalProperties: false`, so the tool-list version of
|
|
41
|
+
a server that opts in changes once. Migrate: an app that wraps `registerTool` itself replaces it with the option.
|
|
42
|
+
- A server version that follows the tool list (#877): `createMcpServerFactory({ name, release?, version?, title?,
|
|
43
|
+
serverOptions?, registerTools(server, identity) })` (`/server`) returns an `McpServerFactory` whose servers answer
|
|
44
|
+
`initialize` with `<release>-tools-<12 hex>`, a fingerprint of every tool as `tools/list` serves it, measured once
|
|
45
|
+
per access level, so MCP clients drop a cached tool list whenever a release changes a tool.
|
|
46
|
+
`measureToolList(registerTools, { release?, name?, serverOptions? })` → `{ toolListVersion, toolCount }` measures a
|
|
47
|
+
list by hand; `measureServedToolLists(createServer)` (`/testing`) reports both levels for a snapshot. Migrate: an
|
|
48
|
+
app that derives the version itself on a recording server replaces it with the factory, or with `measureToolList`
|
|
49
|
+
when its tool list depends on the account.
|
|
50
|
+
- The catalog check treats a server with no tools as an empty list instead of failing to list it.
|
|
51
|
+
|
|
7
52
|
## 0.2.6
|
|
8
53
|
|
|
9
54
|
- A hook around each tool call (#804): `withToolErrors` and `actionTool` take optional `onToolCall`, `caller`
|
package/README.md
CHANGED
|
@@ -15,10 +15,11 @@ limit check made race-free.
|
|
|
15
15
|
`Authorization: Bearer` token, then hands the request to a **fresh server from the app's factory**
|
|
16
16
|
with `{ userId, canWrite, tokenId }`. Unknown, revoked, expired and malformed tokens all get the
|
|
17
17
|
same `401 invalid_token` with a `WWW-Authenticate: Bearer` challenge. The challenge's `scope` is
|
|
18
|
-
`mcp:read mcp:write` while
|
|
18
|
+
`mcp:read mcp:write` while the app allows writes and `mcp:read` otherwise, so an OAuth client asks
|
|
19
19
|
for what it may get.
|
|
20
|
-
- **Writes need
|
|
21
|
-
access.
|
|
20
|
+
- **Writes need the app and the token:** the app's `allowWrites` option, the runtime switch
|
|
21
|
+
`mcp-access.writes_enabled` when the app defines it (§7), and a token issued with write access.
|
|
22
|
+
`canWrite` is decided on every request, so turning `allowWrites` or the switch off makes every token
|
|
22
23
|
read-only at once.
|
|
23
24
|
- A token page for the signed-in user: the app's tool catalog, an issue form, the new token with its
|
|
24
25
|
setup (a prompt for Claude Code and a `claude-cli://` link, the `claude mcp add` command, an
|
|
@@ -30,9 +31,10 @@ limit check made race-free.
|
|
|
30
31
|
- dynamic client registration (RFC 7591, `POST /api/oauth/register`), public or confidential;
|
|
31
32
|
open to anyone, or closed outside a window an ops script opens (`oauth.registration`);
|
|
32
33
|
- `/oauth/authorize`: authorization code with PKCE `S256` only, on a consent page that shows the
|
|
33
|
-
app, where the code goes
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
app's self-declared name, where the code goes (a row of its own, in monospace: the one part a
|
|
35
|
+
client cannot fake), the signed-in account and the access; writes need the `mcp:write` scope, the
|
|
36
|
+
app allowing writes (`allowWrites` and the switch) and the person's tick. A request without `scope`
|
|
37
|
+
gets the default scope: both scopes while the app allows writes, `mcp:read` otherwise;
|
|
36
38
|
- `POST /api/oauth/token`: `authorization_code` and `refresh_token`. Refresh tokens rotate on
|
|
37
39
|
every use; presenting a rotated one again (`previous_refresh_token_hash`) revokes the whole
|
|
38
40
|
grant, and so does reusing a code (RFC 6749 §4.1.2). `resource` (RFC 8707) must name the
|
|
@@ -43,7 +45,10 @@ limit check made race-free.
|
|
|
43
45
|
- Tokens an app issued before adopting the module keep working through `legacyTokenPattern`.
|
|
44
46
|
- Server functions for scripts and other hosts, and a health check for `GET /api/health`.
|
|
45
47
|
- For the app's own server: tool result helpers with a safe error boundary and server actions as write tools
|
|
46
|
-
(`/server`), a
|
|
48
|
+
(`/server`), a server factory whose version follows the tool list, so clients drop a stale cached `tools/list`
|
|
49
|
+
(`createMcpServerFactory`, `measureToolList`, `/server`), strict tool input that refuses unknown and renamed
|
|
50
|
+
fields (`withStrictToolInput`, `/server`), an opt-in `get_server_info` tool that tells which build answers
|
|
51
|
+
(`serverInfoTool`, `/server`), a stdio entry for local assistants (`/stdio`), a catalog parity check (`/testing`), a gate before a
|
|
47
52
|
token is issued (`issueToken`, `/next`) and the `softure-mcp prune` command for a daily cleanup (§4, §5).
|
|
48
53
|
|
|
49
54
|
## 2. Installation
|
|
@@ -147,6 +152,101 @@ Answers to 2025-era clients come as one SSE `message` event, to 2026-07-28 clien
|
|
|
147
152
|
mid-call notifications (progress, logging) are dropped. Keep `/api/mcp` out of a proxy guard that
|
|
148
153
|
redirects to the login page: the endpoint authenticates by token, not by cookie.
|
|
149
154
|
|
|
155
|
+
### A version that follows the tool list
|
|
156
|
+
|
|
157
|
+
MCP clients keep their cached `tools/list` until the server version they read at `initialize` changes, so a
|
|
158
|
+
release that adds a tool or changes a schema under the same `version` leaves the assistant on the old schemas.
|
|
159
|
+
`createMcpServerFactory` builds the factory with a version derived from the tools:
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
// lib/mcp-server.ts
|
|
163
|
+
import { createMcpServerFactory } from "@softure-ai/mcp-access/server";
|
|
164
|
+
|
|
165
|
+
export const createServer = createMcpServerFactory({
|
|
166
|
+
name: "acme",
|
|
167
|
+
release: "2.1.0", // optional, default 1.0.0
|
|
168
|
+
registerTools: (server, { userId, canWrite }) => {
|
|
169
|
+
server.registerTool("list_orders", { description: "Lists your orders." }, () => listOrders(userId));
|
|
170
|
+
if (canWrite) server.registerTool("cancel_order", { ... }, (input) => cancelOrder(userId, input));
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
- The version is `<release>-tools-<12 hex>`, a semver prerelease (comparisons ignore build metadata). The hex is a
|
|
176
|
+
sha256 of every tool as `tools/list` serves it (name, title, description, annotations, input and output JSON
|
|
177
|
+
Schema), in name order with keys sorted: the same registrations always give the same version, any change of a
|
|
178
|
+
name, description or schema changes it, a different registration order does not.
|
|
179
|
+
- It is measured once per access level, on a recording server with the same name and `serverOptions`, so a
|
|
180
|
+
read-only token gets the version of its smaller list. The list may depend on `canWrite` only; for one that depends
|
|
181
|
+
on the account, call `measureToolList(registerTools, { release, name })` → `{ toolListVersion, toolCount }` per
|
|
182
|
+
server instead. `version` passes a fixed value instead of the measured one.
|
|
183
|
+
- In the app's tests, `measureServedToolLists(createServer)` (`/testing`) gives `{ read, write }` with the version
|
|
184
|
+
and count of each level, for an inline snapshot next to the catalog check: a schema change that forgets to update
|
|
185
|
+
the snapshot fails the test.
|
|
186
|
+
|
|
187
|
+
### Strict tool input
|
|
188
|
+
|
|
189
|
+
zod objects strip unknown keys, so a call with a misspelt field (`notes` for `note`) or a field of a newer tool list
|
|
190
|
+
answers as a write that worked while the value was dropped. `withStrictToolInput(server, options?)` rewrites every
|
|
191
|
+
input schema registered on the server from then on, or pass `strictToolInput: true | options` to
|
|
192
|
+
`createMcpServerFactory` (the version is then measured on the strict listing):
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
const server = withStrictToolInput(new McpServer({ name: "acme", version }), {
|
|
196
|
+
renamedFields: { notes: "note" }, // old name → new name
|
|
197
|
+
coerceTextScalars: true, // default
|
|
198
|
+
messages: getMcpAccessMessages(config).toolInput, // default: the English dictionary
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
- **Unknown fields** are refused at every level: nested objects, arrays, records, tuples, optionals, defaults,
|
|
203
|
+
unions, discriminated unions, intersections (a field either side knows is accepted), `z.lazy`, and the input side
|
|
204
|
+
of a transform. The answer names the field and the fields its object accepts, e.g.
|
|
205
|
+
`items.1: Unknown fields: "size". Accepted fields: "title".` An object with its own catchall (`z.looseObject`,
|
|
206
|
+
`.catchall(x)`) keeps it; refinements and the object's own error messages stay.
|
|
207
|
+
- **Renamed fields:** a field sent under an old name where the object accepts the new one is refused with the
|
|
208
|
+
stable code `input.field_renamed` and the new name, so a session on an older tool list learns it in one call.
|
|
209
|
+
- **Text scalars:** a client on an older tool list sends a field it does not know as text, so a boolean field also
|
|
210
|
+
takes the exact text `"true"`/`"false"` and a number field a JSON number written as text, converted before the
|
|
211
|
+
field's own rules (`"-1"` still fails `min(0)`). Any other text is refused. The listed JSON Schema keeps `boolean`
|
|
212
|
+
and `number` and gains `additionalProperties: false`.
|
|
213
|
+
- The SDK validates before the handler runs, so a refused call saves nothing. A raw shape is wrapped in
|
|
214
|
+
`z.object` first; a schema that is not zod passes unchanged. `toStrictToolInput(schema, options?)` gives the
|
|
215
|
+
strict schema on its own.
|
|
216
|
+
|
|
217
|
+
### Which build answers: `get_server_info`
|
|
218
|
+
|
|
219
|
+
An assistant checks a "done" against production in one call. `serverInfoTool` on `createMcpServerFactory` adds a
|
|
220
|
+
read-only `get_server_info` tool for every token, with no input fields, that answers the build info of
|
|
221
|
+
`@softure-ai/ops` (the same public facts as its build info route) and the name and version the server answered at
|
|
222
|
+
`initialize`, which follows the tool list:
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
import { readBuildInfo } from "@softure-ai/ops/server";
|
|
226
|
+
|
|
227
|
+
export const createServer = createMcpServerFactory({
|
|
228
|
+
name: "acme",
|
|
229
|
+
registerTools: (server, identity) => registerNoteTools(server, identity),
|
|
230
|
+
serverInfoTool: {
|
|
231
|
+
buildInfo: () => readBuildInfo(), // the route's options, when it has any
|
|
232
|
+
changelog: () => changelog, // optional: the provider the build info route gets
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
```json
|
|
238
|
+
{ "server": { "name": "acme", "version": "1.0.0-tools-3f9a0c41d2e7" }, "release": "v1.4.0", "commit": "abc1234",
|
|
239
|
+
"builtAt": "2026-10-29T10:00:00.000Z", "startedAt": "2026-10-29T10:05:00.000Z", "changelog": [] }
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
- The app passes the reader, so `/server` never loads `@softure-ai/ops`; `McpBuildInfo` is its `BuildInfo` by shape.
|
|
243
|
+
- `changelog` appears only with a provider; a provider that fails answers `changelog: null` and logs the error
|
|
244
|
+
class, as the route does. A failing `buildInfo` answers a tool error.
|
|
245
|
+
- The tool is part of the measured list, so turning it on changes the version once. The description comes from
|
|
246
|
+
`serverInfoTool.description` of the dictionary, or `description` in the options.
|
|
247
|
+
- A hand-built server registers it with `registerServerInfoTool(server, { buildInfo, server: { name, version } })`,
|
|
248
|
+
passing the name and version it serves.
|
|
249
|
+
|
|
150
250
|
### Writing tools
|
|
151
251
|
|
|
152
252
|
`/server` answers tools safely, so a failure never hands the assistant a query or an error's text:
|
|
@@ -497,12 +597,41 @@ None of its own. The endpoint URL comes from `appOrigin` in `softure.config.ts`.
|
|
|
497
597
|
|
|
498
598
|
## 7. Switches
|
|
499
599
|
|
|
500
|
-
|
|
600
|
+
`mcp-access.writes_enabled` (`WRITES_ENABLED_SWITCH`): a kill switch for writes, read through `readSwitch` of
|
|
601
|
+
`@softure-ai/core` on every MCP request, consent page and decision. `allowWrites` stays the configuration (no
|
|
602
|
+
writes at all without it); the switch takes writes away at once, without a deploy, when a token or a connected
|
|
603
|
+
assistant is suspected of misuse. Off, write tools are not served (the factory gets `canWrite: false`), the
|
|
604
|
+
challenge and the default OAuth scope name only `mcp:read`, and the consent page offers no write tick. Stored
|
|
605
|
+
tokens and grants keep their write access, so turning the switch back on restores it without new consent.
|
|
606
|
+
|
|
607
|
+
The app defines it in `@softure-ai/feature-switches`. Recommended: on by default, `failMode: "closed"` and
|
|
608
|
+
`override: "towards-fail-mode"`, so the environment variable `SOFTURE_SWITCH_MCP_ACCESS_WRITES_ENABLED=false`
|
|
609
|
+
can pull writes off but never push them back on:
|
|
610
|
+
|
|
611
|
+
```ts
|
|
612
|
+
featureSwitches({
|
|
613
|
+
switches: [
|
|
614
|
+
{
|
|
615
|
+
name: "mcp-access.writes_enabled",
|
|
616
|
+
label: { en: "Assistant writes" },
|
|
617
|
+
description: { en: "Lets AI assistants with write access change data. Off, every assistant reads only." },
|
|
618
|
+
default: true,
|
|
619
|
+
failMode: "closed",
|
|
620
|
+
override: "towards-fail-mode",
|
|
621
|
+
},
|
|
622
|
+
],
|
|
623
|
+
});
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
An app that does not define it (or has no feature-switches) keeps `allowWrites` alone. A switch read that throws
|
|
627
|
+
counts as off and is logged by the switch's name. The stdio entry reads the switch once, when it starts.
|
|
501
628
|
|
|
502
629
|
## 8. Appearance
|
|
503
630
|
|
|
504
631
|
`TokenManager` slots: `root`, `section`, `heading`, `text`, `list`, `item`, `itemHeader`, `badge`,
|
|
505
|
-
`details`, `snippet`, `code`; `unstyled` renders structure only.
|
|
632
|
+
`details`, `snippet`, `code`; `unstyled` renders structure only. `ConsentForm` and `ConsentError` slots: `root`,
|
|
633
|
+
`details`, `term`, `value`, `target` (where the code goes), `note` (the hint under it), `actions`, `text`, `link`;
|
|
634
|
+
`OAuthConsentPage` takes `classNames` and `unstyled` and passes them to both. Styling comes from
|
|
506
635
|
`@softure-ai/ui` classes on the `--sft-*` tokens; the module ships no CSS of its own.
|
|
507
636
|
|
|
508
637
|
## 9. Copy
|
|
@@ -511,7 +640,9 @@ None. `allowWrites` is configuration, not a runtime switch: changing who may wri
|
|
|
511
640
|
(placeholders `{serverName}` and `{command}`), `list`, `grants` (connected apps), `consent` (the
|
|
512
641
|
consent page and its errors), and `errors` for the codes
|
|
513
642
|
`mcp-access.name_required`, `name_too_long`, `token_limit_reached`, `token_not_found`, `grant_not_found`,
|
|
514
|
-
`auth.unauthenticated`, `core.database_failed` and `core.unexpected
|
|
643
|
+
`auth.unauthenticated`, `core.database_failed` and `core.unexpected`; `toolInput` for strict tool input
|
|
644
|
+
(`unknownFields` with `{fields}` and `{accepted}`, `noFields`, `fieldRenamed` with `{field}` and `{renamed}`).
|
|
645
|
+
Tool descriptions come from
|
|
515
646
|
the `tools` option, per locale.
|
|
516
647
|
|
|
517
648
|
## 10. Hooks
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
export declare const MODULE_ID = "mcp-access";
|
|
2
|
+
/**
|
|
3
|
+
* Name of the runtime switch that turns writes off without a deploy. Defined in
|
|
4
|
+
* `@softure-ai/feature-switches`, writes need it on as well as `allowWrites` and the token's write access;
|
|
5
|
+
* not defined, `allowWrites` alone decides.
|
|
6
|
+
*/
|
|
7
|
+
export declare const WRITES_ENABLED_SWITCH = "mcp-access.writes_enabled";
|
|
2
8
|
/**
|
|
3
9
|
* The rate limit bucket of `POST /api/mcp`, to spread into `security({ buckets })`: requests per
|
|
4
10
|
* client address, counted before the token is verified. Every request counts, so the limit is for
|
|
@@ -104,7 +110,8 @@ export declare const mcpAccess: import("@softure-ai/core").ModuleFactory<{
|
|
|
104
110
|
title: string;
|
|
105
111
|
lead: string;
|
|
106
112
|
app: string;
|
|
107
|
-
|
|
113
|
+
redirectLabel: string;
|
|
114
|
+
redirectHint: string;
|
|
108
115
|
account: string;
|
|
109
116
|
access: string;
|
|
110
117
|
readAccess: string;
|
|
@@ -119,6 +126,14 @@ export declare const mcpAccess: import("@softure-ai/core").ModuleFactory<{
|
|
|
119
126
|
nothingGranted: string;
|
|
120
127
|
backToApp: string;
|
|
121
128
|
};
|
|
129
|
+
toolInput: {
|
|
130
|
+
unknownFields: string;
|
|
131
|
+
noFields: string;
|
|
132
|
+
fieldRenamed: string;
|
|
133
|
+
};
|
|
134
|
+
serverInfoTool: {
|
|
135
|
+
description: string;
|
|
136
|
+
};
|
|
122
137
|
errors: {
|
|
123
138
|
"mcp-access": {
|
|
124
139
|
name_required: string;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,SAAS,eAAe,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,sBAAsB;;;;;;IAEjC;;;;OAIG;;;;;;CAE8D,CAAC;AAEpE;;;GAGG;AACH,eAAO,MAAM,SAAS
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,SAAS,eAAe,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,8BAA8B,CAAC;AAEjE;;;;GAIG;AACH,eAAO,MAAM,sBAAsB;;;;;;IAEjC;;;;OAIG;;;;;;CAE8D,CAAC;AAEpE;;;GAGG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kCA4BpB,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,eAAe,EACf,mBAAmB,EACnB,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,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,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
|
@@ -9,6 +9,12 @@ import { DEFAULT_MCP_ACCESS_ROUTES } from "./routes.js";
|
|
|
9
9
|
import { checkAccessTokensTable } from "./server/health.js";
|
|
10
10
|
import { mcpAccessPrivacyContributor } from "./server/privacy.js";
|
|
11
11
|
export const MODULE_ID = "mcp-access";
|
|
12
|
+
/**
|
|
13
|
+
* Name of the runtime switch that turns writes off without a deploy. Defined in
|
|
14
|
+
* `@softure-ai/feature-switches`, writes need it on as well as `allowWrites` and the token's write access;
|
|
15
|
+
* not defined, `allowWrites` alone decides.
|
|
16
|
+
*/
|
|
17
|
+
export const WRITES_ENABLED_SWITCH = "mcp-access.writes_enabled";
|
|
12
18
|
/**
|
|
13
19
|
* The rate limit bucket of `POST /api/mcp`, to spread into `security({ buckets })`: requests per
|
|
14
20
|
* client address, counted before the token is verified. Every request counts, so the limit is for
|
|
@@ -30,12 +36,12 @@ export const MCP_RATE_LIMIT_BUCKETS = {
|
|
|
30
36
|
export const mcpAccess = defineModule({
|
|
31
37
|
manifest: {
|
|
32
38
|
id: MODULE_ID,
|
|
33
|
-
version: "0.2.
|
|
39
|
+
version: "0.2.9",
|
|
34
40
|
dependsOn: { security: "^0.2.0", auth: "^0.2.0", jobs: "^0.1.1?", ops: "^0.2.0?" },
|
|
35
41
|
dbSchema: "mcp",
|
|
36
42
|
tables: ["access_tokens", "oauth_clients", "oauth_authorization_codes", "oauth_grants", "oauth_registration_window"],
|
|
37
43
|
env: [],
|
|
38
|
-
switches: [],
|
|
44
|
+
switches: [WRITES_ENABLED_SWITCH],
|
|
39
45
|
routes: { ...DEFAULT_MCP_ACCESS_ROUTES },
|
|
40
46
|
mount: [
|
|
41
47
|
{ kind: "page", path: "app/account/mcp/page.tsx", export: "McpAccessPage" },
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,kGAAkG;AAClG,kGAAkG;AAClG,mDAAmD;AACnD,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAEtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAElE,MAAM,CAAC,MAAM,SAAS,GAAG,YAAY,CAAC;AAEtC;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,GAAG,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE;IACjD;;;;OAIG;IACH,WAAW,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE;CACS,CAAC;AAEpE;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,YAAY,CAAC;IACpC,QAAQ,EAAE;QACR,EAAE,EAAE,SAAS;QACb,OAAO,EAAE,OAAO;QAChB,SAAS,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE;QAClF,QAAQ,EAAE,KAAK;QACf,MAAM,EAAE,CAAC,eAAe,EAAE,eAAe,EAAE,2BAA2B,EAAE,cAAc,EAAE,2BAA2B,CAAC;QACpH,GAAG,EAAE,EAAE;QACP,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/messages/en.d.ts
CHANGED
|
@@ -70,7 +70,8 @@ export declare const en: {
|
|
|
70
70
|
title: string;
|
|
71
71
|
lead: string;
|
|
72
72
|
app: string;
|
|
73
|
-
|
|
73
|
+
redirectLabel: string;
|
|
74
|
+
redirectHint: string;
|
|
74
75
|
account: string;
|
|
75
76
|
access: string;
|
|
76
77
|
readAccess: string;
|
|
@@ -85,6 +86,14 @@ export declare const en: {
|
|
|
85
86
|
nothingGranted: string;
|
|
86
87
|
backToApp: string;
|
|
87
88
|
};
|
|
89
|
+
toolInput: {
|
|
90
|
+
unknownFields: string;
|
|
91
|
+
noFields: string;
|
|
92
|
+
fieldRenamed: string;
|
|
93
|
+
};
|
|
94
|
+
serverInfoTool: {
|
|
95
|
+
description: string;
|
|
96
|
+
};
|
|
88
97
|
errors: {
|
|
89
98
|
"mcp-access": {
|
|
90
99
|
name_required: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/messages/en.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,EAAE
|
|
1
|
+
{"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/messages/en.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmHd,CAAC"}
|
package/dist/messages/en.js
CHANGED
|
@@ -70,7 +70,8 @@ export const en = {
|
|
|
70
70
|
title: "{client} wants access to your account",
|
|
71
71
|
lead: "The assistant can answer questions with your data in this app. You can disconnect it at any time on the AI assistant access page.",
|
|
72
72
|
app: "App",
|
|
73
|
-
|
|
73
|
+
redirectLabel: "Access code goes to",
|
|
74
|
+
redirectHint: "The app chose its own name; this address is the one part it cannot fake. Allow only if you recognise it.",
|
|
74
75
|
account: "Account",
|
|
75
76
|
access: "Access",
|
|
76
77
|
readAccess: "Read your data",
|
|
@@ -85,6 +86,14 @@ export const en = {
|
|
|
85
86
|
nothingGranted: "No access was granted.",
|
|
86
87
|
backToApp: "Back to the app ({target})",
|
|
87
88
|
},
|
|
89
|
+
toolInput: {
|
|
90
|
+
unknownFields: "Unknown fields: {fields}. Accepted fields: {accepted}.",
|
|
91
|
+
noFields: "none",
|
|
92
|
+
fieldRenamed: "input.field_renamed: the field \"{field}\" is now \"{renamed}\". Send it as \"{renamed}\".",
|
|
93
|
+
},
|
|
94
|
+
serverInfoTool: {
|
|
95
|
+
description: "Tells which build of this server answers: its name and version (the version changes whenever a tool changes), the release, the commit, when it was built and started, and the changelog when the app publishes one. Use it to check that a change is live.",
|
|
96
|
+
},
|
|
88
97
|
errors: {
|
|
89
98
|
"mcp-access": {
|
|
90
99
|
name_required: "Give the token a name, so you can tell it from the others.",
|
package/dist/messages/en.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"en.js","sourceRoot":"","sources":["../../src/messages/en.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,EAAE,GAAG;IAChB,IAAI,EAAE;QACJ,KAAK,EAAE,qBAAqB;QAC5B,IAAI,EAAE,uIAAuI;KAC9I;IACD,KAAK,EAAE;QACL,KAAK,EAAE,0BAA0B;QACjC,KAAK,EAAE,6BAA6B;QACpC,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,cAAc;QACrB,gBAAgB,EAAE,uCAAuC;KAC1D;IACD,KAAK,EAAE;QACL,KAAK,EAAE,WAAW;QAClB,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,uDAAuD;QACjE,QAAQ,EAAE,eAAe;QACzB,YAAY,EAAE,0CAA0C;QACxD,MAAM,EAAE,cAAc;QACtB,OAAO,EAAE,WAAW;QACpB,KAAK,EAAE,yCAAyC;KACjD;IACD,MAAM,EAAE;QACN,KAAK,EAAE,uBAAuB;QAC9B,IAAI,EAAE,uFAAuF;QAC7F,OAAO,EAAE,qBAAqB;QAC9B,QAAQ,EAAE,2BAA2B;QACrC,SAAS,EAAE,sCAAsC;QACjD,WAAW,EAAE,oCAAoC;QACjD,UAAU,EAAE,iGAAiG;QAC7G,cAAc,EAAE,qBAAqB;QACrC,YAAY,EAAE,gCAAgC;QAC9C,SAAS,EAAE,gDAAgD;QAC3D,YAAY,EAAE,6CAA6C;QAC3D,WAAW,EAAE,wDAAwD;QACrE,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,QAAQ;QAChB,IAAI,EAAE,sBAAsB;KAC7B;IACD,KAAK,EAAE;QACL,eAAe,EAAE,6IAA6I;KAC/J;IACD,IAAI,EAAE;QACJ,KAAK,EAAE,aAAa;QACpB,KAAK,EAAE,yBAAyB;QAChC,QAAQ,EAAE,WAAW;QACrB,SAAS,EAAE,iBAAiB;QAC5B,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,SAAS;QAClB,YAAY,EAAE,eAAe;QAC7B,eAAe,EAAE,kBAAkB;QACnC,aAAa,EAAE,wBAAwB;QACvC,SAAS,EAAE,oBAAoB;QAC/B,SAAS,EAAE,mBAAmB;QAC9B,SAAS,EAAE,gBAAgB;QAC3B,QAAQ,EAAE,kBAAkB;QAC5B,SAAS,EAAE,cAAc;QACzB,MAAM,EAAE,QAAQ;QAChB,QAAQ,EAAE,WAAW;KACtB;IACD,MAAM,EAAE;QACN,KAAK,EAAE,gBAAgB;QACvB,IAAI,EAAE,mHAAmH;QACzH,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EAAE,kBAAkB;QAC/B,UAAU,EAAE,YAAY;QACxB,aAAa,EAAE,gBAAgB;KAChC;IACD,OAAO,EAAE;QACP,KAAK,EAAE,uCAAuC;QAC9C,IAAI,EAAE,mIAAmI;QACzI,GAAG,EAAE,KAAK;QACV,
|
|
1
|
+
{"version":3,"file":"en.js","sourceRoot":"","sources":["../../src/messages/en.ts"],"names":[],"mappings":"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"}
|
package/dist/messages/index.d.ts
CHANGED
|
@@ -74,7 +74,8 @@ export declare const mcpAccessMessages: {
|
|
|
74
74
|
title: string;
|
|
75
75
|
lead: string;
|
|
76
76
|
app: string;
|
|
77
|
-
|
|
77
|
+
redirectLabel: string;
|
|
78
|
+
redirectHint: string;
|
|
78
79
|
account: string;
|
|
79
80
|
access: string;
|
|
80
81
|
readAccess: string;
|
|
@@ -89,6 +90,14 @@ export declare const mcpAccessMessages: {
|
|
|
89
90
|
nothingGranted: string;
|
|
90
91
|
backToApp: string;
|
|
91
92
|
};
|
|
93
|
+
toolInput: {
|
|
94
|
+
unknownFields: string;
|
|
95
|
+
noFields: string;
|
|
96
|
+
fieldRenamed: string;
|
|
97
|
+
};
|
|
98
|
+
serverInfoTool: {
|
|
99
|
+
description: string;
|
|
100
|
+
};
|
|
92
101
|
errors: {
|
|
93
102
|
"mcp-access": {
|
|
94
103
|
name_required: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/messages/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAE7B,0GAA0G;AAC1G,eAAO,MAAM,iBAAiB
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/messages/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAE7B,0GAA0G;AAC1G,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAS,CAAC;AAExC,MAAM,MAAM,iBAAiB,GAAG,OAAO,EAAE,CAAC;AAE1C,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAOlG"}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import { type ClassNames } from "@softure-ai/ui";
|
|
2
|
+
import { type ConsentFormSlot } from "../ui/consent-form.js";
|
|
1
3
|
type SearchParams = Promise<Record<string, string | string[] | undefined>>;
|
|
2
4
|
export interface OAuthConsentPageProps {
|
|
3
5
|
readonly searchParams?: SearchParams;
|
|
6
|
+
/** Restyles the form or the error, passed to `ConsentForm` and `ConsentError`. */
|
|
7
|
+
readonly classNames?: ClassNames<ConsentFormSlot>;
|
|
8
|
+
readonly unstyled?: boolean;
|
|
4
9
|
}
|
|
5
|
-
export declare function OAuthConsentPage({ searchParams }: OAuthConsentPageProps): Promise<import("react").JSX.Element>;
|
|
10
|
+
export declare function OAuthConsentPage({ searchParams, classNames, unstyled }: OAuthConsentPageProps): Promise<import("react").JSX.Element>;
|
|
6
11
|
export {};
|
|
7
12
|
//# sourceMappingURL=oauth-page.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-page.d.ts","sourceRoot":"","sources":["../../src/next/oauth-page.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"oauth-page.d.ts","sourceRoot":"","sources":["../../src/next/oauth-page.tsx"],"names":[],"mappings":"AASA,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAKvD,OAAO,EAA6B,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxF,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;IACrC,kFAAkF;IAClF,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,eAAe,CAAC,CAAC;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAID,wBAAsB,gBAAgB,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,qBAAqB,wCA6CnG"}
|
package/dist/next/oauth-page.js
CHANGED
|
@@ -12,11 +12,12 @@ import { Card } from "@softure-ai/ui";
|
|
|
12
12
|
import { notFound } from "next/navigation";
|
|
13
13
|
import { getConsentPath, isOAuthEnabled, readAuthorizationParams, validateAuthorizationRequest } from "../server/oauth-http.js";
|
|
14
14
|
import { describeRedirectUri } from "../server/oauth-validation.js";
|
|
15
|
-
import { getMcpAccessMessages,
|
|
15
|
+
import { getMcpAccessMessages, getMcpAccessRoutes } from "../server/options.js";
|
|
16
16
|
import { ConsentError, ConsentForm } from "../ui/consent-form.js";
|
|
17
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
|
-
export async function OAuthConsentPage({ searchParams }) {
|
|
19
|
+
export async function OAuthConsentPage({ searchParams, classNames, unstyled }) {
|
|
20
|
+
const styling = { ...(classNames === undefined ? {} : { classNames }), ...(unstyled === undefined ? {} : { unstyled }) };
|
|
20
21
|
const config = getSoftureConfig();
|
|
21
22
|
if (!isOAuthEnabled(config))
|
|
22
23
|
notFound();
|
|
@@ -28,9 +29,9 @@ export async function OAuthConsentPage({ searchParams }) {
|
|
|
28
29
|
const outcome = await validateAuthorizationRequest(await getMcpAccessContext(config), params, origins);
|
|
29
30
|
if (outcome.kind !== "valid") {
|
|
30
31
|
const message = outcome.kind === "redirect-error" ? messages.consent.invalidRequest : outcome.reason === "unknown_client" ? messages.consent.unknownClient : messages.consent.redirectMismatch;
|
|
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 }) }) }));
|
|
32
|
+
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, ...styling }) }) }));
|
|
32
33
|
}
|
|
33
|
-
const { client, redirectUri,
|
|
34
|
-
return (_jsx("main", { className: LAYOUT_CLASS, children: _jsx(Card, { title: formatMessage(messages.consent.title, { client: client.clientName }), subtitle: messages.consent.lead, children: _jsx(ConsentForm, { action: getMcpAccessRoutes(config).oauthDecision, params: [...params.entries()], clientName: client.clientName, redirectTarget: describeRedirectUri(redirectUri), accountEmail: user.email, isWriteOffered:
|
|
34
|
+
const { client, redirectUri, isWriteOffered } = outcome.request;
|
|
35
|
+
return (_jsx("main", { className: LAYOUT_CLASS, children: _jsx(Card, { title: formatMessage(messages.consent.title, { client: client.clientName }), subtitle: messages.consent.lead, children: _jsx(ConsentForm, { action: getMcpAccessRoutes(config).oauthDecision, params: [...params.entries()], clientName: client.clientName, redirectTarget: describeRedirectUri(redirectUri), accountEmail: user.email, isWriteOffered: isWriteOffered, messages: messages, ...styling }) }) }));
|
|
35
36
|
}
|
|
36
37
|
//# sourceMappingURL=oauth-page.js.map
|
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"oauth-page.js","sourceRoot":"","sources":["../../src/next/oauth-page.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"endpoint.d.ts","sourceRoot":"","sources":["../../src/server/endpoint.ts"],"names":[],"mappings":"AAKA,OAAO,EAML,KAAK,SAAS,EACd,KAAK,MAAM,EACZ,MAAM,8BAA8B,CAAC;AAGtC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"endpoint.d.ts","sourceRoot":"","sources":["../../src/server/endpoint.ts"],"names":[],"mappings":"AAKA,OAAO,EAML,KAAK,SAAS,EACd,KAAK,MAAM,EACZ,MAAM,8BAA8B,CAAC;AAGtC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGxD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGvE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,CAAC;AAE3C,8FAA8F;AAC9F,eAAO,MAAM,qBAAqB,QAAQ,CAAC;AAE3C,6FAA6F;AAC7F,eAAO,MAAM,qBAAqB,QAAc,CAAC;AAOjD,mGAAmG;AACnG,MAAM,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,iBAAiB,KAAK,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,CAAC;AAEjH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAC;CACzC;AAED,8CAA8C;AAC9C,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEzF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,YAAY,EAAE,EAAE,kBAAkB,GAAG,WAAW,CAmCnF"}
|
package/dist/server/endpoint.js
CHANGED
|
@@ -7,10 +7,10 @@ import { bearerAuthChallengeResponse, createMcpHandler, OAuthError, OAuthErrorCo
|
|
|
7
7
|
import { errorLogLabel, getModule } from "@softure-ai/core";
|
|
8
8
|
import { consumeRateLimit, identifyClient } from "@softure-ai/security/server";
|
|
9
9
|
import { getProtectedResourceMetadataUrl, isOAuthEnabled } from "./oauth-http.js";
|
|
10
|
-
import { getMcpAccessOptions } from "./options.js";
|
|
11
10
|
import { resolveMcpOrigins } from "./origins.js";
|
|
12
11
|
import { MCP_READ_SCOPE, MCP_WRITE_SCOPE } from "./scopes.js";
|
|
13
12
|
import { verifyAccessToken } from "./tokens.js";
|
|
13
|
+
import { isWritingEnabled } from "./writes-switch.js";
|
|
14
14
|
export { MCP_READ_SCOPE, MCP_WRITE_SCOPE };
|
|
15
15
|
/** The security bucket the endpoint counts in; `MCP_RATE_LIMIT_BUCKETS` holds its default. */
|
|
16
16
|
export const MCP_RATE_LIMIT_BUCKET = "mcp";
|
|
@@ -66,8 +66,10 @@ export function createMcpEndpoint({ createServer }) {
|
|
|
66
66
|
async function authenticate(ctx, request) {
|
|
67
67
|
const header = request.headers.get("authorization");
|
|
68
68
|
// Clients request the challenge's scope first (MCP authorization, scope selection), so it names
|
|
69
|
-
// `mcp:write` while the app allows writes; the person's tick on
|
|
70
|
-
|
|
69
|
+
// `mcp:write` while the app allows writes (`allowWrites` and the writes switch); the person's tick on
|
|
70
|
+
// the consent page still decides. Read once per request: the switch can change between requests.
|
|
71
|
+
const isWriteAllowed = await isWritingEnabled(ctx);
|
|
72
|
+
const requiredScopes = isWriteAllowed ? [MCP_READ_SCOPE, MCP_WRITE_SCOPE] : [MCP_READ_SCOPE];
|
|
71
73
|
const challenge = isOAuthEnabled(ctx.config)
|
|
72
74
|
? { requiredScopes, resourceMetadataUrl: getProtectedResourceMetadataUrl(ctx.config, resolveMcpOrigins(ctx.config, request)) }
|
|
73
75
|
: { requiredScopes };
|
|
@@ -90,7 +92,7 @@ async function authenticate(ctx, request) {
|
|
|
90
92
|
token,
|
|
91
93
|
// The client is the token: it is what gets revoked, and its id may be logged.
|
|
92
94
|
clientId: verified.tokenId,
|
|
93
|
-
scopes: verified.canWrite ? [MCP_READ_SCOPE, MCP_WRITE_SCOPE] : [MCP_READ_SCOPE],
|
|
95
|
+
scopes: verified.canWrite && isWriteAllowed ? [MCP_READ_SCOPE, MCP_WRITE_SCOPE] : [MCP_READ_SCOPE],
|
|
94
96
|
// AuthInfo counts seconds; Date counts milliseconds.
|
|
95
97
|
expiresAt: Math.floor(verified.expiresAt.getTime() / 1000),
|
|
96
98
|
extra: { [USER_ID_CLAIM]: verified.userId },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"endpoint.js","sourceRoot":"","sources":["../../src/server/endpoint.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,oGAAoG;AACpG,gGAAgG;AAChG,kGAAkG;AAClG,4BAA4B;AAC5B,OAAO,EACL,2BAA2B,EAC3B,gBAAgB,EAChB,UAAU,EACV,cAAc,GAIf,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE/E,OAAO,EAAE,+BAA+B,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"endpoint.js","sourceRoot":"","sources":["../../src/server/endpoint.ts"],"names":[],"mappings":"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"}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { createMcpEndpoint, MAX_MCP_REQUEST_BYTES, MCP_RATE_LIMIT_BUCKET, MCP_READ_SCOPE, MCP_WRITE_SCOPE, type McpEndpoint, type McpEndpointOptions, type McpServerFactory, } from "./endpoint.js";
|
|
2
2
|
export { actionTool, toFormData, type ActionToolOptions, type FormActionHandler } from "./action-tool.js";
|
|
3
3
|
export { createMcpAccessContext } from "./context.js";
|
|
4
|
+
export { isWritingEnabled } from "./writes-switch.js";
|
|
4
5
|
export { checkAccessTokensTable } from "./health.js";
|
|
5
6
|
export { closeClientRegistration, findClientRegistrationWindow, isClientRegistrationOpen, MAX_REGISTRATION_WINDOW_MINUTES, openClientRegistration, type ClientRegistrationWindow, type OpenClientRegistrationInput, } from "./registration-window.js";
|
|
6
7
|
export { CONSENT_CODE_PREFIX, CLIENT_SECRET_PREFIX, createAuthorizationCode, exchangeAuthorizationCode, findOAuthClient, isClientSecretValid, listOAuthGrants, pruneOAuthRecords, REFRESH_TOKEN_PREFIX, refreshMcpGrant, registerMcpClient, revokeOAuthGrant, type CreateAuthorizationCodeInput, type ExchangeAuthorizationCodeInput, type IssuedOAuthTokens, type OAuthClientRegistration, type PrunedOAuthRecords, type RefreshOAuthGrantInput, type RegisteredOAuthClient, type RevokeOAuthGrantInput, } from "./oauth.js";
|
|
@@ -14,5 +15,9 @@ export { getMcpAccessMessages, getMcpAccessOptions, getMcpAccessRoutes, getMcpEn
|
|
|
14
15
|
export { pruneMcpAccess, type PrunedMcpAccessRecords } from "./prune.js";
|
|
15
16
|
export { deleteMcpAccessUserData, exportMcpAccessUserData, mcpAccessPrivacyContributor, type McpAccessUserData, } from "./privacy.js";
|
|
16
17
|
export { ACCESS_TOKEN_PREFIX, hashAccessToken, isAccessTokenShape, issueAccessToken, listAccessTokens, pruneAccessTokens, findTokenClientName, revokeAccessToken, verifyAccessToken, type IssueAccessTokenInput, type IssueAccessTokenResult, type IssuedAccessToken, type McpAccessContext, type RevokeAccessTokenInput, type VerifiedAccessToken, } from "./tokens.js";
|
|
18
|
+
export { createMcpServerFactory, type McpServerFactoryOptions } from "./server-factory.js";
|
|
19
|
+
export { registerServerInfoTool, SERVER_INFO_TOOL_NAME, type McpBuildInfo, type RegisterServerInfoToolOptions, type ServedServerInfo, type ServerInfoAnswer, type ServerInfoToolOptions, } from "./server-info.js";
|
|
20
|
+
export { toStrictToolInput, withStrictToolInput, type StrictToolInputMessages, type StrictToolInputOptions } from "./strict-input.js";
|
|
21
|
+
export { DEFAULT_TOOL_LIST_RELEASE, describeToolList, fingerprintToolList, listServedTools, measureToolList, type MeasureToolListOptions, type RegisterTools, type ServedTool, type ToolListMeasurement, } from "./tool-list.js";
|
|
17
22
|
export { toolError, toolResult, withToolErrors, type ToolCaller, type ToolCallHook, type ToolCallOutcome, type ToolCallRecord, type ToolErrorHints, type ToolErrorOptions, } from "./tools.js";
|
|
18
23
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|