@happyvertical/smrt-app-mcp 0.53.3 → 0.53.5

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.
@@ -2,7 +2,7 @@
2
2
  "version": "1.0.0",
3
3
  "timestamp": 0,
4
4
  "packageName": "@happyvertical/smrt-app-mcp",
5
- "packageVersion": "0.53.3",
5
+ "packageVersion": "0.53.5",
6
6
  "objects": {},
7
7
  "moduleType": "smrt",
8
8
  "smrtDependencies": [
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Own-data reads of application-supplied principal mappings (#3413 review
3
+ * N1). Inherited values, accessors and prototype-poison keys never become
4
+ * authority.
5
+ *
6
+ * @internal
7
+ */
8
+ /**
9
+ * The listed own data fields of a plain object (prototype `Object.prototype`
10
+ * or `null`) in a null-prototype record, or `null` when `value` is not a
11
+ * plain object, has an own `__proto__`/`constructor`/`prototype` key, or any
12
+ * listed field is an accessor. Absent fields are omitted.
13
+ */
14
+ export declare function readOwnFields(value: unknown, keys: readonly string[]): Record<string, unknown> | null;
15
+ /**
16
+ * A copy of a dense, plain array of strings read from own data properties,
17
+ * or `null` for anything else (sparse, subclassed, extra keys, accessors,
18
+ * non-strings).
19
+ */
20
+ export declare function ownStringArray(value: unknown): string[] | null;
21
+ //# sourceMappingURL=own-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"own-data.d.ts","sourceRoot":"","sources":["../src/own-data.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAehC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,IAAI,CA2B9D"}
package/dist/server.d.ts CHANGED
@@ -18,6 +18,7 @@
18
18
  import type { MCPConfig, MCPResponse, MCPTool } from '@happyvertical/smrt-core/generators/mcp';
19
19
  import { type McpTask } from '@happyvertical/smrt-jobs';
20
20
  import { type McpAppResource, type McpAppResourceContent, type McpAppResourceDefinition, type McpResourcePolicy } from './resources.js';
21
+ import { type McpToolEffect } from './tools.js';
21
22
  import { type McpWorkflowToolDefinition } from './workflow-tools.js';
22
23
  /**
23
24
  * Generic authenticated caller information available to app-MCP policy.
@@ -27,6 +28,13 @@ import { type McpWorkflowToolDefinition } from './workflow-tools.js';
27
28
  * application's identity or capability model. A missing principal means the
28
29
  * request is unauthenticated.
29
30
  */
31
+ /**
32
+ * How a bearer principal's tenant authority may be established when the
33
+ * route binds it (`runtime.runAsPrincipal`): `direct` needs an active direct
34
+ * membership in exactly `tenantId`; `direct-or-inherited` also accepts
35
+ * authority inherited from an active inheritable ancestor membership.
36
+ */
37
+ export type McpTenantBinding = 'direct' | 'direct-or-inherited';
30
38
  export interface McpAppPrincipal {
31
39
  id?: string;
32
40
  /** Tenant boundary for task ownership and generated tenant-scoped actions. */
@@ -36,6 +44,12 @@ export interface McpAppPrincipal {
36
44
  kind?: string;
37
45
  roles?: string[];
38
46
  scopes?: string[];
47
+ /**
48
+ * Binding mode carried from the authentication adapter, never request
49
+ * input: local owner tokens are `direct`; hosted access tokens default to
50
+ * `direct-or-inherited` unless their mapping narrows it.
51
+ */
52
+ tenantBinding?: McpTenantBinding;
39
53
  }
40
54
  /** Minimal legacy user shape used for generated tool-call attribution. */
41
55
  export interface McpAppUser extends McpAppPrincipal {
@@ -53,6 +67,15 @@ export interface McpToolPolicyContext {
53
67
  * boundary.
54
68
  */
55
69
  export type McpToolPolicy = (context: McpToolPolicyContext) => boolean | Promise<boolean>;
70
+ /**
71
+ * Principal-level predicate for durable task lifecycle calls (`tasks/get`,
72
+ * `tasks/update`, `tasks/cancel`). It receives the authenticated, bound
73
+ * principal (with effective scopes) and no tool: return `false` to answer
74
+ * the call as an unknown task. A thrown error is a denial.
75
+ */
76
+ export type McpTaskPrincipalPolicy = (context: {
77
+ principal: McpAppPrincipal;
78
+ }) => boolean | Promise<boolean>;
56
79
  /**
57
80
  * Workflow assertion hook signature. Throw `McpAccessError` to reject the
58
81
  * call. Implementations may mutate `args` in place to inject server-trusted
@@ -128,7 +151,25 @@ export interface CreateMcpAppServerOptions {
128
151
  * assertion gates before the handler runs.
129
152
  */
130
153
  workflowTools?: readonly McpWorkflowToolDefinition[];
154
+ /**
155
+ * Restrict the catalog to tools whose effect (see `mcpToolEffect`) is
156
+ * listed, for example `['read']` until per-operation authorization exists.
157
+ * Excluded tools are absent from discovery and a direct call receives the
158
+ * same not-found error as an unknown tool, so they cannot be enumerated.
159
+ * Omitted: every allow-listed tool, regardless of effect.
160
+ */
161
+ effects?: readonly McpToolEffect[];
131
162
  resources?: readonly McpAppResourceDefinition[];
163
+ /**
164
+ * Gate every task lifecycle call (`tasks/get`, `tasks/update`,
165
+ * `tasks/cancel`) on the calling principal before the task store is
166
+ * touched; a denial is answered as an unknown task. `toolPolicy` is not
167
+ * re-applied to lifecycle calls (a task does not yet record the tool that
168
+ * created it), so a server whose `toolPolicy` encodes principal-level
169
+ * requirements (scopes, roles, revocation) should restate them here.
170
+ * `createDefaultMcpAppServer` supplies its principal scope policy.
171
+ */
172
+ taskPrincipalPolicy?: McpTaskPrincipalPolicy;
132
173
  /** Required for private resources; rechecked on catalog/read, errors deny. */
133
174
  resourcePolicy?: McpResourcePolicy;
134
175
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EACX,OAAO,EAER,MAAM,yCAAyC,CAAC;AAKjD,OAAO,EACL,KAAK,OAAO,EAIb,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EAEvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAIL,KAAK,aAAa,EAEnB,MAAM,YAAY,CAAC;AACpB,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;GAOG;AACH;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,qBAAqB,CAAC;AAEhE,MAAM,WAAW,eAAe;IAC9B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;;OAIG;IACH,aAAa,CAAC,EAAE,gBAAgB,CAAC;CAClC;AAED,0EAA0E;AAC1E,MAAM,WAAW,UAAW,SAAQ,eAAe;IACjD,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,kEAAkE;AAClE,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAClC,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,CAC1B,OAAO,EAAE,oBAAoB,KAC1B,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEhC;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,EAAE;IAC7C,SAAS,EAAE,eAAe,CAAC;CAC5B,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEjC;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,CACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,IAAI,EAAE,UAAU,GAAG,IAAI,KACpB,IAAI,CAAC;AAEV;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEhE,mEAAmE;AACnE,MAAM,MAAM,0BAA0B,GAAG,MAAM,SAAS,MAAM,EAAE,CAAC;AAEjE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,SAAS,GAAG,QAAQ,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,uFAAuF;IACvF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,UAAU,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAClC;;;OAGG;IACH,aAAa,CAAC,EAAE,IAAI,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,mEAAmE;IACnE,WAAW,EAAE,mBAAmB,CAAC;IACjC,oDAAoD;IACpD,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GACvD,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IACjC;;;;OAIG;IACH,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,0BAA0B,CAAC;IAChD;;;;OAIG;IACH,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC;;;;OAIG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAC1D;;;;;OAKG;IACH,aAAa,CAAC,EAAE,SAAS,yBAAyB,EAAE,CAAC;IACrD;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IACnC,SAAS,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAC;IAChD;;;;;;;;OAQG;IACH,mBAAmB,CAAC,EAAE,sBAAsB,CAAC;IAC7C,8EAA8E;IAC9E,cAAc,CAAC,EAAE,iBAAiB,CAAC;CACpC;AAED,2BAA2B;AAC3B,MAAM,WAAW,cAAc;IAC7B,4EAA4E;IAC5E,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAwB;AACxB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,4EAA4E;IAC5E,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC;;;OAGG;IACH,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;CAC1B;AAED,8CAA8C;AAC9C,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACrD,aAAa,CAAC,CAAC,KAAK,EAAE;QACpB,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;KACpC,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAC9B,YAAY,CAAC,CAAC,KAAK,EAAE;QACnB,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;KACpC,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACrD,0EAA0E;IAC1E,cAAc,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACpC,yDAAyD;IACzD,UAAU,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5C,4EAA4E;IAC5E,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,+EAA+E;IAC/E,QAAQ,CAAC,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACtD,kDAAkD;IAClD,OAAO,CAAC,CAAC,KAAK,EAAE;QACd,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;KACpC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrB,UAAU,CAAC,CAAC,KAAK,EAAE;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACxC,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;KACpC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB,UAAU,CAAC,CAAC,KAAK,EAAE;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;KACpC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB,sDAAsD;IACtD,qBAAqB,CAAC,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACxD,wDAAwD;IACxD,QAAQ,CAAC,UAAU,EAAE,yBAAyB,CAAC,YAAY,CAAC,CAAC;CAC9D;AAkED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,yBAAyB,GACjC,YAAY,CAygBd"}
@@ -3,13 +3,13 @@
3
3
  "sensitiveFieldsExcluded": true,
4
4
  "generatedAt": "1970-01-01T00:00:00.000Z",
5
5
  "packageName": "@happyvertical/smrt-app-mcp",
6
- "packageVersion": "0.53.3",
6
+ "packageVersion": "0.53.5",
7
7
  "sourceManifestPath": "dist/manifest.json",
8
8
  "agentDocPath": "AGENTS.md",
9
9
  "sourceHashes": {
10
- "manifest": "72e1d126b3045a39adc26c832b883ae58eefddd49bea66f5a2f4c530b1e14090",
11
- "packageJson": "ecadf664928b812213c1cca17e00fb6913dbf6c12fe354a04df619b3e91e1485",
12
- "agents": "f249d4732daeb08f865b67237c0da2b166a96f749b1ec6b595f2bb17c24c2d30"
10
+ "manifest": "c197f498693ff6388bcbf4efcd4e10480efcde3885cf82d98dc07eda8f3a110f",
11
+ "packageJson": "2efaa45af7ae288ffbc7d78c95e977a805431cf5e7c03662f0b84270ef68bba2",
12
+ "agents": "9a9a0828eec449ebe5d7c0c36960bf7cf52ba18586e2355bd60782903940d378"
13
13
  },
14
14
  "exports": [
15
15
  ".",
@@ -59,5 +59,5 @@
59
59
  "polymorphicAssociations": 0,
60
60
  "uuidColumns": 0
61
61
  },
62
- "agentDoc": "# @happyvertical/smrt-app-mcp\n\nApplication-scoped MCP server wrapper for SMRT apps. The core owns generated\ntool policy; `./sveltekit` owns the stateless Streamable HTTP transport.\n\n## Purpose\n\n- Wraps `@happyvertical/smrt-core` MCP generation with app-level tool allow-lists.\n- Filters unauthenticated tool visibility to public read-only tools.\n- Applies an optional principal-aware policy consistently to discovery and calls.\n- Provides workflow assertions so app servers can reject unsafe or incomplete tool calls before dispatch.\n- Exposes an opt-in durable Tasks extension through `@happyvertical/smrt-jobs`.\n\n## Patterns\n\n- Generate tools from core, then filter by allowed class-name prefixes.\n- Treat list/get tools as read-only; mutating tools require authentication unless the app deliberately wraps them with stronger policy.\n- Keep app policy outside generated tool schemas. The wrapper owns auth, allow-list, and workflow assertion behavior.\n- Return 404 for tools outside the app allow-list so private generated tools are not enumerated by mistake.\n- Trust only a principal supplied by the application adapter. This package\n does not implement an OAuth authorization server. The opt-in `./auth` entry\n validates JWT access tokens and requires an application-owned principal mapper.\n- Mount `mountMcpRoute` as one modern `POST` endpoint. It creates a fresh\n protocol server per request, emits no session id, and refuses subscriptions.\n- Keep tool catalogs private by default. Public caching requires an explicit\n attestation and a global, unauthenticated, read-only, non-tenant catalog with\n no principal-aware policy.\n\n## Gotchas\n\n- Public tool patterns are still constrained by read-only detection.\n- Policy errors fail closed and expose only the shared safe denial envelope.\n- Workflow assertions run before generated tool dispatch and should be deterministic.\n- Tasks require a stable authenticated principal id, preserve its tenant boundary,\n and require the deployment to run a `TaskRunner` for the `mcp-tasks` queue.\n- This package ships no stdio executable. Use `@happyvertical/smrt-app-cli` to\n bridge a deployed app endpoint to a local MCP client.\n- `mountMcpToolsRoute` and `mountMcpCallRoute` are deprecated REST-shaped\n compatibility aliases, not MCP transports.\n- This package is runtime app infrastructure, not the development MCP. Use `@happyvertical/smrt-dev-mcp` for agentic development knowledge, review, and architecture tooling.\n"
62
+ "agentDoc": "# @happyvertical/smrt-app-mcp\n\nApplication-scoped MCP server wrapper for SMRT apps. The core owns generated\ntool policy; `./sveltekit` owns the stateless Streamable HTTP transport.\n\n## Purpose\n\n- Wraps `@happyvertical/smrt-core` MCP generation with app-level tool allow-lists.\n- Filters unauthenticated tool visibility to public read-only tools.\n- Applies an optional principal-aware policy consistently to discovery and calls.\n- Provides workflow assertions so app servers can reject unsafe or incomplete tool calls before dispatch.\n- Exposes an opt-in durable Tasks extension through `@happyvertical/smrt-jobs`.\n\n## Patterns\n\n- Generate tools from core, then filter by allowed class-name prefixes.\n- Treat list/get tools as read-only; mutating tools require authentication unless the app deliberately wraps them with stronger policy.\n- Keep app policy outside generated tool schemas. The wrapper owns auth, allow-list, and workflow assertion behavior.\n- Return 404 for tools outside the app allow-list so private generated tools are not enumerated by mistake.\n- Trust only a principal supplied by the application adapter. This package\n does not implement an OAuth authorization server. The opt-in `./auth` entry\n validates JWT access tokens and requires an application-owned principal mapper.\n- Mount `mountMcpRoute` as one modern `POST` endpoint. It creates a fresh\n protocol server per request, emits no session id, and refuses subscriptions.\n- `mountMcpAppRoute` (`src/defaults.ts` + `./sveltekit`) is the one-call app\n route: explicit `models` allow-list, required `requiredScopes`, principal from\n session locals (`principalFromSessionLocals`). App policies compose with the\n default and may only narrow it. Its `Origin` check (default on; opt-in on\n `mountMcpRoute`) runs before auth and dispatch; no-`Origin` clients pass.\n `effects` filters the catalog by `mcpToolEffect` (excluded tools 404).\n `auth` swaps in bearer principals; `bindPrincipal` runs their dispatch in\n the app's principal context (RLS transaction), failing closed, and\n authorizes with the binder's narrowed (live) scopes; task lifecycle calls\n re-check the originating action against the allow-list and `effects`,\n after a principal-level `taskPrincipalPolicy` (defaults: scope policy);\n `mountMcpProtectedResourceMetadataRoute` serves only the advertised path.\n- `createHostedMcpResourceAuth({ profile, runtime })`: locally, a runtime\n `verifyLocalMcpToken` yields the `sessionFallback` adapter\n (`createLocalMcpTokenAuth`): no `Authorization` header keeps the session\n principal; a presented bearer must verify (401, never cookie fallback); no\n metadata (404). Hosted, `runtime.resolveMcpPrincipal` is the default\n identity mapping; an explicit `resolvePrincipal` overrides it.\n- Adapters stamp `principal.tenantBinding` for `bindPrincipal`: the local\n token adapter always `direct`; the JWT adapter the mapping's value or\n `direct-or-inherited`. Never derive it from request input. Both adapters\n read principals/mappings from own data only (`own-data.ts`): inherited\n values, accessors and poison keys deny.\n- Keep tool catalogs private by default. Public caching requires an explicit\n attestation and a global, unauthenticated, read-only, non-tenant catalog with\n no principal-aware policy.\n\n## Gotchas\n\n- Public tool patterns are still constrained by read-only detection.\n- Policy errors fail closed and expose only the shared safe denial envelope.\n- Workflow assertions run before generated tool dispatch and should be deterministic.\n- Tasks require a stable authenticated principal id, preserve its tenant boundary,\n and require the deployment to run a `TaskRunner` for the `mcp-tasks` queue.\n- This package ships no stdio executable. Use `@happyvertical/smrt-app-cli` to\n bridge a deployed app endpoint to a local MCP client.\n- `mountMcpToolsRoute` and `mountMcpCallRoute` are deprecated REST-shaped\n compatibility aliases, not MCP transports.\n- This package is runtime app infrastructure, not the development MCP. Use `@happyvertical/smrt-dev-mcp` for agentic development knowledge, review, and architecture tooling.\n"
63
63
  }
@@ -7,12 +7,26 @@
7
7
  *
8
8
  * @example
9
9
  * ```ts
10
- * // src/routes/api/mcp/+server.ts
10
+ * // src/routes/api/mcp/+server.ts — one call with the app defaults
11
+ * import { mountMcpAppRoute } from '@happyvertical/smrt-app-mcp/sveltekit';
12
+ * import { Item } from '$lib/objects/Item';
13
+ * export const POST = mountMcpAppRoute({
14
+ * models: [Item],
15
+ * requiredScopes: ['items.read'],
16
+ * smrtOptions: () => ({ db: getDatabaseConfig() }),
17
+ * });
18
+ * ```
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * // src/routes/api/mcp/+server.ts — a custom server core
11
23
  * import { mountMcpRoute } from '@happyvertical/smrt-app-mcp/sveltekit';
12
24
  * import { mcpServer } from '$lib/server/mcp';
13
25
  * export const POST = mountMcpRoute(mcpServer);
14
26
  * ```
15
27
  */
28
+ import type { McpResourceAuth } from './auth.js';
29
+ import { type CreateDefaultMcpAppServerOptions } from './defaults.js';
16
30
  import { type McpProtocolRequestOptions } from './protocol.js';
17
31
  import type { McpAppPrincipal, McpAppServer } from './server.js';
18
32
  /** Minimal subset of a SvelteKit RequestEvent we actually touch. */
@@ -27,8 +41,104 @@ export type McpSvelteKitHandler = (event: SvelteKitRequestEvent) => Promise<Resp
27
41
  export type McpPrincipalResolver = (event: SvelteKitRequestEvent) => McpAppPrincipal | null | undefined;
28
42
  /** Backwards-compatible alias for callers that name the principal a user. */
29
43
  export type McpUserResolver = McpPrincipalResolver;
44
+ /**
45
+ * The bearer-authentication surface `mountMcpRoute` and the metadata route
46
+ * need from `createMcpResourceAuth` (`./auth`). Typed structurally so this
47
+ * entry does not load the JWT verifier.
48
+ */
49
+ export type McpRouteResourceAuth = Pick<McpResourceAuth, 'metadataUrl' | 'metadataResponse' | 'authenticate' | 'sessionFallback'>;
50
+ /**
51
+ * A protected-resource adapter, or a thunk read on every request. A `null` or
52
+ * `undefined` result (for example the `local` profile) means the route uses
53
+ * its session principal resolver instead.
54
+ */
55
+ export type McpRouteResourceAuthSource = McpRouteResourceAuth | null | undefined | (() => McpRouteResourceAuth | null | undefined);
56
+ /**
57
+ * Project the session hook's request-local result onto an MCP principal.
58
+ *
59
+ * Reads only `locals.user.id`, the session-authorized `locals.tenantId`, and
60
+ * `locals.permissions` as populated by `createSessionHandler` from
61
+ * `@happyvertical/smrt-users/sveltekit`. Headers, URL-selected tenants
62
+ * (`locals.selectedTenantId`), request bodies and route arguments are never
63
+ * identity inputs. Any missing or malformed field yields `null`
64
+ * (unauthenticated), which fails closed for every non-public tool.
65
+ */
66
+ export declare function principalFromSessionLocals(event: {
67
+ locals?: Record<string, unknown>;
68
+ }): McpAppPrincipal | null;
69
+ /**
70
+ * Run MCP dispatch for a bearer-authenticated principal inside an
71
+ * application-owned context bound to that principal (for example
72
+ * `runtime.runAsPrincipal` from `@happyvertical/smrt-app-runtime/sveltekit`,
73
+ * which opens the principal's permission context and, under `database-rls`,
74
+ * its RLS transaction). Must call `run` exactly once and return its result;
75
+ * throwing before `run` (an unbindable principal) is a denial.
76
+ *
77
+ * Pass `run` the bound principal carrying its *effective* `scopes` (for
78
+ * example the token scopes still granted by live membership permissions).
79
+ * Dispatch then authorizes with those scopes, intersected with the token's:
80
+ * a binder can only narrow authority, and changing the principal's `id` or
81
+ * `tenantId` is a denial. Calling `run()` with no argument keeps the token
82
+ * scopes.
83
+ */
84
+ export type McpPrincipalBinder = <T>(principal: McpAppPrincipal & {
85
+ id: string;
86
+ }, run: (bound?: McpBoundPrincipal) => Promise<T>) => Promise<T>;
87
+ /**
88
+ * The principal a binder hands back to `run`: the authenticated identity,
89
+ * possibly as a frozen snapshot whose arrays are readonly (for example the
90
+ * deep-frozen principal `runtime.runAsPrincipal` passes its callback).
91
+ */
92
+ export type McpBoundPrincipal = Omit<McpAppPrincipal, 'scopes' | 'roles'> & {
93
+ id: string;
94
+ scopes?: readonly string[];
95
+ roles?: readonly string[];
96
+ };
30
97
  /** Options shared by both route mounts. */
31
98
  export interface MountMcpRouteOptions {
99
+ /**
100
+ * Bind a bearer-authenticated principal around dispatch (see
101
+ * {@link McpPrincipalBinder}). The `smrtOptions` database thunk, task
102
+ * handling and tool execution all run inside the binding, and the response
103
+ * is fully materialized before it returns. A binder that throws before
104
+ * running dispatch, or returns without running it, yields HTTP 403 with the
105
+ * safe `mcp_tool_access_denied` JSON-RPC error. Scopes the binder hands
106
+ * back become the effective authority for the tool policy, so live
107
+ * revocation applies even without a database-enforced policy. Used only when `auth`
108
+ * authenticated the request; the session-locals path is unchanged.
109
+ */
110
+ bindPrincipal?: McpPrincipalBinder;
111
+ /**
112
+ * Refuse a modern-endpoint request whose `Origin` header is present but is
113
+ * neither the request URL's own origin nor in `trustedOrigins` (and, when
114
+ * `Origin` is absent, one whose `Sec-Fetch-Site` is `cross-site` or
115
+ * `same-site`). The check runs before bearer authentication, principal
116
+ * resolution and any task or tool dispatch, and answers 403 with the safe
117
+ * `mcp_origin_denied` JSON-RPC error. Requests without browser origin
118
+ * signals (server-side MCP clients, the `smrt-app-cli` stdio bridge) are
119
+ * unaffected. Off unless set for `mountMcpRoute`; on by default for
120
+ * `mountMcpAppRoute`. Ignored by the deprecated REST-shaped mounts.
121
+ */
122
+ checkOrigin?: boolean;
123
+ /**
124
+ * Additional exact origins (`scheme://host[:port]`) accepted by the origin
125
+ * check, e.g. a browser-hosted MCP client, or the public origin when a
126
+ * proxy makes `event.url` differ from what browsers send. `null`, wildcards,
127
+ * paths and credentials are rejected at mount time.
128
+ */
129
+ trustedOrigins?: readonly string[];
130
+ /**
131
+ * Optional bearer authentication for the modern `mountMcpRoute` endpoint.
132
+ * When the source yields an adapter, every request must carry a valid
133
+ * bearer token: a failed check returns the adapter's challenge response
134
+ * before any dispatch, and the adapter's mapped principal replaces the
135
+ * session principal (`resolvePrincipal` is not consulted). When it yields
136
+ * `null`, the route resolves its principal from the request as usual. A
137
+ * `sessionFallback` adapter (the local owner-token adapter) challenges only
138
+ * requests that carry an `Authorization` header; others keep the session
139
+ * principal. Ignored by the deprecated REST-shaped mounts.
140
+ */
141
+ auth?: McpRouteResourceAuthSource;
32
142
  /** Optional extension discovery projected from the request-authorized tool catalog. */
33
143
  extensions?: McpProtocolRequestOptions['extensions'];
34
144
  /**
@@ -54,6 +164,55 @@ export interface MountMcpRouteOptions {
54
164
  * route holds neither MCP sessions nor request principal state between nodes.
55
165
  */
56
166
  export declare function mountMcpRoute(server: McpAppServer, options?: MountMcpRouteOptions): McpSvelteKitHandler;
167
+ /** Options for {@link mountMcpAppRoute}. */
168
+ export interface MountMcpAppRouteOptions extends CreateDefaultMcpAppServerOptions, Pick<MountMcpRouteOptions, 'auth' | 'bindPrincipal' | 'extensions' | 'checkOrigin' | 'trustedOrigins'> {
169
+ /**
170
+ * Resolve the request principal when no bearer adapter is active. Defaults
171
+ * to {@link principalFromSessionLocals}.
172
+ */
173
+ resolvePrincipal?: McpPrincipalResolver;
174
+ }
175
+ /** A mounted app route; `server` is the policy core it serves. */
176
+ export type McpAppSvelteKitHandler = McpSvelteKitHandler & {
177
+ readonly server: McpAppServer;
178
+ };
179
+ /**
180
+ * One-call application MCP endpoint: the app's declared `models`, the default
181
+ * principal scope policy (see `createDefaultMcpAppServer`), principals from
182
+ * the SvelteKit session locals, and optional bearer authentication, mounted
183
+ * as the stateless {@link mountMcpRoute} `POST` endpoint. The origin check
184
+ * (`checkOrigin`) is on by default because the default principal is an
185
+ * ambient session cookie; set `trustedOrigins` for extra browser origins or
186
+ * `checkOrigin: false` to opt out.
187
+ *
188
+ * @example
189
+ * ```ts
190
+ * // src/routes/api/mcp/+server.ts
191
+ * import { mountMcpAppRoute } from '@happyvertical/smrt-app-mcp/sveltekit';
192
+ * import { Item } from '$lib/objects/Item';
193
+ * import { getDatabaseConfig } from '$lib/server/db';
194
+ *
195
+ * export const POST = mountMcpAppRoute({
196
+ * models: [Item],
197
+ * requiredScopes: ['items.read'],
198
+ * smrtOptions: () => ({ db: getDatabaseConfig() }),
199
+ * });
200
+ * ```
201
+ */
202
+ export declare function mountMcpAppRoute(options: MountMcpAppRouteOptions): McpAppSvelteKitHandler;
203
+ /**
204
+ * Mount the RFC 9728 protected-resource metadata document as a SvelteKit
205
+ * `GET` handler, at the exact `metadataUrl` path the bearer challenge
206
+ * advertises (for `/api/mcp`:
207
+ * `src/routes/.well-known/oauth-protected-resource/api/mcp/+server.ts`).
208
+ *
209
+ * Returns 404 when the source yields no adapter or the local owner-token
210
+ * adapter (the `local` profile), or when the request path is not the
211
+ * advertised metadata path. This handler does
212
+ * not implement an OAuth authorization server; the metadata names the
213
+ * operator-owned issuer.
214
+ */
215
+ export declare function mountMcpProtectedResourceMetadataRoute(auth: McpRouteResourceAuthSource): McpSvelteKitHandler;
57
216
  /**
58
217
  * Mount `server.listTools` as a `GET` handler. Returns the tool list shape
59
218
  * `{ tools }` for compatibility with the stock MCP bridge.
@@ -70,6 +229,7 @@ export declare function mountMcpToolsRoute(server: McpAppServer, options?: Mount
70
229
  * this compatibility alias while migrating without a coordinated cutover.
71
230
  */
72
231
  export declare function mountMcpCallRoute(server: McpAppServer, options?: MountMcpRouteOptions): McpSvelteKitHandler;
232
+ export type { CreateDefaultMcpAppServerOptions, McpAppModel, } from './defaults.js';
73
233
  export { McpAccessError } from './errors.js';
74
234
  export type { McpAppPrincipal, McpAppServer } from './server.js';
75
235
  //# sourceMappingURL=sveltekit.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sveltekit.d.ts","sourceRoot":"","sources":["../src/sveltekit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAQH,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAiB,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhF,oEAAoE;AACpE,KAAK,qBAAqB,GAAG;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,GAAG,CAAC;CACV,CAAC;AAEF,6EAA6E;AAC7E,MAAM,MAAM,mBAAmB,GAAG,CAChC,KAAK,EAAE,qBAAqB,KACzB,OAAO,CAAC,QAAQ,CAAC,CAAC;AAQvB,8EAA8E;AAC9E,MAAM,MAAM,oBAAoB,GAAG,CACjC,KAAK,EAAE,qBAAqB,KACzB,eAAe,GAAG,IAAI,GAAG,SAAS,CAAC;AAExC,6EAA6E;AAC7E,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAwCnD,2CAA2C;AAC3C,MAAM,WAAW,oBAAoB;IACnC,uFAAuF;IACvF,UAAU,CAAC,EAAE,yBAAyB,CAAC,YAAY,CAAC,CAAC;IACrD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;IACxC;;OAEG;IACH,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,OAAO,CAAC;CAClE;AAkBD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,oBAAyB,GACjC,mBAAmB,CA8BrB;AA6OD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,oBAAyB,GACjC,mBAAmB,CAcrB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,oBAAyB,GACjC,mBAAmB,CA0BrB;AAyBD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"sveltekit.d.ts","sourceRoot":"","sources":["../src/sveltekit.ts"],"names":[],"mappings":"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"}
package/dist/sveltekit.js CHANGED
@@ -1,4 +1,4 @@
1
- import { f as McpAccessError, r as createMcpProtocolServerForRequest, t as MCP_TASKS_EXTENSION } from "./chunks/protocol-Ce0U_XSp.js";
1
+ import { C as McpAccessError, S as MCP_TOOL_ACCESS_DENIED_CODE, a as createDefaultMcpAppServer, r as createMcpProtocolServerForRequest, t as MCP_TASKS_EXTENSION, x as MCP_ORIGIN_DENIED_CODE } from "./chunks/protocol-BlbEg3jn.js";
2
2
  import { classifyInboundRequest, createMcpHandler, isJsonContentType } from "@modelcontextprotocol/server";
3
3
  //#region src/sveltekit.ts
4
4
  var defaultResolvePrincipal = (event) => event.locals?.user ?? null;
@@ -17,6 +17,87 @@ function listToolsInput(resolved) {
17
17
  if (!resolved.principal && resolved.legacyAuthenticated) return { authenticated: true };
18
18
  return { principal: resolved.principal };
19
19
  }
20
+ function currentResourceAuth(source) {
21
+ return (typeof source === "function" ? source() : source) ?? null;
22
+ }
23
+ function canonicalOrigin(value) {
24
+ if (value === "null") return void 0;
25
+ let url;
26
+ try {
27
+ url = new URL(value);
28
+ } catch {
29
+ return;
30
+ }
31
+ if (url.protocol !== "https:" && url.protocol !== "http:") return void 0;
32
+ if (url.username || url.password || url.search || url.hash) return void 0;
33
+ if (url.pathname !== "/") return void 0;
34
+ return url.origin;
35
+ }
36
+ function normalizeTrustedOrigins(values) {
37
+ if (!Array.isArray(values)) throw new TypeError("MCP trustedOrigins must be an array of origins.");
38
+ const origins = /* @__PURE__ */ new Set();
39
+ for (const value of values) {
40
+ const origin = typeof value === "string" ? canonicalOrigin(value) : void 0;
41
+ if (!origin) throw new TypeError("Invalid MCP trusted origin.");
42
+ origins.add(origin);
43
+ }
44
+ return origins;
45
+ }
46
+ function originPermitted(event, trusted) {
47
+ const header = event.request.headers.get("origin");
48
+ if (header !== null) {
49
+ const origin = canonicalOrigin(header.trim());
50
+ return origin !== void 0 && (origin === event.url.origin || trusted.has(origin));
51
+ }
52
+ const site = event.request.headers.get("sec-fetch-site")?.trim().toLowerCase();
53
+ return site !== "cross-site" && site !== "same-site";
54
+ }
55
+ function originDeniedResponse() {
56
+ return new Response(JSON.stringify({
57
+ jsonrpc: "2.0",
58
+ id: null,
59
+ error: {
60
+ code: -32600,
61
+ message: "MCP request origin is not permitted.",
62
+ data: {
63
+ code: MCP_ORIGIN_DENIED_CODE,
64
+ retryable: false
65
+ }
66
+ }
67
+ }), {
68
+ status: 403,
69
+ headers: {
70
+ "content-type": "application/json",
71
+ "cache-control": "no-store"
72
+ }
73
+ });
74
+ }
75
+ function principalFromSessionLocals(event) {
76
+ const locals = event.locals;
77
+ if (!locals || typeof locals !== "object") return null;
78
+ const user = locals.user;
79
+ const tenantId = locals.tenantId;
80
+ const permissions = locals.permissions;
81
+ if (!user || typeof user !== "object") return null;
82
+ if (typeof user.id !== "string" || user.id.length === 0) return null;
83
+ if (typeof tenantId !== "string" || tenantId.length === 0) return null;
84
+ if (!Array.isArray(permissions) || !permissions.every((value) => typeof value === "string")) return null;
85
+ return {
86
+ id: user.id,
87
+ tenantId,
88
+ kind: "human",
89
+ scopes: [...permissions].sort()
90
+ };
91
+ }
92
+ function effectiveBoundPrincipal(authenticated, bound) {
93
+ if (bound === void 0) return authenticated;
94
+ if (!bound || typeof bound !== "object" || bound.id !== authenticated.id || (bound.tenantId ?? null) !== (authenticated.tenantId ?? null) || !Array.isArray(bound.scopes) || !bound.scopes.every((scope) => typeof scope === "string")) return;
95
+ const granted = new Set(bound.scopes);
96
+ return {
97
+ ...authenticated,
98
+ scopes: (authenticated.scopes ?? []).filter((scope) => granted.has(scope))
99
+ };
100
+ }
20
101
  function protocolServerForRequest(server, resolved) {
21
102
  if (!resolved.legacyAuthenticated || resolved.principal) return server;
22
103
  return {
@@ -27,8 +108,36 @@ function protocolServerForRequest(server, resolved) {
27
108
  };
28
109
  }
29
110
  function mountMcpRoute(server, options = {}) {
111
+ const trustedOrigins = options.checkOrigin ? normalizeTrustedOrigins(options.trustedOrigins ?? []) : void 0;
30
112
  return async (event) => {
31
- const resolved = resolveRequestPrincipal(event, options);
113
+ if (trustedOrigins && !originPermitted(event, trustedOrigins)) return originDeniedResponse();
114
+ const auth = currentResourceAuth(options.auth);
115
+ if (!auth) return dispatch(event, resolveRequestPrincipal(event, options));
116
+ if (auth.sessionFallback === true && !event.request.headers.has("authorization")) return dispatch(event, resolveRequestPrincipal(event, options));
117
+ const checked = await auth.authenticate(event.request);
118
+ if (!checked.ok) return checked.response;
119
+ if (!options.bindPrincipal) return dispatch(event, { principal: checked.principal });
120
+ let entered = false;
121
+ let response;
122
+ try {
123
+ response = await options.bindPrincipal(checked.principal, async (bound) => {
124
+ entered = true;
125
+ const principal = effectiveBoundPrincipal(checked.principal, bound);
126
+ if (!principal) return principalUnboundResponse();
127
+ const dispatched = await dispatch(event, { principal });
128
+ return new Response(await dispatched.arrayBuffer(), {
129
+ status: dispatched.status,
130
+ statusText: dispatched.statusText,
131
+ headers: dispatched.headers
132
+ });
133
+ });
134
+ } catch (error) {
135
+ if (entered) throw error;
136
+ return principalUnboundResponse();
137
+ }
138
+ return entered ? response : principalUnboundResponse();
139
+ };
140
+ async function dispatch(event, resolved) {
32
141
  const taskResponse = await maybeHandleTaskRequest(server, resolved.principal, event.request);
33
142
  if (taskResponse) return taskResponse;
34
143
  return createMcpHandler(() => createMcpProtocolServerForRequest(protocolServerForRequest(server, resolved), {
@@ -38,6 +147,52 @@ function mountMcpRoute(server, options = {}) {
38
147
  legacy: "reject",
39
148
  maxSubscriptions: 0
40
149
  }).fetch(event.request);
150
+ }
151
+ }
152
+ function principalUnboundResponse() {
153
+ return new Response(JSON.stringify({
154
+ jsonrpc: "2.0",
155
+ id: null,
156
+ error: {
157
+ code: -32600,
158
+ message: "MCP tool access is not permitted.",
159
+ data: {
160
+ code: MCP_TOOL_ACCESS_DENIED_CODE,
161
+ retryable: false
162
+ }
163
+ }
164
+ }), {
165
+ status: 403,
166
+ headers: {
167
+ "content-type": "application/json",
168
+ "cache-control": "no-store"
169
+ }
170
+ });
171
+ }
172
+ function mountMcpAppRoute(options) {
173
+ const { auth, bindPrincipal, extensions, resolvePrincipal, checkOrigin, trustedOrigins, ...serverOptions } = options;
174
+ const server = createDefaultMcpAppServer(serverOptions);
175
+ const handler = mountMcpRoute(server, {
176
+ auth,
177
+ bindPrincipal,
178
+ extensions,
179
+ checkOrigin: checkOrigin ?? true,
180
+ trustedOrigins,
181
+ resolvePrincipal: resolvePrincipal ?? principalFromSessionLocals
182
+ });
183
+ return Object.defineProperty(handler, "server", {
184
+ value: server,
185
+ enumerable: true
186
+ });
187
+ }
188
+ function mountMcpProtectedResourceMetadataRoute(auth) {
189
+ return async (event) => {
190
+ const current = currentResourceAuth(auth);
191
+ if (!current || current.sessionFallback === true || event.url.pathname !== new URL(current.metadataUrl).pathname) return new Response(null, {
192
+ status: 404,
193
+ headers: { "Cache-Control": "no-store" }
194
+ });
195
+ return current.metadataResponse();
41
196
  };
42
197
  }
43
198
  async function maybeHandleTaskRequest(server, principal, request) {
@@ -215,6 +370,6 @@ function jsonResponse(body, status = 200) {
215
370
  });
216
371
  }
217
372
  //#endregion
218
- export { McpAccessError, mountMcpCallRoute, mountMcpRoute, mountMcpToolsRoute };
373
+ export { McpAccessError, mountMcpAppRoute, mountMcpCallRoute, mountMcpProtectedResourceMetadataRoute, mountMcpRoute, mountMcpToolsRoute, principalFromSessionLocals };
219
374
 
220
375
  //# sourceMappingURL=sveltekit.js.map