@questpie/mcp 3.28.5 → 3.28.6

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.
@@ -237,6 +237,7 @@ function normalizePolicy(defaults, override) {
237
237
  workload: defaults.workload,
238
238
  operationWorkloads: { ...defaults.operationWorkloads ?? {} },
239
239
  fields: defaults.fields,
240
+ relationLoading: defaults.relationLoading,
240
241
  description: defaults.description
241
242
  };
242
243
  if (override === void 0) return base;
@@ -1244,6 +1245,7 @@ function toRequestContext(ctx, accessMode) {
1244
1245
  return {
1245
1246
  session: ctx.session,
1246
1247
  principal: ctx.principal,
1248
+ actor: ctx.actor,
1247
1249
  locale: ctx.locale,
1248
1250
  defaultLocale: ctx.defaultLocale,
1249
1251
  localeFallback: ctx.localeFallback,
@@ -1251,7 +1253,10 @@ function toRequestContext(ctx, accessMode) {
1251
1253
  stage: ctx.stage,
1252
1254
  requestId: ctx.requestId,
1253
1255
  traceId: ctx.traceId,
1256
+ workload: ctx.workload,
1257
+ logger: ctx.logger,
1254
1258
  db: ctx.db,
1259
+ request: ctx.request,
1255
1260
  "~contextExtensions": ctx["~contextExtensions"]
1256
1261
  };
1257
1262
  }
@@ -1555,7 +1560,12 @@ async function executeWorkloadTool(boundary, authorized, metadata, execution, in
1555
1560
  //#endregion
1556
1561
  //#region src/server/crud-tools.ts
1557
1562
  const idSchema = z.union([z.string(), z.number()]);
1558
- const deleteSchema = z.object({ id: idSchema }).strict();
1563
+ function optimisticConcurrencyEnabled(collection) {
1564
+ return collection.state?.options?.optimisticConcurrency === true;
1565
+ }
1566
+ function expectedRevisionShape(collection) {
1567
+ return optimisticConcurrencyEnabled(collection) ? { expectedRevision: z.number().int().min(1) } : {};
1568
+ }
1559
1569
  const MAX_QUERY_FIELDS = 64;
1560
1570
  const MAX_WHERE_DEPTH = 3;
1561
1571
  const MAX_LOGICAL_CLAUSES = 16;
@@ -1617,7 +1627,7 @@ function relationLoadSchema(relations) {
1617
1627
  function collectionReadSchemas(collection, policy) {
1618
1628
  const fields = allowedEntityFieldNames(collection, policy);
1619
1629
  const common = {
1620
- with: relationLoadSchema(allowedEntityRelationNames(collection, policy)).optional(),
1630
+ with: relationLoadSchema(policy.relationLoading === false ? [] : allowedEntityRelationNames(collection, policy)).optional(),
1621
1631
  columns: columnsSchema(fields).optional(),
1622
1632
  locale: z.string().max(64).optional(),
1623
1633
  includeDeleted: z.boolean().optional(),
@@ -1645,7 +1655,7 @@ function collectionReadSchemas(collection, policy) {
1645
1655
  function globalOperationBaseSchema(global, policy) {
1646
1656
  const fields = allowedEntityFieldNames(global, policy);
1647
1657
  return {
1648
- with: relationLoadSchema(allowedEntityRelationNames(global, policy)).optional(),
1658
+ with: relationLoadSchema(policy.relationLoading === false ? [] : allowedEntityRelationNames(global, policy)).optional(),
1649
1659
  columns: columnsSchema(fields).optional(),
1650
1660
  locale: z.string().max(64).optional(),
1651
1661
  stage: z.string().max(64).optional()
@@ -1656,10 +1666,14 @@ const COLLECTION_OPERATIONS = [
1656
1666
  name: "list",
1657
1667
  kind: "read",
1658
1668
  description: (name) => `List ${name} records.`,
1659
- execute: (crud, input, ctx, maxLimit) => crud.find({
1660
- ...input,
1661
- limit: Math.min(input.limit ?? maxLimit, maxLimit)
1662
- }, ctx)
1669
+ execute: (crud, input, ctx, maxLimit) => {
1670
+ const { sort, ...options } = input;
1671
+ return crud.find({
1672
+ ...options,
1673
+ ...sort === void 0 ? {} : { orderBy: sort },
1674
+ limit: Math.min(input.limit ?? maxLimit, maxLimit)
1675
+ }, ctx);
1676
+ }
1663
1677
  },
1664
1678
  {
1665
1679
  name: "count",
@@ -1691,14 +1705,18 @@ const COLLECTION_OPERATIONS = [
1691
1705
  description: (name) => `Update a ${name} record by id.`,
1692
1706
  execute: (crud, input, ctx) => crud.updateById({
1693
1707
  id: input.id,
1694
- data: input.data
1708
+ data: input.data,
1709
+ ...input.expectedRevision === void 0 ? {} : { expectedRevision: input.expectedRevision }
1695
1710
  }, ctx)
1696
1711
  },
1697
1712
  {
1698
1713
  name: "delete",
1699
1714
  kind: "delete",
1700
1715
  description: (name) => `Delete a ${name} record by id.`,
1701
- execute: (crud, input, ctx) => crud.deleteById({ id: input.id }, ctx)
1716
+ execute: (crud, input, ctx) => crud.deleteById({
1717
+ id: input.id,
1718
+ ...input.expectedRevision === void 0 ? {} : { expectedRevision: input.expectedRevision }
1719
+ }, ctx)
1702
1720
  }
1703
1721
  ];
1704
1722
  const GLOBAL_OPERATIONS = [{
@@ -1719,9 +1737,14 @@ function collectionOperationSchema(operationName, collection, policy) {
1719
1737
  if (operationName === "create") return z.object({ data: createCollectionDataSchema(collection, "create", policy) }).strict();
1720
1738
  if (operationName === "update") return z.object({
1721
1739
  id: idSchema,
1722
- data: createCollectionDataSchema(collection, "update", policy)
1740
+ data: createCollectionDataSchema(collection, "update", policy),
1741
+ ...expectedRevisionShape(collection)
1742
+ }).strict();
1743
+ if (operationName === "delete") return z.object({
1744
+ id: idSchema,
1745
+ ...expectedRevisionShape(collection)
1723
1746
  }).strict();
1724
- return collectionReadSchemas(collection, policy)[operationName] ?? deleteSchema;
1747
+ return collectionReadSchemas(collection, policy)[operationName];
1725
1748
  }
1726
1749
  function globalOperationSchema(operationName, global, policy) {
1727
1750
  if (operationName === "update") return z.object({
@@ -1732,13 +1755,10 @@ function globalOperationSchema(operationName, global, policy) {
1732
1755
  }
1733
1756
  async function questpieAllows(scope, ctx, kind, name, operationName) {
1734
1757
  if (scope.accessMode === "system") return true;
1735
- const crudContext = {
1736
- db: ctx.db ?? scope.app.db,
1737
- session: ctx.session,
1738
- locale: ctx.locale,
1739
- accessMode: scope.accessMode,
1740
- stage: ctx.stage
1741
- };
1758
+ const crudContext = toRequestContext({
1759
+ ...ctx,
1760
+ db: ctx.db ?? scope.app.db
1761
+ }, scope.accessMode);
1742
1762
  if (kind === "collection") {
1743
1763
  const collection = scope.app.getCollections()[name];
1744
1764
  const schema$1 = await introspectCollection(collection, crudContext, scope.app);
@@ -2039,24 +2059,18 @@ function executeResource(scope, operation, input, extra, invoke) {
2039
2059
  async function collectionSchema(scope, name) {
2040
2060
  const ctx = await scope.getContext();
2041
2061
  const collection = scope.app.getCollections()[name];
2042
- return introspectCollection(collection, {
2043
- db: ctx.db ?? scope.app.db,
2044
- session: ctx.session,
2045
- locale: ctx.locale,
2046
- accessMode: scope.accessMode,
2047
- stage: ctx.stage
2048
- }, scope.app);
2062
+ return introspectCollection(collection, toRequestContext({
2063
+ ...ctx,
2064
+ db: ctx.db ?? scope.app.db
2065
+ }, scope.accessMode), scope.app);
2049
2066
  }
2050
2067
  async function globalSchema(scope, name) {
2051
2068
  const ctx = await scope.getContext();
2052
2069
  const global = scope.app.getGlobals()[name];
2053
- return introspectGlobal(global, {
2054
- db: ctx.db ?? scope.app.db,
2055
- session: ctx.session,
2056
- locale: ctx.locale,
2057
- accessMode: scope.accessMode,
2058
- stage: ctx.stage
2059
- }, scope.app);
2070
+ return introspectGlobal(global, toRequestContext({
2071
+ ...ctx,
2072
+ db: ctx.db ?? scope.app.db
2073
+ }, scope.accessMode), scope.app);
2060
2074
  }
2061
2075
  async function visibleCollections(scope, catalog) {
2062
2076
  const entries = [];
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { n as mcpModule } from "./index-C3gm6ar5.mjs";
2
- import { A as McpWorkloadAuthorizer, B as WorkloadMcpServerOptions, C as McpToolConfig, D as McpWorkloadAuditEvent, E as McpTransportKind, F as McpWorkloadHandoffInput, I as McpWorkloadRequirement, L as McpWorkloadToolFacts, M as McpWorkloadContextBindingInput, N as McpWorkloadExecutionControl, O as McpWorkloadAuthorization, P as McpWorkloadHandoff, R as McpWorkloadToolKind, S as McpStdioConfig, T as McpToolHandlerArgs, _ as McpProgrammaticToolResult, a as McpAccessRule, b as McpResourcesConfig, c as McpCrudConfig, d as McpExecutionDiagnosticEvent, f as McpExecutionLimits, g as McpProgrammaticTool, h as McpProgrammaticRequestOptions, i as McpAccessMode, j as McpWorkloadContextBinder, k as McpWorkloadAuthorizationRequest, l as McpEntityPolicy, m as McpHttpConfig, n as QuestpieApp, o as McpAccessRuleContext, p as McpExecutionOptions, r as mcpPublicErrorCode, s as McpConfig, t as startStdioServer, u as McpExecutionConfig, v as McpPublicErrorCode, w as McpToolDefinition, x as McpRoutesConfig, y as McpRequiredScopes, z as McpWorkloadToolPort } from "./stdio-YoM70-42.mjs";
2
+ import { A as McpWorkloadAuthorizer, B as WorkloadMcpServerOptions, C as McpToolConfig, D as McpWorkloadAuditEvent, E as McpTransportKind, F as McpWorkloadHandoffInput, I as McpWorkloadRequirement, L as McpWorkloadToolFacts, M as McpWorkloadContextBindingInput, N as McpWorkloadExecutionControl, O as McpWorkloadAuthorization, P as McpWorkloadHandoff, R as McpWorkloadToolKind, S as McpStdioConfig, T as McpToolHandlerArgs, _ as McpProgrammaticToolResult, a as McpAccessRule, b as McpResourcesConfig, c as McpCrudConfig, d as McpExecutionDiagnosticEvent, f as McpExecutionLimits, g as McpProgrammaticTool, h as McpProgrammaticRequestOptions, i as McpAccessMode, j as McpWorkloadContextBinder, k as McpWorkloadAuthorizationRequest, l as McpEntityPolicy, m as McpHttpConfig, n as QuestpieApp, o as McpAccessRuleContext, p as McpExecutionOptions, r as mcpPublicErrorCode, s as McpConfig, t as startStdioServer, u as McpExecutionConfig, v as McpPublicErrorCode, w as McpToolDefinition, x as McpRoutesConfig, y as McpRequiredScopes, z as McpWorkloadToolPort } from "./stdio-C3663EKG.mjs";
3
3
  import { t as mcpPlugin } from "./plugin-CMR-wkeP.mjs";
4
4
  import { AppContext, Questpie, RequestContext, ScopeOperationKind, defaultOperationScope, introspectRoutes } from "questpie";
5
5
  import { z } from "zod";
@@ -30,6 +30,7 @@ interface ResolvedMcpPolicy {
30
30
  include?: string[];
31
31
  exclude?: string[];
32
32
  };
33
+ relationLoading?: boolean;
33
34
  description?: string;
34
35
  }
35
36
  /** Normalize an {@link McpRequiredScopes} declaration to a scope list. */
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import { S as scopesFromContext, _ as resolveMcpCatalog, a as customToolWorkloadIdentity, b as requiredScopesForOperation, c as createWorkloadMcpBoundary, f as McpAccessDeniedError, g as toMcpToolError, h as mcpPublicErrorCode, i as customToolDescriptor, l as createRuntimeScope, m as assertBoundedMcpValue, n as createWorkloadMcpServer, o as executeCustomToolCall, p as McpPublicError, r as customToolAllows, s as authorizeWorkload, t as createMcpServer, u as createWorkloadMcpRelease, v as defaultOperationScope, w as mcpTool, x as scopeGateAllows, y as normalizeRequiredScopes } from "./create-server-CEWFf041.mjs";
2
- import { n as mcp_default, t as mcpModule } from "./mcp-CLfbFUnD.mjs";
1
+ import { S as scopesFromContext, _ as resolveMcpCatalog, a as customToolWorkloadIdentity, b as requiredScopesForOperation, c as createWorkloadMcpBoundary, f as McpAccessDeniedError, g as toMcpToolError, h as mcpPublicErrorCode, i as customToolDescriptor, l as createRuntimeScope, m as assertBoundedMcpValue, n as createWorkloadMcpServer, o as executeCustomToolCall, p as McpPublicError, r as customToolAllows, s as authorizeWorkload, t as createMcpServer, u as createWorkloadMcpRelease, v as defaultOperationScope, w as mcpTool, x as scopeGateAllows, y as normalizeRequiredScopes } from "./create-server-Ty80vPGh.mjs";
2
+ import { n as mcp_default, t as mcpModule } from "./mcp-BVefYLQh.mjs";
3
3
  import { t as mcpPlugin } from "./plugin-BZQe1pji.mjs";
4
- import { t as startStdioServer } from "./stdio-CgIPiPUb.mjs";
4
+ import { t as startStdioServer } from "./stdio-CiEieZ1y.mjs";
5
5
  import { randomUUID } from "node:crypto";
6
6
 
7
7
  //#region src/server/workload-tool-port.ts
@@ -1,4 +1,4 @@
1
- import { C as validateMcpPrincipal, d as getAppMcpRelease, m as assertBoundedMcpValue, t as createMcpServer } from "./create-server-CEWFf041.mjs";
1
+ import { C as validateMcpPrincipal, d as getAppMcpRelease, m as assertBoundedMcpValue, t as createMcpServer } from "./create-server-Ty80vPGh.mjs";
2
2
  import { t as mcpPlugin } from "./plugin-BZQe1pji.mjs";
3
3
  import { route } from "questpie";
4
4
  import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
@@ -1,3 +1,3 @@
1
- import { t as mcpModule } from "../mcp-CLfbFUnD.mjs";
1
+ import { t as mcpModule } from "../mcp-BVefYLQh.mjs";
2
2
 
3
3
  export { mcpModule };
@@ -60,6 +60,8 @@ type McpEntityPolicy = boolean | {
60
60
  include?: string[];
61
61
  exclude?: string[];
62
62
  };
63
+ /** Allow callers to expand relation fields with `with`. Defaults to true. */
64
+ relationLoading?: boolean;
63
65
  description?: string;
64
66
  };
65
67
  interface McpCrudConfig {
@@ -1,4 +1,4 @@
1
- import { t as createMcpServer } from "./create-server-CEWFf041.mjs";
1
+ import { t as createMcpServer } from "./create-server-Ty80vPGh.mjs";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
3
 
4
4
  //#region src/server/stdio.ts
package/dist/stdio.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { t as startStdioServer } from "./stdio-YoM70-42.mjs";
1
+ import { t as startStdioServer } from "./stdio-C3663EKG.mjs";
2
2
  export { startStdioServer };
package/dist/stdio.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { t as startStdioServer } from "./stdio-CgIPiPUb.mjs";
1
+ import { t as startStdioServer } from "./stdio-CiEieZ1y.mjs";
2
2
 
3
3
  export { startStdioServer };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@questpie/mcp",
3
- "version": "3.28.5",
3
+ "version": "3.28.6",
4
4
  "description": "Model Context Protocol server for QUESTPIE apps, under the app's own access rules",
5
5
  "repository": {
6
6
  "type": "git",
@@ -70,7 +70,7 @@
70
70
  },
71
71
  "dependencies": {
72
72
  "@modelcontextprotocol/sdk": "^1.29.0",
73
- "questpie": "^3.28.5",
73
+ "questpie": "^3.28.6",
74
74
  "zod": "^4.2.1"
75
75
  },
76
76
  "devDependencies": {
@@ -80,6 +80,6 @@
80
80
  "tsdown": "^0.18.3"
81
81
  },
82
82
  "peerDependencies": {
83
- "questpie": "^3.28.5"
83
+ "questpie": "^3.28.6"
84
84
  }
85
85
  }