@softure-ai/mcp-access 0.2.8 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +71 -0
- package/README.md +270 -19
- package/dist/cli/run.d.ts +1 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +2 -2
- package/dist/cli/run.js.map +1 -1
- package/dist/contract.d.ts +48 -2
- package/dist/contract.d.ts.map +1 -1
- package/dist/index.d.ts +96 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -5
- package/dist/index.js.map +1 -1
- package/dist/jobs/index.d.ts +2 -0
- package/dist/jobs/index.d.ts.map +1 -1
- package/dist/jobs/index.js +5 -2
- package/dist/jobs/index.js.map +1 -1
- package/dist/jobs/operation-state.d.ts +58 -0
- package/dist/jobs/operation-state.d.ts.map +1 -0
- package/dist/jobs/operation-state.js +68 -0
- package/dist/jobs/operation-state.js.map +1 -0
- package/dist/jobs/operation-tasks.d.ts +61 -0
- package/dist/jobs/operation-tasks.d.ts.map +1 -0
- package/dist/jobs/operation-tasks.js +161 -0
- package/dist/jobs/operation-tasks.js.map +1 -0
- package/dist/jobs/operations.d.ts +68 -0
- package/dist/jobs/operations.d.ts.map +1 -0
- package/dist/jobs/operations.js +110 -0
- package/dist/jobs/operations.js.map +1 -0
- package/dist/messages/en.d.ts +57 -1
- package/dist/messages/en.d.ts.map +1 -1
- package/dist/messages/en.js +57 -1
- package/dist/messages/en.js.map +1 -1
- package/dist/messages/index.d.ts +56 -1
- package/dist/messages/index.d.ts.map +1 -1
- package/dist/next/issue-token.d.ts +11 -2
- package/dist/next/issue-token.d.ts.map +1 -1
- package/dist/next/issue-token.js +56 -7
- package/dist/next/issue-token.js.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/next/token-manager-props.d.ts +3 -2
- package/dist/next/token-manager-props.d.ts.map +1 -1
- package/dist/next/token-manager-props.js +12 -2
- package/dist/next/token-manager-props.js.map +1 -1
- package/dist/options.d.ts +47 -0
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +53 -0
- package/dist/options.js.map +1 -1
- package/dist/schema.d.ts +214 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +21 -3
- package/dist/schema.js.map +1 -1
- package/dist/server/api-tokens.d.ts +64 -0
- package/dist/server/api-tokens.d.ts.map +1 -0
- package/dist/server/api-tokens.js +176 -0
- package/dist/server/api-tokens.js.map +1 -0
- package/dist/server/confirmation.d.ts +69 -0
- package/dist/server/confirmation.d.ts.map +1 -0
- package/dist/server/confirmation.js +220 -0
- package/dist/server/confirmation.js.map +1 -0
- 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/health.d.ts.map +1 -1
- package/dist/server/health.js +3 -1
- package/dist/server/health.js.map +1 -1
- package/dist/server/index.d.ts +5 -2
- 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 +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/privacy.d.ts +4 -0
- package/dist/server/privacy.d.ts.map +1 -1
- package/dist/server/privacy.js +5 -1
- package/dist/server/privacy.js.map +1 -1
- package/dist/server/prune.d.ts +5 -1
- package/dist/server/prune.d.ts.map +1 -1
- package/dist/server/prune.js +14 -4
- package/dist/server/prune.js.map +1 -1
- package/dist/server/strict-input.d.ts +3 -1
- package/dist/server/strict-input.d.ts.map +1 -1
- package/dist/server/strict-input.js +54 -8
- package/dist/server/strict-input.js.map +1 -1
- package/dist/server/tokens.d.ts +46 -11
- package/dist/server/tokens.d.ts.map +1 -1
- package/dist/server/tokens.js +46 -24
- package/dist/server/tokens.js.map +1 -1
- package/dist/server/tools.d.ts +8 -0
- package/dist/server/tools.d.ts.map +1 -1
- package/dist/server/tools.js +1 -0
- package/dist/server/tools.js.map +1 -1
- 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/tokens/index.d.ts +6 -0
- package/dist/tokens/index.d.ts.map +1 -0
- package/dist/tokens/index.js +8 -0
- package/dist/tokens/index.js.map +1 -0
- 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/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/token-manager.d.ts +18 -2
- package/dist/ui/token-manager.d.ts.map +1 -1
- package/dist/ui/token-manager.js +28 -3
- package/dist/ui/token-manager.js.map +1 -1
- package/migrations/0004_create_used_confirmations.sql +13 -0
- package/migrations/0005_add_api_tokens.sql +15 -0
- package/migrations/0006_create_operation_tasks.sql +18 -0
- package/module.json +10 -4
- package/package.json +7 -2
- package/src/cli/run.ts +2 -2
- package/src/contract.ts +60 -2
- package/src/index.ts +39 -4
- package/src/jobs/index.ts +41 -2
- package/src/jobs/operation-state.ts +119 -0
- package/src/jobs/operation-tasks.ts +229 -0
- package/src/jobs/operations.ts +213 -0
- package/src/messages/en.ts +58 -1
- package/src/next/issue-token.ts +64 -9
- package/src/next/oauth-page.tsx +12 -6
- package/src/next/token-manager-props.ts +15 -4
- package/src/options.ts +62 -0
- package/src/schema.ts +23 -3
- package/src/server/api-tokens.ts +224 -0
- package/src/server/confirmation.ts +316 -0
- package/src/server/endpoint.ts +6 -4
- package/src/server/health.ts +3 -1
- package/src/server/index.ts +33 -2
- package/src/server/oauth-http.ts +16 -7
- package/src/server/privacy.ts +9 -1
- package/src/server/prune.ts +17 -4
- package/src/server/strict-input.ts +62 -13
- package/src/server/tokens.ts +73 -27
- package/src/server/tools.ts +9 -0
- package/src/server/writes-switch.ts +24 -0
- package/src/stdio/serve.ts +5 -7
- package/src/tokens/index.ts +22 -0
- package/src/ui/consent-form.tsx +12 -8
- package/src/ui/index.ts +1 -0
- package/src/ui/token-manager.tsx +140 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"privacy.d.ts","sourceRoot":"","sources":["../../src/server/privacy.ts"],"names":[],"mappings":"AAGA,OAAO,EAAM,KAAK,aAAa,EAAE,KAAK,EAAE,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAK5F,2EAA2E;AAC3E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,YAAY,EAAE,SAAS;QAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC3B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;QACzB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;QACzB,QAAQ,CAAC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;KAClC,EAAE,CAAC;IACJ,+FAA+F;IAC/F,QAAQ,CAAC,aAAa,EAAE,SAAS;QAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC3B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;QACzB,QAAQ,CAAC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;KAClC,EAAE,CAAC;CACL;AAID,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"privacy.d.ts","sourceRoot":"","sources":["../../src/server/privacy.ts"],"names":[],"mappings":"AAGA,OAAO,EAAM,KAAK,aAAa,EAAE,KAAK,EAAE,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAK5F,2EAA2E;AAC3E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,YAAY,EAAE,SAAS;QAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,+DAA+D;QAC/D,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;QAC7B,8DAA8D;QAC9D,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;QACnC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC3B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;QACzB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;QACzB,QAAQ,CAAC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;KAClC,EAAE,CAAC;IACJ,+FAA+F;IAC/F,QAAQ,CAAC,aAAa,EAAE,SAAS;QAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC3B,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;QACzB,QAAQ,CAAC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;KAClC,EAAE,CAAC;CACL;AAID,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAwBpH;AAED,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAU5G;AAED,eAAO,MAAM,2BAA2B,EAAE,kBAGzC,CAAC"}
|
package/dist/server/privacy.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// by name before auth deletes the account, so it does not rest on the foreign keys' cascade alone.
|
|
4
4
|
import { ok } from "@softure-ai/core";
|
|
5
5
|
import { and, asc, eq, isNull } from "drizzle-orm";
|
|
6
|
-
import { accessTokens, oauthAuthorizationCodes, oauthClients, oauthGrants } from "../schema.js";
|
|
6
|
+
import { accessTokens, oauthAuthorizationCodes, oauthClients, oauthGrants, operationTasks } from "../schema.js";
|
|
7
7
|
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8
8
|
export async function exportMcpAccessUserData(context, userId) {
|
|
9
9
|
if (!UUID.test(userId))
|
|
@@ -13,6 +13,8 @@ export async function exportMcpAccessUserData(context, userId) {
|
|
|
13
13
|
const tokens = await db
|
|
14
14
|
.select({
|
|
15
15
|
name: accessTokens.name,
|
|
16
|
+
kind: accessTokens.kind,
|
|
17
|
+
scopes: accessTokens.scopes,
|
|
16
18
|
canWrite: accessTokens.canWrite,
|
|
17
19
|
createdAt: accessTokens.createdAt,
|
|
18
20
|
expiresAt: accessTokens.expiresAt,
|
|
@@ -37,6 +39,8 @@ export async function deleteMcpAccessUserData(context, userId) {
|
|
|
37
39
|
// A grant's access tokens go with it by cascade; the next line takes the hand-issued ones.
|
|
38
40
|
await db.delete(oauthGrants).where(eq(oauthGrants.userId, userId));
|
|
39
41
|
await db.delete(accessTokens).where(eq(accessTokens.userId, userId));
|
|
42
|
+
// MCP tasks hold a job id and dates only, so the export leaves them out; they go with the account.
|
|
43
|
+
await db.delete(operationTasks).where(eq(operationTasks.userId, userId));
|
|
40
44
|
return ok();
|
|
41
45
|
}
|
|
42
46
|
export const mcpAccessPrivacyContributor = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"privacy.js","sourceRoot":"","sources":["../../src/server/privacy.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,mGAAmG;AACnG,mGAAmG;AACnG,OAAO,EAAE,EAAE,EAAwD,MAAM,kBAAkB,CAAC;AAE5F,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"privacy.js","sourceRoot":"","sources":["../../src/server/privacy.ts"],"names":[],"mappings":"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"}
|
package/dist/server/prune.d.ts
CHANGED
|
@@ -2,7 +2,11 @@ import { type PrunedOAuthRecords } from "./oauth.js";
|
|
|
2
2
|
import { type McpAccessContext } from "./tokens.js";
|
|
3
3
|
export interface PrunedMcpAccessRecords extends PrunedOAuthRecords {
|
|
4
4
|
readonly accessTokens: number;
|
|
5
|
+
readonly usedConfirmations: number;
|
|
6
|
+
readonly operationTasks: number;
|
|
5
7
|
}
|
|
6
|
-
/** Runs `pruneAccessTokens`, then `
|
|
8
|
+
/** Runs `pruneAccessTokens`, `pruneOAuthRecords`, `pruneUsedConfirmations`, then `pruneOperationTasks`, and counts what each removed. */
|
|
7
9
|
export declare function pruneMcpAccess(ctx: McpAccessContext): Promise<PrunedMcpAccessRecords>;
|
|
10
|
+
/** Deletes the MCP tasks past their expiry (#977); the operations' jobs stay with `@softure-ai/jobs`. */
|
|
11
|
+
export declare function pruneOperationTasks(ctx: McpAccessContext): Promise<number>;
|
|
8
12
|
//# sourceMappingURL=prune.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prune.d.ts","sourceRoot":"","sources":["../../src/server/prune.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prune.d.ts","sourceRoot":"","sources":["../../src/server/prune.ts"],"names":[],"mappings":"AAKA,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEvE,MAAM,WAAW,sBAAuB,SAAQ,kBAAkB;IAChE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,yIAAyI;AACzI,wBAAsB,cAAc,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAK3F;AAED,yGAAyG;AACzG,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhF"}
|
package/dist/server/prune.js
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
// The module's scheduled cleanup: expired access tokens
|
|
2
|
-
// one call for a daily job (`softure-mcp prune`, a deploy `maintain` hook) instead of inline on requests.
|
|
1
|
+
// The module's scheduled cleanup: expired access tokens, dead OAuth records of every account, used
|
|
2
|
+
// confirmation tokens and MCP tasks past their expiry, in one call for a daily job (`softure-mcp prune`, a deploy `maintain` hook) instead of inline on requests.
|
|
3
|
+
import { lte } from "drizzle-orm";
|
|
4
|
+
import { operationTasks } from "../schema.js";
|
|
5
|
+
import { pruneUsedConfirmations } from "./confirmation.js";
|
|
3
6
|
import { pruneOAuthRecords } from "./oauth.js";
|
|
4
7
|
import { pruneAccessTokens } from "./tokens.js";
|
|
5
|
-
/** Runs `pruneAccessTokens`, then `
|
|
8
|
+
/** Runs `pruneAccessTokens`, `pruneOAuthRecords`, `pruneUsedConfirmations`, then `pruneOperationTasks`, and counts what each removed. */
|
|
6
9
|
export async function pruneMcpAccess(ctx) {
|
|
7
10
|
const accessTokens = await pruneAccessTokens(ctx);
|
|
8
|
-
|
|
11
|
+
const oauth = await pruneOAuthRecords(ctx);
|
|
12
|
+
const usedConfirmations = await pruneUsedConfirmations(ctx);
|
|
13
|
+
return { accessTokens, ...oauth, usedConfirmations, operationTasks: await pruneOperationTasks(ctx) };
|
|
14
|
+
}
|
|
15
|
+
/** Deletes the MCP tasks past their expiry (#977); the operations' jobs stay with `@softure-ai/jobs`. */
|
|
16
|
+
export async function pruneOperationTasks(ctx) {
|
|
17
|
+
const removed = await ctx.db.delete(operationTasks).where(lte(operationTasks.expiresAt, ctx.clock.now())).returning({ taskId: operationTasks.taskId });
|
|
18
|
+
return removed.length;
|
|
9
19
|
}
|
|
10
20
|
//# sourceMappingURL=prune.js.map
|
package/dist/server/prune.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prune.js","sourceRoot":"","sources":["../../src/server/prune.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"prune.js","sourceRoot":"","sources":["../../src/server/prune.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,kKAAkK;AAClK,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAA2B,MAAM,YAAY,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAyB,MAAM,aAAa,CAAC;AAQvE,yIAAyI;AACzI,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAqB;IACxD,MAAM,YAAY,GAAG,MAAM,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,iBAAiB,GAAG,MAAM,sBAAsB,CAAC,GAAG,CAAC,CAAC;IAC5D,OAAO,EAAE,YAAY,EAAE,GAAG,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC;AACvG,CAAC;AAED,yGAAyG;AACzG,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,GAAqB;IAC7D,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC;IACvJ,OAAO,OAAO,CAAC,MAAM,CAAC;AACxB,CAAC"}
|
|
@@ -2,9 +2,11 @@ import type { McpServer } from "@modelcontextprotocol/server";
|
|
|
2
2
|
import { en } from "../messages/en.js";
|
|
3
3
|
/** The texts of a refused field: `toolInput` of the module dictionary (`getMcpAccessMessages(config).toolInput`). */
|
|
4
4
|
export type StrictToolInputMessages = typeof en.toolInput;
|
|
5
|
+
/** Old field name → new field name, as a map or a rule (`undefined`: not renamed). */
|
|
6
|
+
export type RenamedFields = Readonly<Record<string, string>> | ((field: string) => string | undefined);
|
|
5
7
|
export interface StrictToolInputOptions {
|
|
6
8
|
/** Old field name → new field name, refused as `input.field_renamed` wherever an object accepts the new name. */
|
|
7
|
-
readonly renamedFields?:
|
|
9
|
+
readonly renamedFields?: RenamedFields;
|
|
8
10
|
/** Boolean fields also take `"true"`/`"false"` and number fields a number written as text. Default: `true`. */
|
|
9
11
|
readonly coerceTextScalars?: boolean;
|
|
10
12
|
/** Default: the module's English dictionary. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strict-input.d.ts","sourceRoot":"","sources":["../../src/server/strict-input.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAI9D,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAEvC,qHAAqH;AACrH,MAAM,MAAM,uBAAuB,GAAG,OAAO,EAAE,CAAC,SAAS,CAAC;AAE1D,MAAM,
|
|
1
|
+
{"version":3,"file":"strict-input.d.ts","sourceRoot":"","sources":["../../src/server/strict-input.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAI9D,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAEvC,qHAAqH;AACrH,MAAM,MAAM,uBAAuB,GAAG,OAAO,EAAE,CAAC,SAAS,CAAC;AAE1D,sFAAsF;AACtF,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC,CAAC;AAEvG,MAAM,WAAW,sBAAsB;IACrC,iHAAiH;IACjH,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC,+GAA+G;IAC/G,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,CAAC,EAAE,uBAAuB,CAAC;CAC7C;AAWD,6GAA6G;AAC7G,wBAAgB,mBAAmB,CAAC,MAAM,SAAS,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG,MAAM,CAc1H;AAED,0HAA0H;AAC1H,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAShG"}
|
|
@@ -10,7 +10,14 @@ export function withStrictToolInput(server, options = {}) {
|
|
|
10
10
|
return server;
|
|
11
11
|
// The SDK's overloads only differ in how the schema is typed; at runtime it is one method.
|
|
12
12
|
const register = server.registerTool.bind(server);
|
|
13
|
-
const registerStrict = (name, config, callback) =>
|
|
13
|
+
const registerStrict = (name, config, callback) => {
|
|
14
|
+
if (config.inputSchema !== undefined)
|
|
15
|
+
return register(name, { ...config, inputSchema: toStrictToolInput(config.inputSchema, options) }, callback);
|
|
16
|
+
// Without a schema the SDK skips validation and calls `callback(ctx)`; with the strict empty object it calls
|
|
17
|
+
// `callback(args, ctx)`, so the callback keeps receiving the context only.
|
|
18
|
+
const contextCallback = callback;
|
|
19
|
+
return register(name, { ...config, inputSchema: toStrictToolInput(z.object({}), options) }, (_args, ctx) => contextCallback(ctx));
|
|
20
|
+
};
|
|
14
21
|
Object.defineProperty(server, "registerTool", { value: registerStrict, configurable: true, writable: true });
|
|
15
22
|
strictServers.add(server);
|
|
16
23
|
return server;
|
|
@@ -21,7 +28,7 @@ export function toStrictToolInput(schema, options = {}) {
|
|
|
21
28
|
if (zodSchema === null)
|
|
22
29
|
return schema;
|
|
23
30
|
const rewriter = new StrictRewriter({
|
|
24
|
-
|
|
31
|
+
renameField: toRenameRule(options.renamedFields ?? {}),
|
|
25
32
|
coerceTextScalars: options.coerceTextScalars ?? true,
|
|
26
33
|
messages: options.messages ?? en.toolInput,
|
|
27
34
|
});
|
|
@@ -35,6 +42,13 @@ function isRawShape(value) {
|
|
|
35
42
|
return false;
|
|
36
43
|
return Object.values(value).every(isZodSchema);
|
|
37
44
|
}
|
|
45
|
+
function toRenameRule(renamedFields) {
|
|
46
|
+
if (typeof renamedFields === "function")
|
|
47
|
+
return renamedFields;
|
|
48
|
+
return (field) => (Object.hasOwn(renamedFields, field) ? renamedFields[field] : undefined);
|
|
49
|
+
}
|
|
50
|
+
/** Wrappers that keep the value's kind: a chain of them around a scalar takes the text step around the whole chain. */
|
|
51
|
+
const WRAPPER_TYPES = new Set(["optional", "nullable", "default", "prefault", "nonoptional", "readonly", "catch"]);
|
|
38
52
|
class StrictRewriter {
|
|
39
53
|
settings;
|
|
40
54
|
// The same node (a shared field, a recursive `z.lazy`) is rewritten once.
|
|
@@ -63,8 +77,14 @@ class StrictRewriter {
|
|
|
63
77
|
case "prefault":
|
|
64
78
|
case "nonoptional":
|
|
65
79
|
case "readonly":
|
|
66
|
-
case "catch":
|
|
80
|
+
case "catch": {
|
|
81
|
+
// Outside the chain, zod still lists its `default` (it drops one on a transforming node) and the field's
|
|
82
|
+
// optionality is the chain's own; the step passes `undefined` and `null` through to it.
|
|
83
|
+
const reader = this.findTextReader(schema);
|
|
84
|
+
if (reader !== undefined)
|
|
85
|
+
return withTextStep(reader, schema);
|
|
67
86
|
return this.cloneWith(schema, { innerType: this.rewrite(def.innerType) });
|
|
87
|
+
}
|
|
68
88
|
case "union":
|
|
69
89
|
return this.cloneWith(schema, { options: def.options.map((option) => this.rewrite(option)) });
|
|
70
90
|
case "intersection":
|
|
@@ -83,13 +103,29 @@ class StrictRewriter {
|
|
|
83
103
|
return this.cloneWith(schema, { getter: () => this.rewrite(getter()) });
|
|
84
104
|
}
|
|
85
105
|
case "boolean":
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return
|
|
106
|
+
case "number": {
|
|
107
|
+
const reader = this.findTextReader(schema);
|
|
108
|
+
return reader === undefined ? schema : withTextStep(reader, schema);
|
|
109
|
+
}
|
|
89
110
|
default:
|
|
90
111
|
return schema;
|
|
91
112
|
}
|
|
92
113
|
}
|
|
114
|
+
/** The text reader for a boolean or number, seen through its wrapper chain; none when text is not taken. */
|
|
115
|
+
findTextReader(schema) {
|
|
116
|
+
if (!this.settings.coerceTextScalars)
|
|
117
|
+
return undefined;
|
|
118
|
+
let def = schema._zod.def;
|
|
119
|
+
while (WRAPPER_TYPES.has(def.type))
|
|
120
|
+
def = def.innerType._zod.def;
|
|
121
|
+
if (def.coerce === true)
|
|
122
|
+
return undefined;
|
|
123
|
+
if (def.type === "boolean")
|
|
124
|
+
return readBooleanText;
|
|
125
|
+
if (def.type === "number")
|
|
126
|
+
return readNumberText;
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
93
129
|
/** Only the input side: `in`, or `out` after a preprocess (whose `in` is the transform). */
|
|
94
130
|
rewritePipe(schema, def) {
|
|
95
131
|
const input = def.in;
|
|
@@ -126,11 +162,11 @@ class StrictRewriter {
|
|
|
126
162
|
function describeUnknownFields(issue, accepted, settings) {
|
|
127
163
|
if (issue.code !== "unrecognized_keys")
|
|
128
164
|
return undefined;
|
|
129
|
-
const { messages,
|
|
165
|
+
const { messages, renameField } = settings;
|
|
130
166
|
const renamed = [];
|
|
131
167
|
const unknown = [];
|
|
132
168
|
for (const field of issue.keys) {
|
|
133
|
-
const newName =
|
|
169
|
+
const newName = renameField(field);
|
|
134
170
|
if (newName !== undefined && accepted.includes(newName))
|
|
135
171
|
renamed.push(formatMessage(messages.fieldRenamed, { field, renamed: newName }));
|
|
136
172
|
else
|
|
@@ -144,6 +180,16 @@ function describeUnknownFields(issue, accepted, settings) {
|
|
|
144
180
|
function quoteAll(names) {
|
|
145
181
|
return names.map((name) => JSON.stringify(name)).join(", ");
|
|
146
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* `schema` behind a text step. zod gives every transform an optional input, so a step would make a required field
|
|
185
|
+
* look optional in the listed JSON Schema inside `nullable` or a union; it takes the optionality of the schema it
|
|
186
|
+
* wraps instead. That changes no parse: the step passes `undefined` on, and the schema refuses it as before.
|
|
187
|
+
*/
|
|
188
|
+
function withTextStep(reader, schema) {
|
|
189
|
+
const step = z.preprocess(reader, schema);
|
|
190
|
+
Object.defineProperty(step._zod, "optin", { value: schema._zod.optin, configurable: true, writable: true });
|
|
191
|
+
return step;
|
|
192
|
+
}
|
|
147
193
|
function readBooleanText(value) {
|
|
148
194
|
if (value === "true")
|
|
149
195
|
return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strict-input.js","sourceRoot":"","sources":["../../src/server/strict-input.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"strict-input.js","sourceRoot":"","sources":["../../src/server/strict-input.ts"],"names":[],"mappings":"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"}
|
package/dist/server/tokens.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Err, type ModuleContext, type Ok } from "@softure-ai/core";
|
|
2
2
|
import type { Queryable } from "@softure-ai/db";
|
|
3
|
-
import type { AccessTokenView } from "../contract.js";
|
|
3
|
+
import type { AccessTokenKind, AccessTokenView } from "../contract.js";
|
|
4
4
|
export type McpAccessContext = ModuleContext<Queryable>;
|
|
5
5
|
/** Marks a token as this module's, for people and for secret scanners. */
|
|
6
6
|
export declare const ACCESS_TOKEN_PREFIX = "sftmcp_";
|
|
@@ -29,15 +29,36 @@ export interface IssuedAccessToken {
|
|
|
29
29
|
}
|
|
30
30
|
export type IssueAccessTokenResult = Ok<IssuedAccessToken> | Err<"mcp-access.name_required" | "mcp-access.name_too_long" | "mcp-access.token_limit_reached">;
|
|
31
31
|
/**
|
|
32
|
-
* Issues
|
|
33
|
-
* that holds a per-user advisory lock, so two parallel requests cannot both take the last
|
|
34
|
-
* The owner's expired tokens are deleted first: they would otherwise count against the limit.
|
|
32
|
+
* Issues an MCP token for its owner. The per-account limit counts unexpired tokens of both kinds, in one
|
|
33
|
+
* transaction that holds a per-user advisory lock, so two parallel requests cannot both take the last
|
|
34
|
+
* place. The owner's expired tokens are deleted first: they would otherwise count against the limit.
|
|
35
35
|
* Database failures propagate.
|
|
36
36
|
*/
|
|
37
37
|
export declare function issueAccessToken(ctx: McpAccessContext, input: IssueAccessTokenInput): Promise<IssueAccessTokenResult>;
|
|
38
|
+
/** What `insertToken` stores: the new secret with its hash, write access and scopes are already decided. */
|
|
39
|
+
export interface TokenInsert {
|
|
40
|
+
readonly userId: string;
|
|
41
|
+
readonly name: string;
|
|
42
|
+
readonly kind: AccessTokenKind;
|
|
43
|
+
readonly canWrite: boolean;
|
|
44
|
+
readonly scopes: readonly string[];
|
|
45
|
+
/** The plaintext and the hash the lookup will find it by (`createSecret`, or the API token's own). */
|
|
46
|
+
readonly secret: {
|
|
47
|
+
readonly secret: string;
|
|
48
|
+
readonly secretHash: string;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export type InsertTokenResult = Ok<{
|
|
52
|
+
readonly id: string;
|
|
53
|
+
readonly token: string;
|
|
54
|
+
readonly name: string;
|
|
55
|
+
readonly expiresAt: Date;
|
|
56
|
+
}> | Err<"mcp-access.name_required" | "mcp-access.name_too_long" | "mcp-access.token_limit_reached">;
|
|
57
|
+
/** Stores a new token of either kind under the owner's lock and limit; the plaintext is returned once. */
|
|
58
|
+
export declare function insertToken(ctx: McpAccessContext, input: TokenInsert): Promise<InsertTokenResult>;
|
|
38
59
|
/**
|
|
39
|
-
* The owner's hand-issued tokens, newest first, expired ones included (the list marks
|
|
40
|
-
* OAuth access tokens are left out: the page shows their grants instead.
|
|
60
|
+
* The owner's hand-issued tokens of both kinds, newest first, expired ones included (the list marks
|
|
61
|
+
* them). OAuth access tokens are left out: the page shows their grants instead.
|
|
41
62
|
*/
|
|
42
63
|
export declare function listAccessTokens(ctx: McpAccessContext, userId: string): Promise<AccessTokenView[]>;
|
|
43
64
|
export interface RevokeAccessTokenInput {
|
|
@@ -68,14 +89,28 @@ export interface VerifiedAccessToken {
|
|
|
68
89
|
*/
|
|
69
90
|
export declare function findTokenClientName(ctx: McpAccessContext, tokenId: string): Promise<string | null>;
|
|
70
91
|
/**
|
|
71
|
-
* The identity behind
|
|
72
|
-
* tell which, so a guess learns nothing. The expiry sits in the query, so no
|
|
73
|
-
* it. Records the use (at most once a minute per token); a failed record is
|
|
74
|
-
* fail the request. Database failures of the lookup propagate.
|
|
92
|
+
* The identity behind an MCP token, or null for anything unknown, revoked or expired, and for an API
|
|
93
|
+
* token: the caller cannot tell which, so a guess learns nothing. The expiry sits in the query, so no
|
|
94
|
+
* code path can forget it. Records the use (at most once a minute per token); a failed record is
|
|
95
|
+
* logged and does not fail the request. Database failures of the lookup propagate.
|
|
75
96
|
*/
|
|
76
97
|
export declare function verifyAccessToken(ctx: McpAccessContext, token: string): Promise<VerifiedAccessToken | null>;
|
|
98
|
+
/** A stored, unexpired token of one kind, found by the hash of its plaintext. */
|
|
99
|
+
export interface ValidTokenRow {
|
|
100
|
+
readonly id: string;
|
|
101
|
+
readonly userId: string;
|
|
102
|
+
readonly canWrite: boolean;
|
|
103
|
+
readonly expiresAt: Date;
|
|
104
|
+
readonly grantId: string | null;
|
|
105
|
+
readonly scopes: readonly string[];
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The unexpired token of `kind` stored under this hash, or null, after recording its use. The caller
|
|
109
|
+
* checks the shape first, so no lookup runs for a value that cannot be a token.
|
|
110
|
+
*/
|
|
111
|
+
export declare function findValidToken(ctx: McpAccessContext, tokenHash: string, kind: AccessTokenKind): Promise<ValidTokenRow | null>;
|
|
77
112
|
/**
|
|
78
|
-
* Deletes every expired token, of every account, hand-issued and OAuth alike. Issuing already
|
|
113
|
+
* Deletes every expired token, of every account and kind, hand-issued and OAuth alike. Issuing already
|
|
79
114
|
* removes the issuer's own; an app may call this from a scheduled job so abandoned accounts do not
|
|
80
115
|
* keep dead rows (with `pruneOAuthRecords` for codes, grants and clients).
|
|
81
116
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/server/tokens.ts"],"names":[],"mappings":"AAIA,OAAO,EAA0B,KAAK,GAAG,EAAE,KAAK,aAAa,EAAE,KAAK,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACjG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/server/tokens.ts"],"names":[],"mappings":"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"}
|
package/dist/server/tokens.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// Access tokens (an adopting app's token code, generalised).
|
|
2
|
-
// bytes; the database holds only its sha256, so a leaked row cannot be replayed. The plaintext
|
|
1
|
+
// Access tokens (an adopting app's token code, generalised). An MCP token is `sftmcp_` and 32 random
|
|
2
|
+
// bytes, an API token (`api-tokens.ts`) the app's prefix and 32 random bytes; the database holds only its sha256, so a leaked row cannot be replayed. The plaintext
|
|
3
3
|
// leaves this file once, in the result of `issueAccessToken` (or of an OAuth exchange, `oauth.ts`).
|
|
4
4
|
import { createHash, randomBytes } from "node:crypto";
|
|
5
5
|
import { err, errorLogLabel, ok } from "@softure-ai/core";
|
|
@@ -39,19 +39,28 @@ export function createSecret(prefix) {
|
|
|
39
39
|
return { secret, secretHash: hashAccessToken(secret) };
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
|
-
* Issues
|
|
43
|
-
* that holds a per-user advisory lock, so two parallel requests cannot both take the last
|
|
44
|
-
* The owner's expired tokens are deleted first: they would otherwise count against the limit.
|
|
42
|
+
* Issues an MCP token for its owner. The per-account limit counts unexpired tokens of both kinds, in one
|
|
43
|
+
* transaction that holds a per-user advisory lock, so two parallel requests cannot both take the last
|
|
44
|
+
* place. The owner's expired tokens are deleted first: they would otherwise count against the limit.
|
|
45
45
|
* Database failures propagate.
|
|
46
46
|
*/
|
|
47
47
|
export async function issueAccessToken(ctx, input) {
|
|
48
|
+
const options = getMcpAccessOptions(ctx.config);
|
|
49
|
+
const canWrite = input.canWrite && options.allowWrites;
|
|
50
|
+
const result = await insertToken(ctx, { userId: input.userId, name: input.name, kind: "mcp", canWrite, scopes: [], secret: createSecret(ACCESS_TOKEN_PREFIX) });
|
|
51
|
+
if (!result.ok)
|
|
52
|
+
return result;
|
|
53
|
+
const { id, token, name, expiresAt } = result.value;
|
|
54
|
+
return ok({ id, token, name, canWrite, expiresAt });
|
|
55
|
+
}
|
|
56
|
+
/** Stores a new token of either kind under the owner's lock and limit; the plaintext is returned once. */
|
|
57
|
+
export async function insertToken(ctx, input) {
|
|
48
58
|
const name = input.name.trim();
|
|
49
59
|
if (name === "")
|
|
50
60
|
return err("mcp-access.name_required");
|
|
51
61
|
if (name.length > MAX_TOKEN_NAME_LENGTH)
|
|
52
62
|
return err("mcp-access.name_too_long");
|
|
53
63
|
const options = getMcpAccessOptions(ctx.config);
|
|
54
|
-
const canWrite = input.canWrite && options.allowWrites;
|
|
55
64
|
const now = ctx.clock.now();
|
|
56
65
|
const expiresAt = new Date(now.getTime() + options.tokenLifetimeDays * DAY_MS);
|
|
57
66
|
return ctx.db.transaction(async (tx) => {
|
|
@@ -64,25 +73,27 @@ export async function issueAccessToken(ctx, input) {
|
|
|
64
73
|
.where(and(eq(accessTokens.userId, input.userId), isNull(accessTokens.grantId)));
|
|
65
74
|
if ((held?.total ?? 0) >= options.maxTokensPerUser)
|
|
66
75
|
return err("mcp-access.token_limit_reached");
|
|
67
|
-
const { secret: token, secretHash: tokenHash } =
|
|
76
|
+
const { secret: token, secretHash: tokenHash } = input.secret;
|
|
68
77
|
const [row] = await tx
|
|
69
78
|
.insert(accessTokens)
|
|
70
|
-
.values({ userId: input.userId, name, tokenHash, canWrite, createdAt: now, expiresAt })
|
|
79
|
+
.values({ userId: input.userId, name, tokenHash, canWrite: input.canWrite, createdAt: now, expiresAt, kind: input.kind, scopes: [...input.scopes] })
|
|
71
80
|
.returning();
|
|
72
81
|
if (row === undefined)
|
|
73
82
|
throw new Error("@softure-ai/mcp-access: inserting a token returned no row");
|
|
74
|
-
return ok({ id: row.id, token, name,
|
|
83
|
+
return ok({ id: row.id, token, name, expiresAt });
|
|
75
84
|
});
|
|
76
85
|
}
|
|
77
86
|
/**
|
|
78
|
-
* The owner's hand-issued tokens, newest first, expired ones included (the list marks
|
|
79
|
-
* OAuth access tokens are left out: the page shows their grants instead.
|
|
87
|
+
* The owner's hand-issued tokens of both kinds, newest first, expired ones included (the list marks
|
|
88
|
+
* them). OAuth access tokens are left out: the page shows their grants instead.
|
|
80
89
|
*/
|
|
81
90
|
export async function listAccessTokens(ctx, userId) {
|
|
82
91
|
return ctx.db
|
|
83
92
|
.select({
|
|
84
93
|
id: accessTokens.id,
|
|
85
94
|
name: accessTokens.name,
|
|
95
|
+
kind: accessTokens.kind,
|
|
96
|
+
scopes: accessTokens.scopes,
|
|
86
97
|
canWrite: accessTokens.canWrite,
|
|
87
98
|
createdAt: accessTokens.createdAt,
|
|
88
99
|
expiresAt: accessTokens.expiresAt,
|
|
@@ -117,15 +128,31 @@ export async function findTokenClientName(ctx, tokenId) {
|
|
|
117
128
|
return row?.name ?? null;
|
|
118
129
|
}
|
|
119
130
|
/**
|
|
120
|
-
* The identity behind
|
|
121
|
-
* tell which, so a guess learns nothing. The expiry sits in the query, so no
|
|
122
|
-
* it. Records the use (at most once a minute per token); a failed record is
|
|
123
|
-
* fail the request. Database failures of the lookup propagate.
|
|
131
|
+
* The identity behind an MCP token, or null for anything unknown, revoked or expired, and for an API
|
|
132
|
+
* token: the caller cannot tell which, so a guess learns nothing. The expiry sits in the query, so no
|
|
133
|
+
* code path can forget it. Records the use (at most once a minute per token); a failed record is
|
|
134
|
+
* logged and does not fail the request. Database failures of the lookup propagate.
|
|
124
135
|
*/
|
|
125
136
|
export async function verifyAccessToken(ctx, token) {
|
|
126
137
|
const options = getMcpAccessOptions(ctx.config);
|
|
127
138
|
if (!isAcceptedTokenShape(options, token))
|
|
128
139
|
return null;
|
|
140
|
+
const row = await findValidToken(ctx, hashAccessToken(token), "mcp");
|
|
141
|
+
if (row === null)
|
|
142
|
+
return null;
|
|
143
|
+
return {
|
|
144
|
+
tokenId: row.id,
|
|
145
|
+
userId: row.userId,
|
|
146
|
+
canWrite: row.canWrite && options.allowWrites,
|
|
147
|
+
expiresAt: row.expiresAt,
|
|
148
|
+
grantId: row.grantId,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* The unexpired token of `kind` stored under this hash, or null, after recording its use. The caller
|
|
153
|
+
* checks the shape first, so no lookup runs for a value that cannot be a token.
|
|
154
|
+
*/
|
|
155
|
+
export async function findValidToken(ctx, tokenHash, kind) {
|
|
129
156
|
const now = ctx.clock.now();
|
|
130
157
|
const [row] = await ctx.db
|
|
131
158
|
.select({
|
|
@@ -134,19 +161,14 @@ export async function verifyAccessToken(ctx, token) {
|
|
|
134
161
|
canWrite: accessTokens.canWrite,
|
|
135
162
|
expiresAt: accessTokens.expiresAt,
|
|
136
163
|
grantId: accessTokens.grantId,
|
|
164
|
+
scopes: accessTokens.scopes,
|
|
137
165
|
})
|
|
138
166
|
.from(accessTokens)
|
|
139
|
-
.where(and(eq(accessTokens.tokenHash,
|
|
167
|
+
.where(and(eq(accessTokens.tokenHash, tokenHash), eq(accessTokens.kind, kind), gt(accessTokens.expiresAt, now)));
|
|
140
168
|
if (row === undefined)
|
|
141
169
|
return null;
|
|
142
170
|
await recordUse(ctx, row, now);
|
|
143
|
-
return
|
|
144
|
-
tokenId: row.id,
|
|
145
|
-
userId: row.userId,
|
|
146
|
-
canWrite: row.canWrite && options.allowWrites,
|
|
147
|
-
expiresAt: row.expiresAt,
|
|
148
|
-
grantId: row.grantId,
|
|
149
|
-
};
|
|
171
|
+
return row;
|
|
150
172
|
}
|
|
151
173
|
/** Records the use on the token and, for an OAuth token, on its grant (the connected apps list). */
|
|
152
174
|
async function recordUse(ctx, token, now) {
|
|
@@ -169,7 +191,7 @@ async function recordUse(ctx, token, now) {
|
|
|
169
191
|
}
|
|
170
192
|
}
|
|
171
193
|
/**
|
|
172
|
-
* Deletes every expired token, of every account, hand-issued and OAuth alike. Issuing already
|
|
194
|
+
* Deletes every expired token, of every account and kind, hand-issued and OAuth alike. Issuing already
|
|
173
195
|
* removes the issuer's own; an app may call this from a scheduled job so abandoned accounts do not
|
|
174
196
|
* keep dead rows (with `pruneOAuthRecords` for codes, grants and clients).
|
|
175
197
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/server/tokens.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/server/tokens.ts"],"names":[],"mappings":"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"}
|
package/dist/server/tools.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export interface ToolErrorOptions {
|
|
|
13
13
|
readonly caller?: ToolCaller;
|
|
14
14
|
/** The tool's arguments, for the record: only their names are read, never their values. */
|
|
15
15
|
readonly args?: Readonly<Record<string, unknown>>;
|
|
16
|
+
/** Whether the call ran on the person's confirmation, for the record (`withConfirmation` sets it). */
|
|
17
|
+
readonly confirmed?: boolean;
|
|
16
18
|
}
|
|
17
19
|
/** The client behind a call: the token's id (`McpServerIdentity.tokenId`) and its name (`findTokenClientName`). */
|
|
18
20
|
export interface ToolCaller {
|
|
@@ -41,6 +43,12 @@ export interface ToolCallRecord {
|
|
|
41
43
|
readonly tokenId: string | null;
|
|
42
44
|
readonly clientName: string | null;
|
|
43
45
|
readonly argumentNames: readonly string[];
|
|
46
|
+
/**
|
|
47
|
+
* For a tool wrapped in `withConfirmation`: `true` when the call carried a valid confirmation and did the work,
|
|
48
|
+
* `false` when it answered an estimate, was refused, or ran without asking (`runWithoutConfirmationWhen`). `null`
|
|
49
|
+
* for any other tool.
|
|
50
|
+
*/
|
|
51
|
+
readonly confirmed: boolean | null;
|
|
44
52
|
readonly outcome: ToolCallOutcome;
|
|
45
53
|
readonly startedAt: Date;
|
|
46
54
|
readonly durationMs: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/server/tools.ts"],"names":[],"mappings":"AAIA,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACrF,OAAO,EAA8C,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAElG,4IAA4I;AAC5I,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC;IAChC,sEAAsE;IACtE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,+GAA+G;IAC/G,QAAQ,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC;IACnC,sFAAsF;IACtF,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B,2FAA2F;IAC3F,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/server/tools.ts"],"names":[],"mappings":"AAIA,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACrF,OAAO,EAA8C,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAElG,4IAA4I;AAC5I,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC;IAChC,sEAAsE;IACtE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,+GAA+G;IAC/G,QAAQ,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC;IACnC,sFAAsF;IACtF,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B,2FAA2F;IAC3F,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAClD,sGAAsG;IACtG,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,mHAAmH;AACnH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACjE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACzD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAAA;CAAE,CAAC;AAErE,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,cAAc,KAAK,OAAO,CAAC;AAQ/D,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAEzD;AAED,+DAA+D;AAC/D,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAEzD;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,OAAO,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,cAAc,CAAC,CAcjH;AA+BD,2DAA2D;AAC3D,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,GAAE,cAAmB,GAAG,cAAc,CAItF;AAUD,iEAAiE;AACjE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAExE"}
|
package/dist/server/tools.js
CHANGED
|
@@ -47,6 +47,7 @@ async function reportToolCall(options, outcome, startedAt) {
|
|
|
47
47
|
tokenId: options.caller?.tokenId ?? null,
|
|
48
48
|
clientName: options.caller?.clientName ?? null,
|
|
49
49
|
argumentNames: Object.keys(options.args ?? {}),
|
|
50
|
+
confirmed: options.confirmed ?? null,
|
|
50
51
|
outcome,
|
|
51
52
|
startedAt: new Date(startedAt),
|
|
52
53
|
durationMs: Date.now() - startedAt,
|