@classytic/arc 2.15.4 → 2.16.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.
Files changed (158) hide show
  1. package/README.md +1 -0
  2. package/bin/arc.js +12 -0
  3. package/dist/{BaseController-dx3m2J8V.mjs → BaseController-DlCCTIxJ.mjs} +61 -19
  4. package/dist/{HookSystem-Iiebom92.mjs → HookSystem-Cmf7-Etp.mjs} +8 -4
  5. package/dist/{QueryCache-D41bfdBB.d.mts → QueryCache-SvmT_9ti.d.mts} +1 -1
  6. package/dist/{ResourceRegistry-CTERg_2x.mjs → ResourceRegistry-f48hFk3m.mjs} +52 -9
  7. package/dist/audit/index.d.mts +1 -1
  8. package/dist/audit/index.mjs +4 -2
  9. package/dist/auth/index.d.mts +4 -4
  10. package/dist/auth/index.mjs +4 -4
  11. package/dist/auth/redis-session.d.mts +1 -1
  12. package/dist/{betterAuthOpenApi--M_i87dQ.mjs → betterAuthOpenApi-ClWxaceA.mjs} +10 -6
  13. package/dist/buildHandler-BZX6zzDM.mjs +300 -0
  14. package/dist/cache/index.d.mts +3 -3
  15. package/dist/cache/index.mjs +3 -3
  16. package/dist/{caching-SM8gghN6.mjs → caching-TeHE8G-v.mjs} +1 -1
  17. package/dist/cli/commands/describe.d.mts +35 -1
  18. package/dist/cli/commands/describe.mjs +52 -12
  19. package/dist/cli/commands/docs.d.mts +1 -4
  20. package/dist/cli/commands/docs.mjs +4 -16
  21. package/dist/cli/commands/generate.d.mts +2 -20
  22. package/dist/cli/commands/generate.mjs +1 -546
  23. package/dist/cli/commands/init.d.mts +2 -40
  24. package/dist/cli/commands/init.mjs +1 -3045
  25. package/dist/cli/commands/introspect.mjs +53 -64
  26. package/dist/cli/index.d.mts +2 -2
  27. package/dist/cli/index.mjs +2 -2
  28. package/dist/{constants-Cxde4rpC.mjs → constants-TrJVIJl0.mjs} +7 -0
  29. package/dist/core/index.d.mts +3 -3
  30. package/dist/core/index.mjs +5 -5
  31. package/dist/{core-CvmOqEms.mjs → core-DBJ_j6rX.mjs} +222 -44
  32. package/dist/createActionRouter-DUpN3Dd1.mjs +288 -0
  33. package/dist/{createAggregationRouter-B0bPDf5b.mjs → createAggregationRouter-Dq-TUCuY.mjs} +3 -2
  34. package/dist/{createApp-PFegs47-.mjs → createApp-DNccuhyI.mjs} +16 -14
  35. package/dist/{defineEvent-D5h7EvAx.mjs → defineEvent-DRwY0fYm.mjs} +1 -1
  36. package/dist/docs/index.d.mts +2 -2
  37. package/dist/docs/index.mjs +1 -1
  38. package/dist/{errorHandler-Bk-AGhkU.mjs → errorHandler-DpoXQHZ9.mjs} +17 -14
  39. package/dist/errors-C1lX_jlm.d.mts +91 -0
  40. package/dist/{eventPlugin-CaKTYkYM.mjs → eventPlugin-C2cGqtRO.mjs} +1 -1
  41. package/dist/{eventPlugin-qXpqTebY.d.mts → eventPlugin-CtHC_av1.d.mts} +1 -1
  42. package/dist/events/index.d.mts +3 -3
  43. package/dist/events/index.mjs +5 -5
  44. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  45. package/dist/events/transports/redis.d.mts +1 -1
  46. package/dist/factory/index.d.mts +1 -1
  47. package/dist/factory/index.mjs +2 -2
  48. package/dist/{fields-COhcH3fk.d.mts → fields-Anj0xdih.d.mts} +1 -1
  49. package/dist/generate-BWFwgcCM.d.mts +38 -0
  50. package/dist/generate-CYac-OLv.mjs +654 -0
  51. package/dist/hooks/index.d.mts +1 -1
  52. package/dist/hooks/index.mjs +1 -1
  53. package/dist/idempotency/index.d.mts +2 -2
  54. package/dist/idempotency/index.mjs +1 -1
  55. package/dist/idempotency/redis.d.mts +1 -1
  56. package/dist/{index-BTqLEvhu.d.mts → index-3oIimXQn.d.mts} +12 -12
  57. package/dist/{index-BstGxcc3.d.mts → index-B-ulKx5P.d.mts} +55 -4
  58. package/dist/{index-BswOSJCE.d.mts → index-CkW0flkU.d.mts} +355 -16
  59. package/dist/index.d.mts +6 -6
  60. package/dist/index.mjs +7 -8
  61. package/dist/init-Dv71MsJr.d.mts +71 -0
  62. package/dist/init-HDvoO9L5.mjs +3098 -0
  63. package/dist/integrations/event-gateway.d.mts +2 -2
  64. package/dist/integrations/event-gateway.mjs +1 -1
  65. package/dist/integrations/index.d.mts +2 -2
  66. package/dist/integrations/jobs.mjs +3 -3
  67. package/dist/integrations/mcp/index.d.mts +239 -7
  68. package/dist/integrations/mcp/index.mjs +2 -528
  69. package/dist/integrations/mcp/testing.d.mts +2 -2
  70. package/dist/integrations/mcp/testing.mjs +6 -10
  71. package/dist/integrations/streamline.mjs +26 -1
  72. package/dist/integrations/websocket-redis.d.mts +1 -1
  73. package/dist/integrations/websocket.d.mts +1 -1
  74. package/dist/integrations/websocket.mjs +1 -0
  75. package/dist/loadResourcesFromEntry-BLMEI2Xa.mjs +51 -0
  76. package/dist/{resourceToTools-tFYUNmM0.mjs → mcpPlugin-7vGV51ED.mjs} +1021 -318
  77. package/dist/{memory-UBydS5ku.mjs → memory-QOLe11D5.mjs} +2 -0
  78. package/dist/middleware/index.d.mts +1 -1
  79. package/dist/middleware/index.mjs +1 -1
  80. package/dist/{openapi-BHXhoX8O.mjs → openapi-34T9yNwd.mjs} +47 -36
  81. package/dist/permissions/index.d.mts +2 -2
  82. package/dist/permissions/index.mjs +1 -1
  83. package/dist/{permissions-ohQyv50e.mjs → permissions-CTxMrreC.mjs} +2 -2
  84. package/dist/{pipe-Zr0KXjQe.mjs → pipe-DiCyvyPN.mjs} +1 -0
  85. package/dist/pipeline/index.d.mts +1 -1
  86. package/dist/pipeline/index.mjs +1 -1
  87. package/dist/plugins/index.d.mts +5 -5
  88. package/dist/plugins/index.mjs +10 -10
  89. package/dist/plugins/response-cache.mjs +5 -5
  90. package/dist/plugins/tracing-entry.d.mts +1 -1
  91. package/dist/plugins/tracing-entry.mjs +1 -1
  92. package/dist/{pluralize-DQgqgifU.mjs → pluralize-B9M8xvy-.mjs} +2 -1
  93. package/dist/presets/filesUpload.d.mts +4 -4
  94. package/dist/presets/filesUpload.mjs +2 -2
  95. package/dist/presets/index.d.mts +1 -1
  96. package/dist/presets/index.mjs +1 -1
  97. package/dist/presets/multiTenant.d.mts +1 -1
  98. package/dist/presets/multiTenant.mjs +4 -3
  99. package/dist/presets/search.d.mts +2 -2
  100. package/dist/presets/search.mjs +1 -1
  101. package/dist/{presets-BbkjdPeH.mjs → presets-C9BE6WaZ.mjs} +2 -2
  102. package/dist/{queryCachePlugin-m1XsgAIJ.mjs → queryCachePlugin-B4XMSSe7.mjs} +2 -2
  103. package/dist/{queryCachePlugin-CqMdLI2-.d.mts → queryCachePlugin-Biqzfbi5.d.mts} +2 -2
  104. package/dist/{redis-DiMkdHEl.d.mts → redis-Cyzrz6SX.d.mts} +1 -1
  105. package/dist/{redis-stream-D6HzR1Z_.d.mts → redis-stream-DT-YjzrB.d.mts} +1 -1
  106. package/dist/registry/index.d.mts +319 -2
  107. package/dist/registry/index.mjs +3 -3
  108. package/dist/registry-BBE23CDj.mjs +576 -0
  109. package/dist/{routerShared-DrOa-26E.mjs → routerShared-CZV5aabX.mjs} +3 -3
  110. package/dist/scope/index.d.mts +3 -3
  111. package/dist/scope/index.mjs +3 -3
  112. package/dist/{sse-Bz-5ZeTt.mjs → sse-BY6sTy4P.mjs} +1 -1
  113. package/dist/testing/index.d.mts +2 -2
  114. package/dist/testing/index.mjs +16 -7
  115. package/dist/testing/storageContract.d.mts +1 -1
  116. package/dist/types/index.d.mts +5 -5
  117. package/dist/types/storage.d.mts +1 -1
  118. package/dist/{types-C_s5moIu.mjs → types-Bi0r0vjG.mjs} +53 -1
  119. package/dist/{types-BQsjgQzS.d.mts → types-BsJMEQ4D.d.mts} +106 -12
  120. package/dist/{types-DrBaUwyV.d.mts → types-D-fYtKjb.d.mts} +33 -10
  121. package/dist/{types-CTYvcwHe.d.mts → types-DVfpSfx2.d.mts} +42 -1
  122. package/dist/utils/index.d.mts +1286 -2
  123. package/dist/utils/index.mjs +1 -1
  124. package/dist/{utils-_h9B3c57.mjs → utils-DC5ycPfr.mjs} +89 -40
  125. package/dist/{buildHandler-CcFOpJLh.mjs → validate-By96rH0r.mjs} +8 -299
  126. package/dist/{versioning-hmkPcDlX.d.mts → versioning-ZwX9tmbS.d.mts} +1 -1
  127. package/package.json +21 -28
  128. package/skills/arc/SKILL.md +300 -706
  129. package/skills/arc/references/auth.md +19 -7
  130. package/skills/arc-code-review/SKILL.md +1 -1
  131. package/skills/arc-code-review/references/arc-cheatsheet.md +100 -322
  132. package/dist/createActionRouter-S3MLVYot.mjs +0 -220
  133. package/dist/index-bRjYu21O.d.mts +0 -1320
  134. package/dist/org/index.d.mts +0 -66
  135. package/dist/org/index.mjs +0 -486
  136. package/dist/org/types.d.mts +0 -82
  137. package/dist/org/types.mjs +0 -1
  138. package/dist/registry-I-ogLgL9.mjs +0 -46
  139. /package/dist/{EventTransport-CT_52aWU.d.mts → EventTransport-C-2oAHtw.d.mts} +0 -0
  140. /package/dist/{EventTransport-DLWoUMHy.mjs → EventTransport-Hxvv5QQz.mjs} +0 -0
  141. /package/dist/{actionPermissions-CyUkQu6O.mjs → actionPermissions-Bjmvn7Eb.mjs} +0 -0
  142. /package/dist/{elevation-BXOWoGCF.d.mts → elevation-0YBpa663.d.mts} +0 -0
  143. /package/dist/{elevation-DgoeTyfX.mjs → elevation-Dci0AYLT.mjs} +0 -0
  144. /package/dist/{errorHandler-DFr45ZG4.d.mts → errorHandler-mHuyWzZE.d.mts} +0 -0
  145. /package/dist/{externalPaths-BD5nw6St.d.mts → externalPaths-DFg-2KTp.d.mts} +0 -0
  146. /package/dist/{interface-beEtJyWM.d.mts → interface-CH0OQudo.d.mts} +0 -0
  147. /package/dist/{interface-DfLGcus7.d.mts → interface-NwJ_qPlY.d.mts} +0 -0
  148. /package/dist/{keys-CGcCbNyu.mjs → keys-DopsCuyQ.mjs} +0 -0
  149. /package/dist/{loadResources-DBMQg_Aj.mjs → loadResources-ChQEj8ih.mjs} +0 -0
  150. /package/dist/{metrics-Qnvwc-LQ.mjs → metrics-TuOmguhi.mjs} +0 -0
  151. /package/dist/{replyHelpers-CK-FNO8E.mjs → replyHelpers-C-gD32oF.mjs} +0 -0
  152. /package/dist/{schemaIR-lYhC2gE5.mjs → schemaIR-Ctc89DSn.mjs} +0 -0
  153. /package/dist/{sessionManager-C4Le_UB3.d.mts → sessionManager-BqFegc0W.d.mts} +0 -0
  154. /package/dist/{storage-Dfzt4VTl.d.mts → storage-D2KZJAmn.d.mts} +0 -0
  155. /package/dist/{store-helpers-BkIN9-vu.mjs → store-helpers-B0sunfZZ.mjs} +0 -0
  156. /package/dist/{tracing-QJVprktp.d.mts → tracing-Dm8n7Cnn.d.mts} +0 -0
  157. /package/dist/{versioning-BUrT5aP4.mjs → versioning-B6mimogM.mjs} +0 -0
  158. /package/dist/{websocket-ChC2rqe1.d.mts → websocket-BkjeGZRn.d.mts} +0 -0
@@ -1,5 +1,5 @@
1
- import { n as DomainEvent } from "../EventTransport-CT_52aWU.mjs";
2
- import { a as WebSocketMessage, i as WebSocketClient } from "../websocket-ChC2rqe1.mjs";
1
+ import { n as DomainEvent } from "../EventTransport-C-2oAHtw.mjs";
2
+ import { a as WebSocketMessage, i as WebSocketClient } from "../websocket-BkjeGZRn.mjs";
3
3
  import { FastifyPluginAsync, FastifyRequest } from "fastify";
4
4
 
5
5
  //#region src/integrations/event-gateway.d.ts
@@ -4,7 +4,7 @@ const eventGatewayPluginImpl = async (fastify, opts = {}) => {
4
4
  const { auth = true, orgScoped = false, roomPolicy, maxMessageBytes, maxSubscriptionsPerClient, authenticate } = opts;
5
5
  if (auth && !authenticate && !fastify.hasDecorator("authenticate")) throw new Error("[arc-event-gateway] auth is true but fastify.authenticate is not registered. Register an auth plugin first, provide a custom authenticate function, or set auth: false.");
6
6
  if (opts.sse !== false) {
7
- const { default: ssePlugin } = await import("../sse-Bz-5ZeTt.mjs").then((n) => n.r);
7
+ const { default: ssePlugin } = await import("../sse-BY6sTy4P.mjs").then((n) => n.r);
8
8
  await fastify.register(ssePlugin, {
9
9
  path: opts.sse?.path ?? "/events/stream",
10
10
  requireAuth: auth,
@@ -1,7 +1,7 @@
1
- import { a as WebSocketMessage, i as WebSocketClient, o as WebSocketPluginOptions } from "../websocket-ChC2rqe1.mjs";
1
+ import { a as WebSocketMessage, i as WebSocketClient, o as WebSocketPluginOptions } from "../websocket-BkjeGZRn.mjs";
2
2
  import { EventGatewayOptions } from "./event-gateway.mjs";
3
3
  import { JobDefinition, JobDispatchOptions, JobDispatcher, JobMeta, JobsPluginOptions, QueueStats } from "./jobs.mjs";
4
- import { c as McpResourceConfig, f as ToolAnnotations, i as CrudOperation, l as PromptDefinition, m as ToolDefinition, n as CallToolResult, o as McpAuthResult, p as ToolContext, r as CreateMcpServerConfig, s as McpPluginOptions, t as BetterAuthHandler } from "../types-BQsjgQzS.mjs";
4
+ import { c as McpAuthResult, d as PromptDefinition, g as ToolDefinition, h as ToolContext, l as McpPluginOptions, m as ToolAnnotations, n as CallToolResult, o as CrudOperation, r as CreateMcpServerConfig, t as BetterAuthHandler, u as McpResourceConfig } from "../types-BsJMEQ4D.mjs";
5
5
  import { StreamlinePluginOptions, WorkflowLike, WorkflowRunLike } from "./streamline.mjs";
6
6
  import { WebhookDeliveryRecord, WebhookManager, WebhookPluginOptions, WebhookStore, WebhookSubscription } from "./webhooks.mjs";
7
7
  export { type BetterAuthHandler, type CallToolResult, type CreateMcpServerConfig, type CrudOperation, type EventGatewayOptions, type JobDefinition, type JobDispatchOptions, type JobDispatcher, type JobMeta, type JobsPluginOptions, type McpAuthResult, type McpPluginOptions, type McpResourceConfig, type PromptDefinition, type QueueStats, type StreamlinePluginOptions, type ToolAnnotations, type ToolContext, type ToolDefinition, type WebSocketClient, type WebSocketMessage, type WebSocketPluginOptions, type WebhookDeliveryRecord, type WebhookManager, type WebhookPluginOptions, type WebhookStore, type WebhookSubscription, type WorkflowLike, type WorkflowRunLike };
@@ -68,8 +68,8 @@ const jobsPluginImpl = async (fastify, options) => {
68
68
  const jobTimeout = job.timeout ?? defaults.timeout;
69
69
  const worker = new Worker(queueName, async (bullJob) => {
70
70
  const meta = {
71
- jobId: bullJob.id,
72
- attemptsMade: bullJob.attemptsMade,
71
+ jobId: bullJob.id ?? "",
72
+ attemptsMade: bullJob.attemptsMade ?? 0,
73
73
  timestamp: Date.now()
74
74
  };
75
75
  let result;
@@ -107,7 +107,7 @@ const jobsPluginImpl = async (fastify, options) => {
107
107
  });
108
108
  worker.on("failed", async (bullJob, error) => {
109
109
  const maxAttempts = job.retries ?? defaults.retries ?? 3;
110
- if (dlqQueue && bullJob && bullJob.attemptsMade >= maxAttempts) try {
110
+ if (dlqQueue && bullJob && (bullJob.attemptsMade ?? 0) >= maxAttempts) try {
111
111
  await dlqQueue.add(`${queueName}:dead`, bullJob.data, {
112
112
  jobId: `${bullJob.id}:dlq`,
113
113
  removeOnComplete: false
@@ -1,5 +1,8 @@
1
- import { V as ResourceDefinition } from "../../index-BswOSJCE.mjs";
2
- import { a as McpAuthResolver, c as McpResourceConfig, d as SessionEntry, f as ToolAnnotations, i as CrudOperation, l as PromptDefinition, m as ToolDefinition, n as CallToolResult, o as McpAuthResult, p as ToolContext, r as CreateMcpServerConfig, s as McpPluginOptions, t as BetterAuthHandler, u as PromptResult } from "../../types-BQsjgQzS.mjs";
1
+ import { V as ResourceDefinition, bt as IRequestContext, yt as IControllerResponse } from "../../index-CkW0flkU.mjs";
2
+ import { i as RequestScope } from "../../types-DVfpSfx2.mjs";
3
+ import { c as PermissionCheck } from "../../fields-Anj0xdih.mjs";
4
+ import { a as CrudDescriptionOverride, c as McpAuthResult, d as PromptDefinition, f as PromptResult, g as ToolDefinition, h as ToolContext, i as CrudDescriptionMeta, l as McpPluginOptions, m as ToolAnnotations, n as CallToolResult, o as CrudOperation, p as SessionEntry, r as CreateMcpServerConfig, s as McpAuthResolver, t as BetterAuthHandler, u as McpResourceConfig } from "../../types-BsJMEQ4D.mjs";
5
+ import { ErrorContract } from "@classytic/repo-core/errors";
3
6
  import { FastifyPluginAsync } from "fastify";
4
7
  import { z } from "zod";
5
8
 
@@ -74,6 +77,30 @@ interface McpServerInstance {
74
77
  resource: (...args: unknown[]) => void;
75
78
  }
76
79
  //#endregion
80
+ //#region src/integrations/mcp/crud-tools.d.ts
81
+ /**
82
+ * Default description for a CRUD tool. Enriches list descriptions with the
83
+ * configured filter/sort metadata so MCP clients can see what's queryable
84
+ * without reading the resource source.
85
+ *
86
+ * Exposed publicly so authors using the function-form `descriptions`
87
+ * override can call this from their own override to keep the auto-derived
88
+ * blurb intact and only append extra context.
89
+ */
90
+ declare function defaultCrudDescription(op: CrudOperation, displayName: string, softDelete: boolean, queryMeta?: {
91
+ filterableFields?: readonly string[];
92
+ allowedOperators?: readonly string[];
93
+ sortableFields?: readonly string[];
94
+ }): string;
95
+ /**
96
+ * Resolve a {@link CrudDescriptionOverride} (string or function) into a
97
+ * concrete description. Centralises the function-form contract so every
98
+ * call site that consumes an override applies it the same way.
99
+ *
100
+ * Falls back to {@link defaultCrudDescription} when no override is set.
101
+ */
102
+ declare function resolveCrudDescription(override: CrudDescriptionOverride | undefined, meta: CrudDescriptionMeta): string;
103
+ //#endregion
77
104
  //#region src/integrations/mcp/definePrompt.d.ts
78
105
  /** definePrompt() config */
79
106
  interface DefinePromptConfig<TArgs extends Record<string, z.ZodTypeAny>> {
@@ -92,8 +119,15 @@ interface DefinePromptConfig<TArgs extends Record<string, z.ZodTypeAny>> {
92
119
  declare function definePrompt<TArgs extends Record<string, z.ZodTypeAny>>(name: string, config: DefinePromptConfig<TArgs>): PromptDefinition;
93
120
  //#endregion
94
121
  //#region src/integrations/mcp/defineTool.d.ts
95
- /** defineTool() config — uses flat Zod shapes for SDK compatibility */
96
- interface DefineToolConfig<TInput extends Record<string, z.ZodTypeAny>> {
122
+ /**
123
+ * defineTool() config — uses flat Zod shapes for SDK compatibility.
124
+ *
125
+ * The `TSession` parameter widens `ctx.session` to a host-specific shape.
126
+ * Pass an interface that extends `McpAuthResult` (or one that omits it
127
+ * entirely for custom auth resolvers) to drop the `as any` casts that
128
+ * pre-2.15.5 handlers needed when reading session fields.
129
+ */
130
+ interface DefineToolConfig<TInput extends Record<string, z.ZodTypeAny>, TSession = McpAuthResult> {
97
131
  description: string;
98
132
  title?: string;
99
133
  /** Flat Zod shape: `{ name: z.string(), age: z.number() }` */
@@ -101,7 +135,7 @@ interface DefineToolConfig<TInput extends Record<string, z.ZodTypeAny>> {
101
135
  /** Flat Zod shape for structured output */
102
136
  output?: Record<string, z.ZodTypeAny>;
103
137
  annotations?: ToolAnnotations;
104
- handler: (input: { [K in keyof TInput]: z.infer<TInput[K]> }, ctx: ToolContext) => Promise<CallToolResult>;
138
+ handler: (input: { [K in keyof TInput]: z.infer<TInput[K]> }, ctx: ToolContext<TSession>) => Promise<CallToolResult>;
105
139
  }
106
140
  /**
107
141
  * Define a type-safe MCP tool.
@@ -109,7 +143,7 @@ interface DefineToolConfig<TInput extends Record<string, z.ZodTypeAny>> {
109
143
  * @param name - Tool name (snake_case recommended)
110
144
  * @param config - Tool description, input schema, annotations, handler
111
145
  */
112
- declare function defineTool<TInput extends Record<string, z.ZodTypeAny>>(name: string, config: DefineToolConfig<TInput>): ToolDefinition;
146
+ declare function defineTool<TInput extends Record<string, z.ZodTypeAny>, TSession = McpAuthResult>(name: string, config: DefineToolConfig<TInput, TSession>): ToolDefinition<TSession>;
113
147
  //#endregion
114
148
  //#region src/integrations/mcp/fieldRulesToZod.d.ts
115
149
  interface FieldRulesToZodOptions {
@@ -202,6 +236,121 @@ declare function requireOrgId(orgId: string): McpGuard;
202
236
  */
203
237
  declare function customGuard(check: (ctx: ToolContext) => boolean | Promise<boolean>, errorMessage: string): McpGuard;
204
238
  //#endregion
239
+ //#region src/integrations/mcp/buildRequestContext.d.ts
240
+ type McpOperation = "list" | "get" | "create" | "update" | "delete" | "action";
241
+ /**
242
+ * Build an IRequestContext from MCP tool input and session auth.
243
+ *
244
+ * | Operation | params | query | body |
245
+ * |-----------|------------|----------------------|---------------------|
246
+ * | list | {} | all input fields | undefined |
247
+ * | get | { id } | {} | undefined |
248
+ * | create | {} | {} | all input fields |
249
+ * | update | { id } | {} | input minus id |
250
+ * | delete | { id } | {} | undefined |
251
+ *
252
+ * **scopeOverride** — when a permission check (e.g. `requireApiKey()`) returns
253
+ * `PermissionResult.scope`, the MCP tool handler must install it on the request
254
+ * context the same way CRUD/action routes do. This parameter follows the exact
255
+ * same non-downgrade rule as `applyPermissionResult`: it overrides only when
256
+ * the session-derived scope is `public` (i.e. MCP called with `auth: false`).
257
+ * An authenticated session scope is never overwritten.
258
+ */
259
+ declare function buildRequestContext(input: Record<string, unknown>, auth: McpAuthResult | null, operation: McpOperation, policyFilters?: Record<string, unknown>, scopeOverride?: RequestScope): IRequestContext;
260
+ //#endregion
261
+ //#region src/integrations/mcp/invokeController.d.ts
262
+ /**
263
+ * Options threaded into {@link invokeController}. `session` is required so
264
+ * permission checks and scope resolution can both honor the caller's
265
+ * identity; everything else is optional and falls back to sensible defaults.
266
+ */
267
+ interface InvokeControllerOptions {
268
+ /** Resolved identity for this invocation — `null` runs as public scope. */
269
+ readonly session: McpAuthResult | null;
270
+ /** Resource name surfaced into the permission context (`PermissionContext.resource`). */
271
+ readonly resourceName: string;
272
+ /**
273
+ * Logical action name surfaced into the permission context
274
+ * (`PermissionContext.action`). Defaults to `op` — pass a distinct name
275
+ * for custom routes / declarative actions to keep audit logs readable.
276
+ */
277
+ readonly actionName?: string;
278
+ /**
279
+ * Permission to evaluate before invoking the controller. `undefined` means
280
+ * "no gate" — same semantics as CRUD without a declared `permissions.<op>`.
281
+ * Authors that want fail-closed behavior should pass `requireAuth()` or a
282
+ * concrete role gate; `allowPublic()` documents an intentional opt-out.
283
+ */
284
+ readonly permissions?: PermissionCheck;
285
+ /**
286
+ * Method name on the controller. Defaults to `op`. Override for custom-route
287
+ * dispatch where the method name differs from the MCP operation (e.g. an
288
+ * action handler reached through a `string` route handler).
289
+ */
290
+ readonly methodName?: string;
291
+ }
292
+ /**
293
+ * Invoke a controller method through the MCP synthetic-context path.
294
+ *
295
+ * Runs the same chain CRUD MCP tools run:
296
+ * 1. {@link evaluatePermission} — fails with the canonical
297
+ * `arc.unauthorized` / `arc.forbidden` `CallToolResult` shape on denial.
298
+ * 2. {@link buildRequestContext} — projects MCP input + session into
299
+ * `IRequestContext`. Permission `filters` / `scope` thread through
300
+ * identically to CRUD/action routes.
301
+ * 3. `controller[methodName](ctx)` — dispatch. Errors are routed through
302
+ * `toCallToolError` so `ArcError` / `HttpError` throws land as the same
303
+ * `ErrorContract` shape an HTTP client would see.
304
+ *
305
+ * @example Run a controller op from a custom MCP tool.
306
+ * ```ts
307
+ * defineTool('promote_post', {
308
+ * description: 'Promote a draft to published',
309
+ * inputSchema: { id: z.string() },
310
+ * handler: (input, ctx) =>
311
+ * invokeController(postController, 'update', { ...input, status: 'published' }, {
312
+ * session: ctx.session,
313
+ * resourceName: 'post',
314
+ * permissions: requireRoles(['editor']),
315
+ * }),
316
+ * });
317
+ * ```
318
+ *
319
+ * Workflow / scheduled-job callers pass a synthetic `session` they
320
+ * constructed from the job's owning identity — the shape is the same
321
+ * `McpAuthResult` the HTTP MCP plugin produces, so the same permission
322
+ * checks compose.
323
+ */
324
+ declare function invokeController(controller: unknown, op: McpOperation, input: Record<string, unknown>, options: InvokeControllerOptions): Promise<CallToolResult>;
325
+ /**
326
+ * Wrap an async function as a {@link ToolDefinition} handler — handles the
327
+ * try/catch → canonical-error translation in one place so MCP tools that
328
+ * compose multiple internal calls don't reimplement the boilerplate.
329
+ *
330
+ * The wrapped function may return:
331
+ * - A `CallToolResult` — passed through unchanged (use this to short-circuit
332
+ * with `permissionDeniedResult` or a custom error shape).
333
+ * - An `IControllerResponse` envelope (`{ data, meta?, status?, headers? }`)
334
+ * — serialised via `toCallToolResult` so pagination meta etc. survive.
335
+ * - Any other value — serialised as JSON via `toCallToolSuccess` semantics.
336
+ *
337
+ * Errors raised inside the function are caught and routed through
338
+ * `toCallToolError`, so `ArcError` / `HttpError` throws collapse to the
339
+ * canonical `ErrorContract` shape MCP agents see for every other surface.
340
+ *
341
+ * @example Compose two controller calls in one tool.
342
+ * ```ts
343
+ * defineTool('archive_and_log', {
344
+ * description: '...',
345
+ * handler: mcpHandlerAdapter(async (input, ctx) => {
346
+ * await invokeController(postController, 'update', { ...input, archived: true }, opts);
347
+ * return invokeController(auditController, 'create', { event: 'archive', ...input }, opts);
348
+ * }),
349
+ * });
350
+ * ```
351
+ */
352
+ declare function mcpHandlerAdapter<TSession = McpAuthResult>(fn: (input: Record<string, unknown>, ctx: ToolContext<TSession>) => Promise<unknown>): ToolDefinition<TSession>["handler"];
353
+ //#endregion
205
354
  //#region src/integrations/mcp/sessionCache.d.ts
206
355
  declare class McpSessionCache {
207
356
  private sessions;
@@ -261,6 +410,37 @@ declare module "fastify" {
261
410
  mcp?: McpDecorator;
262
411
  }
263
412
  }
413
+ interface ResourceFilterInputs {
414
+ readonly expose?: readonly string[];
415
+ readonly include?: readonly string[];
416
+ readonly exclude?: readonly string[];
417
+ }
418
+ /**
419
+ * Resolve `expose` / `include` / `exclude` into the filtered resource list
420
+ * `mcpPlugin` should surface. Three mutually exclusive intents:
421
+ *
422
+ * - `expose`: default-deny allowlist (preferred — new resources auto-deny).
423
+ * - `include`: legacy alias for `expose`, kept for back-compat.
424
+ * - `exclude`: default-allow opt-out (drift-prone — new resources auto-leak).
425
+ *
426
+ * Conflicting combinations throw with an actionable message so a host that
427
+ * accidentally mixed paradigms fails at boot instead of silently leaking or
428
+ * starving the LLM surface.
429
+ *
430
+ * **Local opt-out wins.** Any resource declared with
431
+ * `defineResource({ mcp: false })` is dropped FIRST, before any of the
432
+ * plugin-level allowlists/blocklists run. The opt-out is colocated with
433
+ * the resource definition, so adding a new "never-expose" resource is
434
+ * a single-file change instead of a host-wide blocklist update that
435
+ * drifts as the codebase grows.
436
+ *
437
+ * Exported so `mcp/testing.ts` and external test harnesses can apply the
438
+ * same precedence rules without duplicating them.
439
+ */
440
+ declare function filterResourcesForMcp<T extends {
441
+ name: string;
442
+ mcp?: boolean;
443
+ }>(resources: readonly T[], inputs: ResourceFilterInputs): T[];
264
444
  declare const mcpPlugin: FastifyPluginAsync<McpPluginOptions>;
265
445
  //#endregion
266
446
  //#region src/integrations/mcp/resourceToTools.d.ts
@@ -284,4 +464,56 @@ interface ResourceToToolsConfig extends McpResourceConfig {
284
464
  */
285
465
  declare function resourceToTools(resource: ResourceDefinition, config?: ResourceToToolsConfig): ToolDefinition[];
286
466
  //#endregion
287
- export { type AuthRef, type BetterAuthHandler, type BuildMcpToolsFromBridgesOptions, type CallToolResult, type CreateMcpServerConfig, type CrudOperation, type DefinePromptConfig, type DefineToolConfig, type FieldRuleEntry, type FieldRulesToZodOptions, type McpAuthResolver, type McpAuthResult, type McpBridge, type McpGuard, type McpPluginOptions, type McpResourceConfig, type McpServerInstance, type PromptDefinition, type PromptResult, type ResourceToToolsConfig, type ToolAnnotations, type ToolContext, type ToolDefinition, bridgeToMcp, buildMcpToolsFromBridges, createMcpServer, customGuard, definePrompt, defineTool, denied, fieldRulesToZod, getOrgId, getUserId, guard, hasOrg, isAuthenticated, isOrg, mcpPlugin, requireAuth, requireOrg, requireOrgId, requireRole, resourceToTools };
467
+ //#region src/integrations/mcp/tool-helpers.d.ts
468
+ /**
469
+ * Convert a controller response envelope into an MCP `CallToolResult`.
470
+ * Carries `meta` into the serialized payload so consumers see pagination
471
+ * totals, stripped-field arrays, etc.
472
+ *
473
+ * Errors are not represented here — controllers throw `ArcError` and the
474
+ * MCP tool wrapper catches them via {@link toCallToolError}.
475
+ */
476
+ declare function toCallToolResult(result: IControllerResponse): CallToolResult;
477
+ /**
478
+ * Wrap a raw success payload as an MCP `CallToolResult`. Use when the
479
+ * tool produced a value directly (action handler return, aggregation
480
+ * rows, etc.) instead of an `IControllerResponse` envelope.
481
+ *
482
+ * Emits the value as JSON with no envelope — same no-envelope contract
483
+ * the HTTP wire follows. The `isError: true` flag on `CallToolResult`
484
+ * is the success/error discriminant for MCP, mirroring HTTP status.
485
+ */
486
+ declare function toCallToolSuccess(value: unknown): CallToolResult;
487
+ /**
488
+ * Wrap an error as an MCP `CallToolResult` with the canonical
489
+ * `ErrorContract` shape inside the text payload. Single source of truth
490
+ * for MCP error serialization — every tool surface (CRUD, action, route,
491
+ * aggregation) routes through here so the JSON shape an agent sees is
492
+ * identical to what an HTTP client sees.
493
+ *
494
+ * Accepts:
495
+ * - An `ArcError` (or any `HttpError`-shaped throw) → routes through
496
+ * `toErrorContract()` for the canonical conversion.
497
+ * - A partial contract `{code, message, status, details?}` → used as-is.
498
+ * - Any other `Error` → falls back to `arc.internal_error` 500.
499
+ */
500
+ declare function toCallToolError(input: Error | {
501
+ code: string;
502
+ message: string;
503
+ status?: number;
504
+ details?: ErrorContract["details"];
505
+ }): CallToolResult;
506
+ /**
507
+ * Build the canonical permission-denied `CallToolResult` for an MCP
508
+ * tool. Discriminates 401 (no session — "Authentication required") from
509
+ * 403 (session present, denied — "Permission denied"). Mirrors the
510
+ * status split the HTTP `errorHandler` plugin uses.
511
+ */
512
+ declare function permissionDeniedResult(args: {
513
+ resource: string;
514
+ operation: string;
515
+ reason?: string;
516
+ session: McpAuthResult | null;
517
+ }): CallToolResult;
518
+ //#endregion
519
+ export { type AuthRef, type BetterAuthHandler, type BuildMcpToolsFromBridgesOptions, type CallToolResult, type CreateMcpServerConfig, type CrudDescriptionMeta, type CrudDescriptionOverride, type CrudOperation, type DefinePromptConfig, type DefineToolConfig, type FieldRuleEntry, type FieldRulesToZodOptions, type InvokeControllerOptions, type McpAuthResolver, type McpAuthResult, type McpBridge, type McpGuard, type McpOperation, type McpPluginOptions, type McpResourceConfig, type McpServerInstance, type PromptDefinition, type PromptResult, type ResourceToToolsConfig, type ToolAnnotations, type ToolContext, type ToolDefinition, bridgeToMcp, buildMcpToolsFromBridges, buildRequestContext, createMcpServer, customGuard, defaultCrudDescription, definePrompt, defineTool, denied, fieldRulesToZod, filterResourcesForMcp, getOrgId, getUserId, guard, hasOrg, invokeController, isAuthenticated, isOrg, mcpHandlerAdapter, mcpPlugin, permissionDeniedResult, requireAuth, requireOrg, requireOrgId, requireRole, resolveCrudDescription, resourceToTools, toCallToolError, toCallToolResult, toCallToolSuccess };