@gjermundgaraba/effect-actions 0.19.0 → 0.21.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 (326) hide show
  1. package/README.md +19 -41
  2. package/dist/Action.d.mts +140 -48
  3. package/dist/Action.mjs +88 -44
  4. package/dist/ActionCli.d.mts +70 -35
  5. package/dist/ActionCli.mjs +53 -34
  6. package/dist/ActionHttp.d.mts +70 -38
  7. package/dist/ActionHttp.mjs +76 -25
  8. package/dist/ActionMcp.d.mts +56 -24
  9. package/dist/ActionMcp.mjs +104 -61
  10. package/dist/ActionRpc.d.mts +222 -57
  11. package/dist/ActionRpc.mjs +301 -49
  12. package/dist/ActionToolkit.d.mts +22 -7
  13. package/dist/ActionToolkit.mjs +37 -14
  14. package/dist/Authentication.d.mts +42 -12
  15. package/dist/Authentication.mjs +38 -32
  16. package/dist/Event.d.mts +370 -0
  17. package/dist/Event.mjs +103 -0
  18. package/dist/Testing.d.mts +1 -3
  19. package/dist/Testing.mjs +2 -3
  20. package/dist/Webhook.d.mts +146 -0
  21. package/dist/Webhook.mjs +72 -0
  22. package/dist/authentication/provider.d.mts +35 -12
  23. package/dist/authentication/provider.mjs +2 -3
  24. package/dist/authentication/refusal.mjs +3 -4
  25. package/dist/cli/commands.d.mts +9 -7
  26. package/dist/cli/commands.mjs +85 -35
  27. package/dist/contract/ast.mjs +5 -3
  28. package/dist/contract/authorizer.d.mts +8 -0
  29. package/dist/contract/authorizer.mjs +20 -0
  30. package/dist/contract/call.d.mts +9 -8
  31. package/dist/contract/call.mjs +49 -8
  32. package/dist/contract/callback.d.mts +7 -0
  33. package/dist/contract/callback.mjs +27 -0
  34. package/dist/contract/caller.d.mts +12 -3
  35. package/dist/contract/caller.mjs +23 -5
  36. package/dist/contract/canonical.mjs +10 -0
  37. package/dist/contract/codec.d.mts +9 -0
  38. package/dist/contract/codec.mjs +9 -0
  39. package/dist/contract/codes.mjs +81 -0
  40. package/dist/contract/declared.d.mts +0 -2
  41. package/dist/contract/declared.mjs +26 -11
  42. package/dist/contract/digest.mjs +6 -0
  43. package/dist/contract/errors.d.mts +9 -5
  44. package/dist/contract/errors.mjs +2 -3
  45. package/dist/contract/feed.d.mts +127 -0
  46. package/dist/contract/feed.mjs +249 -0
  47. package/dist/contract/hints.mjs +1 -2
  48. package/dist/contract/hub.d.mts +94 -0
  49. package/dist/contract/hub.mjs +133 -0
  50. package/dist/contract/idempotency.d.mts +47 -0
  51. package/dist/contract/idempotency.mjs +99 -0
  52. package/dist/contract/implementation.d.mts +73 -51
  53. package/dist/contract/implementation.mjs +94 -60
  54. package/dist/contract/input-check.d.mts +15 -0
  55. package/dist/contract/input-check.mjs +16 -0
  56. package/dist/contract/lease.mjs +28 -0
  57. package/dist/contract/listed.d.mts +4 -0
  58. package/dist/contract/listed.mjs +22 -0
  59. package/dist/contract/log.d.mts +41 -0
  60. package/dist/contract/log.mjs +144 -0
  61. package/dist/contract/media.d.mts +1 -3
  62. package/dist/contract/media.mjs +1 -2
  63. package/dist/contract/names.mjs +15 -6
  64. package/dist/contract/occurrence.d.mts +29 -0
  65. package/dist/contract/occurrence.mjs +45 -0
  66. package/dist/contract/pages.d.mts +13 -0
  67. package/dist/contract/pages.mjs +39 -0
  68. package/dist/contract/progress.d.mts +26 -0
  69. package/dist/contract/progress.mjs +72 -0
  70. package/dist/contract/push.d.mts +20 -0
  71. package/dist/contract/push.mjs +96 -0
  72. package/dist/contract/receiving.d.mts +29 -0
  73. package/dist/contract/receiving.mjs +42 -0
  74. package/dist/contract/recent.mjs +12 -0
  75. package/dist/contract/reported.mjs +16 -0
  76. package/dist/contract/serving.mjs +63 -0
  77. package/dist/contract/status.mjs +15 -7
  78. package/dist/contract/stream.d.mts +34 -0
  79. package/dist/contract/stream.mjs +31 -0
  80. package/dist/contract/subscribe.d.mts +45 -0
  81. package/dist/contract/subscribe.mjs +50 -0
  82. package/dist/contract/transient.mjs +28 -0
  83. package/dist/contract/watch.d.mts +18 -0
  84. package/dist/contract/watch.mjs +105 -0
  85. package/dist/contract/webhooks.d.mts +42 -0
  86. package/dist/contract/webhooks.mjs +53 -0
  87. package/dist/http/client.d.mts +37 -14
  88. package/dist/http/client.mjs +52 -14
  89. package/dist/http/events.d.mts +56 -0
  90. package/dist/http/events.mjs +102 -0
  91. package/dist/http/placed.d.mts +36 -0
  92. package/dist/http/placed.mjs +71 -0
  93. package/dist/http/schema-errors.mjs +2 -3
  94. package/dist/http/streamed.d.mts +21 -0
  95. package/dist/http/streamed.mjs +94 -0
  96. package/dist/http/watch.mjs +50 -0
  97. package/dist/mcp/bridge.mjs +283 -0
  98. package/dist/mcp/client.d.mts +30 -99
  99. package/dist/mcp/client.mjs +60 -134
  100. package/dist/mcp/events.mjs +142 -0
  101. package/dist/mcp/progress.mjs +34 -0
  102. package/dist/mcp/protocol.mjs +40 -15
  103. package/dist/mcp/reply.d.mts +79 -0
  104. package/dist/mcp/reply.mjs +99 -0
  105. package/dist/mcp/request.d.mts +40 -0
  106. package/dist/mcp/request.mjs +51 -0
  107. package/dist/mcp/watch.mjs +115 -0
  108. package/dist/rpc/watch.mjs +39 -0
  109. package/dist/stdio/console.mjs +14 -7
  110. package/dist/testing/memory.d.mts +1 -3
  111. package/dist/testing/memory.mjs +4 -5
  112. package/dist/webhook/address.mjs +47 -0
  113. package/dist/webhook/attempt.mjs +65 -0
  114. package/dist/webhook/receiver.mjs +67 -0
  115. package/dist/webhook/signing.mjs +28 -0
  116. package/dist/webhook/stored.mjs +57 -0
  117. package/dist/webhook/subscriptions.mjs +342 -0
  118. package/docs/Action-failures.md +2 -2
  119. package/docs/Action-streams.md +115 -0
  120. package/docs/Action.md +58 -124
  121. package/docs/ActionCli-failures.md +1 -2
  122. package/docs/ActionCli.md +83 -88
  123. package/docs/ActionHttp-failures.md +3 -3
  124. package/docs/ActionHttp.md +90 -70
  125. package/docs/ActionMcp-failures.md +2 -1
  126. package/docs/ActionMcp.md +120 -92
  127. package/docs/ActionRpc-events.md +126 -0
  128. package/docs/ActionRpc-failures.md +1 -2
  129. package/docs/ActionRpc.md +108 -79
  130. package/docs/ActionToolkit-failures.md +1 -2
  131. package/docs/ActionToolkit.md +33 -90
  132. package/docs/Authentication-advanced.md +57 -61
  133. package/docs/Authentication-failures.md +5 -4
  134. package/docs/Authentication.md +23 -58
  135. package/docs/Event-failures.md +15 -0
  136. package/docs/Event.md +281 -0
  137. package/docs/README.md +51 -82
  138. package/docs/Testing-failures.md +1 -5
  139. package/docs/Testing.md +126 -86
  140. package/docs/Webhook-failures.md +8 -0
  141. package/docs/Webhook.md +319 -0
  142. package/docs/setup-failures.md +2 -3
  143. package/docs/setup.md +32 -53
  144. package/examples/README.md +12 -37
  145. package/examples/assistant/README.md +21 -26
  146. package/examples/assistant/src/agent.ts +66 -24
  147. package/examples/assistant/src/cli.ts +7 -4
  148. package/examples/assistant/src/commands.ts +9 -4
  149. package/examples/assistant/src/identity/Identity.ts +5 -4
  150. package/examples/assistant/src/identity/authorize.ts +13 -5
  151. package/examples/assistant/src/identity/handlers.ts +3 -2
  152. package/examples/assistant/src/identity/permissions.ts +9 -3
  153. package/examples/assistant/src/platform/tasks-file.ts +15 -11
  154. package/examples/assistant/src/scripted.ts +7 -4
  155. package/examples/assistant/src/tasks/Tasks.ts +20 -6
  156. package/examples/assistant/src/tasks/handlers.ts +9 -5
  157. package/examples/assistant/src/tasks/store.ts +38 -11
  158. package/examples/assistant/src/toolkit.ts +11 -7
  159. package/examples/assistant/test/commands.test.ts +53 -27
  160. package/examples/assistant/test/identity/identity.test.ts +27 -11
  161. package/examples/assistant/test/platform/tasks-file.test.ts +39 -23
  162. package/examples/assistant/test/tasks/tasks.test.ts +62 -34
  163. package/examples/assistant/test/toolkit.test.ts +104 -75
  164. package/examples/build-events/README.md +83 -0
  165. package/examples/build-events/src/Api.ts +27 -0
  166. package/examples/build-events/src/Rpc.ts +26 -0
  167. package/examples/build-events/src/builds/Builds.ts +108 -0
  168. package/examples/build-events/src/builds/events.ts +54 -0
  169. package/examples/build-events/src/builds/handlers.ts +58 -0
  170. package/examples/build-events/src/builds/log.ts +30 -0
  171. package/examples/build-events/src/builds/status.ts +28 -0
  172. package/examples/build-events/src/builds/store.ts +130 -0
  173. package/examples/build-events/src/cli.ts +18 -0
  174. package/examples/build-events/src/commands.ts +32 -0
  175. package/examples/build-events/src/deploys/Deploys.ts +44 -0
  176. package/examples/build-events/src/deploys/approvers.ts +55 -0
  177. package/examples/build-events/src/deploys/events.ts +32 -0
  178. package/examples/build-events/src/deploys/handlers.ts +38 -0
  179. package/examples/build-events/src/identity/Identity.ts +29 -0
  180. package/examples/build-events/src/identity/members.ts +7 -0
  181. package/examples/build-events/src/identity/verifier.ts +22 -0
  182. package/examples/build-events/src/notifier/Notices.ts +26 -0
  183. package/examples/build-events/src/notifier/routes.ts +71 -0
  184. package/examples/build-events/src/notifier.ts +48 -0
  185. package/examples/build-events/src/routes.ts +71 -0
  186. package/examples/build-events/src/server.ts +62 -0
  187. package/examples/build-events/test/builds/events.test.ts +68 -0
  188. package/examples/build-events/test/builds/log.test.ts +71 -0
  189. package/examples/build-events/test/builds/progress.test.ts +57 -0
  190. package/examples/build-events/test/builds/status.test.ts +42 -0
  191. package/examples/build-events/test/commands.test.ts +103 -0
  192. package/examples/build-events/test/deploys/events.test.ts +52 -0
  193. package/examples/build-events/test/http.test.ts +95 -0
  194. package/examples/build-events/test/notifier.test.ts +80 -0
  195. package/examples/build-events/test/routes.test.ts +96 -0
  196. package/examples/build-events/test/rpc.test.ts +84 -0
  197. package/examples/build-events/test/support/as.ts +8 -0
  198. package/examples/build-events/test/support/memory.ts +43 -0
  199. package/examples/build-events/test/webhooks.test.ts +143 -0
  200. package/examples/kitchen-sink/README.md +178 -166
  201. package/examples/kitchen-sink/src/Actions.ts +11 -3
  202. package/examples/kitchen-sink/src/Api.ts +12 -6
  203. package/examples/kitchen-sink/src/Rpc.ts +7 -5
  204. package/examples/kitchen-sink/src/admin/Admin.ts +21 -10
  205. package/examples/kitchen-sink/src/admin/authenticate.ts +8 -4
  206. package/examples/kitchen-sink/src/admin/authorize.ts +13 -5
  207. package/examples/kitchen-sink/src/admin/grants.ts +5 -3
  208. package/examples/kitchen-sink/src/admin/handlers.ts +9 -5
  209. package/examples/kitchen-sink/src/agent.ts +14 -6
  210. package/examples/kitchen-sink/src/assistant/Assistant.ts +21 -15
  211. package/examples/kitchen-sink/src/assistant/conversations.ts +14 -9
  212. package/examples/kitchen-sink/src/assistant/demo-model.ts +2 -2
  213. package/examples/kitchen-sink/src/assistant/handlers.ts +42 -22
  214. package/examples/kitchen-sink/src/attachments/Attachments.ts +6 -6
  215. package/examples/kitchen-sink/src/attachments/download.ts +7 -6
  216. package/examples/kitchen-sink/src/attachments/handlers.ts +9 -4
  217. package/examples/kitchen-sink/src/attachments/store.ts +25 -18
  218. package/examples/kitchen-sink/src/browser.ts +10 -4
  219. package/examples/kitchen-sink/src/cli.ts +28 -12
  220. package/examples/kitchen-sink/src/config.ts +1 -1
  221. package/examples/kitchen-sink/src/identity/Identity.ts +24 -10
  222. package/examples/kitchen-sink/src/identity/authenticate.ts +19 -11
  223. package/examples/kitchen-sink/src/identity/authorize.ts +14 -4
  224. package/examples/kitchen-sink/src/identity/directory.ts +16 -7
  225. package/examples/kitchen-sink/src/identity/handlers.ts +1 -0
  226. package/examples/kitchen-sink/src/identity/members.ts +7 -2
  227. package/examples/kitchen-sink/src/identity/quota.ts +23 -20
  228. package/examples/kitchen-sink/src/issues/Issues.ts +91 -15
  229. package/examples/kitchen-sink/src/issues/assistant.ts +4 -2
  230. package/examples/kitchen-sink/src/issues/events.ts +46 -0
  231. package/examples/kitchen-sink/src/issues/export.ts +35 -0
  232. package/examples/kitchen-sink/src/issues/guide.ts +4 -3
  233. package/examples/kitchen-sink/src/issues/handlers.ts +20 -7
  234. package/examples/kitchen-sink/src/issues/store.ts +156 -67
  235. package/examples/kitchen-sink/src/issues/write-limit.ts +44 -18
  236. package/examples/kitchen-sink/src/memory.ts +11 -2
  237. package/examples/kitchen-sink/src/ops.ts +10 -5
  238. package/examples/kitchen-sink/src/request-policy.ts +25 -9
  239. package/examples/kitchen-sink/src/routes.ts +67 -27
  240. package/examples/kitchen-sink/src/sdk.ts +22 -12
  241. package/examples/kitchen-sink/src/seed.ts +15 -9
  242. package/examples/kitchen-sink/src/server.ts +24 -10
  243. package/examples/kitchen-sink/src/stdio.ts +9 -3
  244. package/examples/kitchen-sink/src/workspaces/Workspaces.ts +10 -7
  245. package/examples/kitchen-sink/src/workspaces/handlers.ts +3 -2
  246. package/examples/kitchen-sink/src/workspaces/registry.ts +16 -10
  247. package/examples/kitchen-sink/src/workspaces/tenant.ts +12 -5
  248. package/examples/kitchen-sink/test/admin/admin.test.ts +38 -23
  249. package/examples/kitchen-sink/test/assistant/assistant.test.ts +471 -299
  250. package/examples/kitchen-sink/test/attachments/attachments.test.ts +135 -94
  251. package/examples/kitchen-sink/test/identity/identity.test.ts +110 -82
  252. package/examples/kitchen-sink/test/identity/session.test.ts +65 -43
  253. package/examples/kitchen-sink/test/issues/assistant.test.ts +50 -31
  254. package/examples/kitchen-sink/test/issues/events.test.ts +273 -0
  255. package/examples/kitchen-sink/test/issues/export.test.ts +120 -0
  256. package/examples/kitchen-sink/test/issues/issues.test.ts +105 -75
  257. package/examples/kitchen-sink/test/request-policy.test.ts +130 -33
  258. package/examples/kitchen-sink/test/routes.test.ts +102 -57
  259. package/examples/kitchen-sink/test/support/as.ts +9 -0
  260. package/examples/kitchen-sink/test/support/scripted.ts +6 -5
  261. package/examples/kitchen-sink/test/support/services.ts +17 -0
  262. package/examples/live-rpc/README.md +33 -35
  263. package/examples/live-rpc/src/Rpc.ts +9 -5
  264. package/examples/live-rpc/src/browser.ts +39 -11
  265. package/examples/live-rpc/src/chat/Chat.ts +30 -16
  266. package/examples/live-rpc/src/chat/authorize.ts +2 -1
  267. package/examples/live-rpc/src/chat/events.ts +74 -0
  268. package/examples/live-rpc/src/chat/handlers.ts +13 -5
  269. package/examples/live-rpc/src/chat/room.ts +9 -5
  270. package/examples/live-rpc/src/chat/store.ts +51 -14
  271. package/examples/live-rpc/src/client.ts +22 -5
  272. package/examples/live-rpc/src/identity/Identity.ts +3 -3
  273. package/examples/live-rpc/src/identity/verifier.ts +8 -4
  274. package/examples/live-rpc/src/page.ts +58 -12
  275. package/examples/live-rpc/src/routes.ts +14 -10
  276. package/examples/live-rpc/src/server.ts +15 -5
  277. package/examples/live-rpc/test/browser.test.ts +127 -50
  278. package/examples/live-rpc/test/chat/chat.test.ts +215 -23
  279. package/examples/live-rpc/test/routes.test.ts +130 -46
  280. package/examples/live-rpc/test/server.test.ts +94 -33
  281. package/examples/mcp-tools/README.md +24 -38
  282. package/examples/mcp-tools/src/platform/fake-farm.ts +63 -24
  283. package/examples/mcp-tools/src/platform/print-farm.ts +59 -29
  284. package/examples/mcp-tools/src/printers/Printers.ts +18 -7
  285. package/examples/mcp-tools/src/printers/farm.ts +15 -5
  286. package/examples/mcp-tools/src/printers/handlers.ts +12 -6
  287. package/examples/mcp-tools/src/routes.ts +8 -6
  288. package/examples/mcp-tools/src/server.ts +12 -5
  289. package/examples/mcp-tools/src/stdio.ts +3 -2
  290. package/examples/mcp-tools/test/printers/printers.test.ts +132 -89
  291. package/examples/mcp-tools/test/routes.test.ts +140 -81
  292. package/examples/notes-service/README.md +30 -45
  293. package/examples/notes-service/src/Api.ts +1 -0
  294. package/examples/notes-service/src/browser.ts +15 -14
  295. package/examples/notes-service/src/cli.ts +8 -3
  296. package/examples/notes-service/src/commands.ts +46 -20
  297. package/examples/notes-service/src/identity/Identity.ts +2 -2
  298. package/examples/notes-service/src/identity/authorize.ts +6 -2
  299. package/examples/notes-service/src/identity/handlers.ts +3 -2
  300. package/examples/notes-service/src/identity/users.ts +2 -1
  301. package/examples/notes-service/src/identity/verifier.ts +12 -6
  302. package/examples/notes-service/src/notes/Notes.ts +46 -22
  303. package/examples/notes-service/src/notes/handlers.ts +18 -9
  304. package/examples/notes-service/src/notes/store.ts +70 -43
  305. package/examples/notes-service/src/routes.ts +7 -5
  306. package/examples/notes-service/src/server.ts +12 -5
  307. package/examples/notes-service/src/status/Status.ts +1 -1
  308. package/examples/notes-service/src/status/handlers.ts +5 -3
  309. package/examples/notes-service/src/stdio.ts +7 -3
  310. package/examples/notes-service/src/worker.ts +6 -3
  311. package/examples/notes-service/test/commands.test.ts +164 -91
  312. package/examples/notes-service/test/notes/as.ts +3 -1
  313. package/examples/notes-service/test/notes/idempotency.test.ts +97 -67
  314. package/examples/notes-service/test/notes/in-process.test.ts +26 -15
  315. package/examples/notes-service/test/notes/notes.test.ts +49 -31
  316. package/examples/notes-service/test/routes.test.ts +106 -71
  317. package/examples/notes-service/test/worker.test.ts +21 -13
  318. package/examples/quickstart/README.md +2 -6
  319. package/examples/quickstart/src/Api.ts +1 -0
  320. package/examples/quickstart/src/client.ts +6 -3
  321. package/examples/quickstart/src/greeting/Greeting.ts +1 -1
  322. package/examples/quickstart/src/greeting/handlers.ts +5 -2
  323. package/examples/quickstart/src/routes.ts +3 -2
  324. package/examples/quickstart/src/server.ts +6 -2
  325. package/examples/quickstart/test/routes.test.ts +3 -2
  326. package/package.json +19 -17
@@ -1,33 +1,28 @@
1
1
  import { Anyone, assertAuthentication } from "./contract/caller.mjs";
2
- import { assertOnce, heldOnce } from "./contract/names.mjs";
3
2
  import { projectedErrors } from "./contract/declared.mjs";
3
+ import { assertOnce, heldOnce } from "./contract/names.mjs";
4
+ import { toolSuccessOf } from "./contract/stream.mjs";
5
+ import { acquire, answeringWhole } from "./contract/implementation.mjs";
6
+ import { inputParseOptions } from "./contract/call.mjs";
4
7
  import { hintsOf } from "./contract/hints.mjs";
5
- import { acquire, provideHandlers, select, toList } from "./contract/implementation.mjs";
6
8
  import { promote, providerOf } from "./authentication/provider.mjs";
7
- import { inputParseOptions } from "./contract/call.mjs";
8
- import { defaultPath, fieldKey, httpProtocol, isMisplaced, liftOf, liftedFrom, protocols } from "./mcp/protocol.mjs";
9
+ import { provideServed, selectFrom } from "./contract/serving.mjs";
9
10
  import { recordStepUp } from "./authentication/refusal.mjs";
10
11
  import { withStderrConsole } from "./stdio/console.mjs";
11
- import { McpCallError, client, request } from "./mcp/client.mjs";
12
- import { Cause, Context, Effect, ErrorReporter, Exit, Fiber, JsonPointer, Layer, Predicate, Schema } from "effect";
13
- import { AiError, McpSchema, McpServer } from "effect/ai";
12
+ import { defaultPath, fieldKey, httpProtocol, isMisplaced, isObjectSchema, liftOf, liftedFrom, protocols, routingFormsOf, toolJsonSchema } from "./mcp/protocol.mjs";
13
+ import { eventSchemasOf, refuseUnservable, serveWebhooks, withEvents } from "./mcp/bridge.mjs";
14
+ import { progressNotifier } from "./mcp/progress.mjs";
15
+ import { McpCallError } from "./mcp/reply.mjs";
16
+ import { request } from "./mcp/request.mjs";
17
+ import { client } from "./mcp/client.mjs";
18
+ import { Cause, Context, Effect, ErrorReporter, Exit, Fiber, Layer, Option, Predicate, Schema, Stdio, Stream } from "effect";
14
19
  import { HttpRouter, HttpServerRequest } from "effect/http";
15
- import { Base64 } from "effect/encoding";
16
- //#region src/mcp/ActionMcp.ts
17
- const isToolArgumentsSchema = Schema.is(McpSchema.ToolJson);
18
- const toolJsonSchema = (schema, strict) => {
19
- const document = Schema.toJsonSchemaDocument(schema, { onExcessProperty: strict ? "error" : "ignore" });
20
- const [scope, key] = Predicate.isString(document.schema.$ref) ? JsonPointer.parseUriFragment(document.schema.$ref) ?? [] : [];
21
- const root = scope === "$defs" && key !== void 0 ? document.definitions[key] : document.schema;
22
- return root === void 0 || Object.keys(document.definitions).length === 0 ? root : {
23
- ...root,
24
- $defs: document.definitions
25
- };
26
- };
27
- const assertToolShapes = (lifted) => {
28
- const inputs = lifted.map(([action]) => action).filter((action) => !isToolArgumentsSchema(toolJsonSchema(Schema.toCodecJson(action.input), true))).map(({ name }) => name);
20
+ import { AiError, McpSchema, McpServer } from "effect/ai";
21
+ // src/mcp/ActionMcp.ts
22
+ const assertToolsServable = (lifted) => {
23
+ const inputs = lifted.map(([action]) => action).flatMap(({ input, name }) => isObjectSchema(toolJsonSchema(Schema.toCodecJson(input), true)) ? [] : [name]);
29
24
  if (inputs.length > 0) throw new Error(`MCP tool input must be one object with keys, such as a struct: ${inputs.join(", ")} (wrap a union, an array or a scalar in a field, omit input for no arguments, or leave the action out of actions)`);
30
- const misplaced = lifted.filter(([action, lift]) => isMisplaced(action, lift)).map(([{ name }]) => name);
25
+ const misplaced = lifted.flatMap(([action, lift]) => isMisplaced(action, lift) ? [action.name] : []);
31
26
  if (misplaced.length > 0) throw new Error(`MCP media must be the success or an array of it, or a top-level field of a struct success, one, optional or a required array: ${misplaced.join(", ")} (make the image such a field, or give an optional array as a required one, empty when absent; an image in input or an error is not served over MCP, so leave that action out of actions)`);
32
27
  };
33
28
  const nativeInternalErrorText = "Tool execution failed due to an internal server error.";
@@ -59,26 +54,30 @@ const toolOf = (action, outputSchema) => Effect.map(Schema.decodeUnknownEffect(M
59
54
  },
60
55
  _meta: action.mcp._meta === void 0 ? void 0 : { ...action.mcp._meta }
61
56
  }));
57
+ const internalError = (cause) => Effect.logError(cause).pipe(Effect.andThen(ErrorReporter.report(cause)), Effect.as(textErrorResult(nativeInternalErrorText)));
58
+ const internalErrorOnDefect = (cause) => Cause.hasDies(cause) ? internalError(cause) : Effect.failCause(cause);
59
+ const encoder = (schema) => {
60
+ const encode = Schema.encodeUnknownEffect(Schema.toCodecJson(schema));
61
+ return (value) => Effect.orDie(encode(value));
62
+ };
62
63
  const registerTools = Effect.fnUntraced(function* (apps, authentication) {
63
64
  const registry = yield* McpServer.McpServer;
64
- const bound = yield* acquire(apps);
65
+ const bound = yield* acquire(apps, authentication);
65
66
  const built = yield* Effect.context();
66
- const internalError = (cause) => Effect.logError(cause).pipe(Effect.andThen(ErrorReporter.report(cause)), Effect.as(textErrorResult(nativeInternalErrorText)));
67
- const internalErrorOnDefect = (cause) => Cause.hasDies(cause) ? internalError(cause) : Effect.failCause(cause);
68
- for (const [action, run] of bound) {
69
- const lift = liftOf(action.success);
67
+ for (const [action, handler] of bound) {
68
+ const toolSuccess = toolSuccessOf(action.success);
69
+ const run = answeringWhole(action, handler);
70
+ const lift = liftOf(toolSuccess);
70
71
  const media = lift.fields.length === 0 ? void 0 : lift;
71
- const structured = media === void 0 ? Schema.toCodecJson(action.success) : media.rest === void 0 ? void 0 : Schema.toCodecJson(media.rest);
72
+ const structuredSuccess = media === void 0 ? toolSuccess : media.rest;
73
+ const structured = structuredSuccess === void 0 ? void 0 : Schema.toCodecJson(structuredSuccess);
72
74
  const outputSchema = structured === void 0 ? void 0 : yield* Schema.decodeUnknownEffect(McpSchema.ToolOutputJson)(toolJsonSchema(structured, false)).pipe(Effect.orDie);
73
75
  const tool = yield* toolOf(action, outputSchema).pipe(Effect.orDie);
74
76
  const decode = Schema.decodeUnknownEffect(Schema.toCodecJson(action.input), inputParseOptions);
75
- const encoder = (schema) => {
76
- const encode = Schema.encodeUnknownEffect(Schema.toCodecJson(schema));
77
- return (value) => Effect.orDie(encode(value));
78
- };
79
- const encodeSuccess = encoder(action.success);
77
+ const encodeSuccess = encoder(toolSuccess);
80
78
  const encodeFailure = encoder(Schema.Union(projectedErrors(action)));
81
- const call = authentication === void 0 || action.caller === Anyone ? run : (input) => recordStepUp(promote(authentication, run(input)));
79
+ const reported = (input) => action.progress === void 0 ? run(input) : Effect.flatMap(progressNotifier(registry.notifications, action.progress), (sink) => run(input, sink));
80
+ const call = authentication === void 0 || action.caller === Anyone ? reported : (input) => recordStepUp(promote(authentication, reported(input)));
82
81
  const liftedFieldNames = new Set(media?.fields.map(({ name }) => name));
83
82
  const resultOf = (encoded, success) => {
84
83
  if (media === void 0) return new McpSchema.CallToolResult({
@@ -101,10 +100,7 @@ const registerTools = Effect.fnUntraced(function* (apps, authentication) {
101
100
  yield* registry.addTool({
102
101
  tool,
103
102
  annotations: Context.empty(),
104
- handle: (payload) => Effect.annotateCurrentSpan({
105
- tool: action.name,
106
- parameters: payload ?? {}
107
- }).pipe(Effect.andThen(() => decode(payload ?? {})), Effect.mapError(({ message }) => new McpSchema.InvalidParams({ message: new AiError.ToolParameterValidationError({
103
+ handle: (payload) => Effect.annotateCurrentSpan({ tool: action.name }).pipe(Effect.andThen(() => decode(payload ?? {})), Effect.mapError(({ message }) => new McpSchema.InvalidParams({ message: new AiError.ToolParameterValidationError({
108
104
  toolName: action.name,
109
105
  description: message
110
106
  }).message })), Effect.flatMap((input) => call(input).pipe(Effect.matchEffect({
@@ -117,66 +113,113 @@ const registerTools = Effect.fnUntraced(function* (apps, authentication) {
117
113
  });
118
114
  }
119
115
  });
120
- const server = (apps, transport, features = Layer.empty, authentication) => {
116
+ /**
117
+ * Refuses event types an endpoint cannot serve as MCP events: one named twice, one named as MCP's
118
+ * own, or one whose input or payload is no object.
119
+ */
120
+ const assertEventsServable = (events) => {
121
+ assertOnce("MCP event", events);
122
+ const reserved = events.find(({ name }) => name.startsWith("mcp."));
123
+ if (reserved !== void 0) throw new Error(`MCP event name starts with "mcp.", which MCP keeps for its own events: ${reserved.name} (rename it, or serve it on another surface)`);
124
+ for (const event of events) eventSchemasOf(event);
125
+ };
126
+ /** The revisions an endpoint speaks, the 2026-07-28 one serving `serving`'s events if any. */
127
+ const servingEvents = ([stateless, ...rest], serving) => serving.events.length === 0 ? [stateless, ...rest] : [withEvents(stateless, serving), ...rest];
128
+ const server = (apps, serving, transport, features = Layer.empty) => {
129
+ const { events, authentication } = serving;
121
130
  assertOnce("MCP tool", apps.flatMap((app) => app.actions), heldOnce);
122
- const lifted = apps.flatMap((app) => app.actions.map((action) => [action, liftOf(action.success)]));
123
- assertToolShapes(lifted);
131
+ const lifted = apps.flatMap((app) => app.actions.map((action) => [action, liftOf(toolSuccessOf(action.success))]));
132
+ assertToolsServable(lifted);
124
133
  const names = new Set(lifted.map(([{ name }]) => name));
125
134
  const register = Effect.gen(function* () {
126
135
  const namesClaimedByFeatures = (yield* McpServer.McpServer).tools.flatMap(({ tool }) => names.has(tool.name) ? [tool.name] : []);
127
136
  if (namesClaimedByFeatures.length > 0) return yield* Effect.die(/* @__PURE__ */ new Error(`Duplicate MCP tool: ${namesClaimedByFeatures.join(", ")}, claimed by an action and a native feature (rename the native tool, or leave the action out of actions)`));
137
+ yield* refuseUnservable(serving);
138
+ yield* serveWebhooks(serving);
128
139
  yield* registerTools(apps, authentication);
129
140
  });
130
- return Layer.effectDiscard(register).pipe(Layer.provide(features), Layer.provide(transport), Layer.fresh, provideHandlers(apps));
141
+ return Layer.effectDiscard(register).pipe(Layer.provide(features), Layer.provide(transport), Layer.fresh, provideServed({
142
+ apps,
143
+ events
144
+ }));
131
145
  };
132
146
  const anonymousMethods = /* @__PURE__ */ new Set([
133
147
  "server/discover",
134
148
  "tools/list",
149
+ "events/list",
135
150
  "notifications/cancelled"
136
151
  ]);
137
- const requiresAuthentication = (actions) => {
138
- const open = new Set(actions.filter(({ caller }) => caller === Anyone).flatMap(({ name }) => [name, `=?base64?${Base64.encode(name)}?=`]));
152
+ const namedMethods = /* @__PURE__ */ new Map([
153
+ ["tools/call", "tool"],
154
+ ["events/poll", "event"],
155
+ ["events/stream", "event"]
156
+ ]);
157
+ const openOf = (contracts) => new Set(contracts.filter(({ caller }) => caller === Anyone).flatMap(({ name }) => routingFormsOf(name)));
158
+ const requiresAuthentication = (actions, events) => {
159
+ const open = {
160
+ tool: openOf(actions),
161
+ event: openOf(events)
162
+ };
139
163
  return (headers) => {
140
- if (open.size === 0) return true;
164
+ if (open.tool.size === 0 && open.event.size === 0) return true;
141
165
  if (headers["mcp-protocol-version"] !== httpProtocol.protocolVersion) return true;
142
166
  const method = headers["mcp-method"];
143
167
  if (method === void 0) return true;
144
168
  if (anonymousMethods.has(method)) return false;
145
- if (method !== "tools/call") return true;
169
+ const named = namedMethods.get(method);
170
+ if (named === void 0) return true;
146
171
  const name = headers["mcp-name"];
147
- return name === void 0 || !open.has(name);
172
+ return name === void 0 || !open[named].has(name);
148
173
  };
149
174
  };
150
175
  const namesItsMethod = (request) => Effect.match(request.json, {
151
176
  onFailure: () => true,
152
177
  onSuccess: (body) => !Predicate.hasProperty(body, "method") || body.method === request.headers["mcp-method"]
153
178
  });
154
- function layerHttp(apps, { actions, features, path = defaultPath, authentication, requestScoped, allowSubscriptions = features !== void 0, ...options }) {
155
- const selected = select(toList(apps), actions);
179
+ const readsItsBody = (route) => Effect.flatMap(HttpServerRequest.HttpServerRequest, (request) => request.method === "POST" ? Effect.andThen(request.text, route) : route);
180
+ function layerHttp(apps, { actions, features, path = defaultPath, authentication, requestScoped, allowSubscriptions, ...options }) {
181
+ const { apps: selected, events } = selectFrom(apps, actions);
156
182
  const served = selected.flatMap((app) => app.actions);
183
+ const listed = events.flatMap((app) => app.events);
157
184
  assertAuthentication(served, authentication);
158
- const transport = server(selected, requestScoped === true ? McpServer.layerHttpRequestScoped({
185
+ assertAuthentication(listed, authentication, "event");
186
+ assertEventsServable(listed);
187
+ const serving = {
188
+ events,
189
+ authentication
190
+ };
191
+ const transport = server(selected, serving, requestScoped === true ? McpServer.layerHttpRequestScoped({
159
192
  ...options,
160
193
  path,
161
- protocols: [httpProtocol]
194
+ protocols: servingEvents([httpProtocol], serving)
162
195
  }) : McpServer.layerHttp({
163
196
  ...options,
164
197
  path,
165
- protocols,
198
+ protocols: servingEvents(protocols, serving),
166
199
  allowSessionTermination: true,
167
- allowSubscriptions
168
- }), features, authentication);
169
- if (authentication === void 0) return transport;
170
- const required = requiresAuthentication(served);
171
- const middleware = HttpRouter.middleware(Effect.map(providerOf(authentication), (runtime) => (route) => Effect.flatMap(HttpServerRequest.HttpServerRequest, (request) => request.method !== "POST" || required(request.headers) ? runtime.http(route, false) : Effect.flatMap(namesItsMethod(request), (named) => runtime.http(route, named)))));
200
+ allowSubscriptions: allowSubscriptions ?? (features !== void 0 || events.length > 0)
201
+ }), features);
202
+ if (authentication === void 0) return transport.pipe(Layer.provide(HttpRouter.middleware(readsItsBody).layer));
203
+ const required = requiresAuthentication(served, listed);
204
+ const middleware = HttpRouter.middleware(Effect.map(providerOf(authentication), (runtime) => (route) => Effect.flatMap(HttpServerRequest.HttpServerRequest, (request) => request.method !== "POST" || required(request.headers) ? runtime.http(readsItsBody(route), false) : Effect.flatMap(namesItsMethod(request), (named) => runtime.http(readsItsBody(route), named)))));
172
205
  return transport.pipe(Layer.provide(middleware.layer));
173
206
  }
207
+ const isJsonLine = (line) => Option.isSome(Schema.decodeOption(Schema.fromJsonString(Schema.Json))(line));
208
+ const jsonLinesOnly = Layer.effect(Stdio.Stdio, Effect.map(Stdio.Stdio, (stdio) => Stdio.make({
209
+ ...stdio,
210
+ stdin: stdio.stdin.pipe(Stream.decodeText, Stream.splitLines, Stream.filter(isJsonLine), Stream.map((line) => `${line}\n`), Stream.encodeText)
211
+ })));
174
212
  function runStdio(apps, { actions, features, ...options }) {
175
- const transport = server(select(toList(apps), actions), McpServer.layerStdio({
213
+ const { apps: selected, events } = selectFrom(apps, actions);
214
+ assertEventsServable(events.flatMap((app) => app.events));
215
+ const serving = {
216
+ events,
217
+ authentication: void 0
218
+ };
219
+ const transport = server(selected, serving, McpServer.layerStdio({
176
220
  ...options,
177
- protocols
178
- }), features);
221
+ protocols: servingEvents(protocols, serving)
222
+ }).pipe(Layer.provide(jsonLinesOnly)), features);
179
223
  return Layer.launch(transport).pipe(withStderrConsole, Effect.forkChild, Effect.flatMap(Fiber.await), Effect.flatMap((exit) => Exit.isFailure(exit) && !Cause.hasInterruptsOnly(exit.cause) ? Effect.failCause(exit.cause) : Effect.void));
180
224
  }
181
- //#endregion
182
225
  export { McpCallError, client, layerHttp, request, runStdio };