effect 4.0.7 → 4.1.1

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 (863) hide show
  1. package/README.md +31 -1
  2. package/THIRD_PARTY_NOTICES.md +62 -0
  3. package/dist/BigDecimal.d.ts +139 -7
  4. package/dist/BigDecimal.d.ts.map +1 -1
  5. package/dist/BigDecimal.js +86 -14
  6. package/dist/BigDecimal.js.map +1 -1
  7. package/dist/Channel.d.ts +12 -6
  8. package/dist/Channel.d.ts.map +1 -1
  9. package/dist/Channel.js +9 -3
  10. package/dist/Channel.js.map +1 -1
  11. package/dist/Config.d.ts +7 -1
  12. package/dist/Config.d.ts.map +1 -1
  13. package/dist/Config.js.map +1 -1
  14. package/dist/Context.d.ts +18 -1
  15. package/dist/Context.d.ts.map +1 -1
  16. package/dist/Context.js +27 -8
  17. package/dist/Context.js.map +1 -1
  18. package/dist/Cron.d.ts +81 -11
  19. package/dist/Cron.d.ts.map +1 -1
  20. package/dist/Cron.js +101 -26
  21. package/dist/Cron.js.map +1 -1
  22. package/dist/Duration.d.ts +78 -0
  23. package/dist/Duration.d.ts.map +1 -1
  24. package/dist/Duration.js +123 -0
  25. package/dist/Duration.js.map +1 -1
  26. package/dist/Effect.d.ts +164 -7
  27. package/dist/Effect.d.ts.map +1 -1
  28. package/dist/Effect.js +11 -1
  29. package/dist/Effect.js.map +1 -1
  30. package/dist/Equal.d.ts +2 -2
  31. package/dist/Equal.d.ts.map +1 -1
  32. package/dist/Equal.js +3 -3
  33. package/dist/Equal.js.map +1 -1
  34. package/dist/FileSystem.d.ts +59 -4
  35. package/dist/FileSystem.d.ts.map +1 -1
  36. package/dist/FileSystem.js +9 -2
  37. package/dist/FileSystem.js.map +1 -1
  38. package/dist/Glob.d.ts +165 -0
  39. package/dist/Glob.d.ts.map +1 -0
  40. package/dist/Glob.js +127 -0
  41. package/dist/Glob.js.map +1 -0
  42. package/dist/Hash.d.ts +3 -2
  43. package/dist/Hash.d.ts.map +1 -1
  44. package/dist/Hash.js +5 -4
  45. package/dist/Hash.js.map +1 -1
  46. package/dist/Iterable.d.ts.map +1 -1
  47. package/dist/Iterable.js +11 -8
  48. package/dist/Iterable.js.map +1 -1
  49. package/dist/Match.d.ts +86 -0
  50. package/dist/Match.d.ts.map +1 -1
  51. package/dist/Match.js +72 -0
  52. package/dist/Match.js.map +1 -1
  53. package/dist/Path.d.ts.map +1 -1
  54. package/dist/Path.js +5 -1
  55. package/dist/Path.js.map +1 -1
  56. package/dist/Pool.d.ts +51 -0
  57. package/dist/Pool.d.ts.map +1 -1
  58. package/dist/Pool.js +61 -10
  59. package/dist/Pool.js.map +1 -1
  60. package/dist/Random.d.ts.map +1 -1
  61. package/dist/Random.js +3 -3
  62. package/dist/Random.js.map +1 -1
  63. package/dist/RcMap.d.ts.map +1 -1
  64. package/dist/RcMap.js +8 -2
  65. package/dist/RcMap.js.map +1 -1
  66. package/dist/Schedule.d.ts +18 -1
  67. package/dist/Schedule.d.ts.map +1 -1
  68. package/dist/Schedule.js +7 -2
  69. package/dist/Schedule.js.map +1 -1
  70. package/dist/Schema.d.ts +668 -42
  71. package/dist/Schema.d.ts.map +1 -1
  72. package/dist/Schema.js +652 -1
  73. package/dist/Schema.js.map +1 -1
  74. package/dist/SchemaGetter.d.ts +6 -1
  75. package/dist/SchemaGetter.d.ts.map +1 -1
  76. package/dist/SchemaGetter.js +22 -11
  77. package/dist/SchemaGetter.js.map +1 -1
  78. package/dist/SchemaRepresentation.d.ts +18 -2
  79. package/dist/SchemaRepresentation.d.ts.map +1 -1
  80. package/dist/SchemaRepresentation.js +20 -2
  81. package/dist/SchemaRepresentation.js.map +1 -1
  82. package/dist/SchemaTransformation.d.ts +10 -5
  83. package/dist/SchemaTransformation.d.ts.map +1 -1
  84. package/dist/SchemaTransformation.js +8 -5
  85. package/dist/SchemaTransformation.js.map +1 -1
  86. package/dist/ScopedCache.d.ts.map +1 -1
  87. package/dist/ScopedCache.js +5 -7
  88. package/dist/ScopedCache.js.map +1 -1
  89. package/dist/Semaphore.d.ts +130 -0
  90. package/dist/Semaphore.d.ts.map +1 -1
  91. package/dist/Semaphore.js +40 -0
  92. package/dist/Semaphore.js.map +1 -1
  93. package/dist/Stream.d.ts +13 -4
  94. package/dist/Stream.d.ts.map +1 -1
  95. package/dist/Stream.js +9 -0
  96. package/dist/Stream.js.map +1 -1
  97. package/dist/Terminal.d.ts +18 -1
  98. package/dist/Terminal.d.ts.map +1 -1
  99. package/dist/Terminal.js +1 -1
  100. package/dist/Terminal.js.map +1 -1
  101. package/dist/ai/AiError.d.ts +43 -116
  102. package/dist/ai/AiError.d.ts.map +1 -1
  103. package/dist/ai/AiError.js +53 -72
  104. package/dist/ai/AiError.js.map +1 -1
  105. package/dist/ai/Decision.d.ts +196 -15
  106. package/dist/ai/Decision.d.ts.map +1 -1
  107. package/dist/ai/Decision.js +130 -0
  108. package/dist/ai/Decision.js.map +1 -1
  109. package/dist/ai/DecisionModel.d.ts +54 -13
  110. package/dist/ai/DecisionModel.d.ts.map +1 -1
  111. package/dist/ai/DecisionModel.js +123 -12
  112. package/dist/ai/DecisionModel.js.map +1 -1
  113. package/dist/ai/McpClient.d.ts +171 -19
  114. package/dist/ai/McpClient.d.ts.map +1 -1
  115. package/dist/ai/McpClient.js +277 -66
  116. package/dist/ai/McpClient.js.map +1 -1
  117. package/dist/ai/McpSchema.d.ts +108 -0
  118. package/dist/ai/McpSchema.d.ts.map +1 -1
  119. package/dist/ai/McpSchema.js +99 -0
  120. package/dist/ai/McpSchema.js.map +1 -1
  121. package/dist/ai/McpServer.d.ts +744 -29
  122. package/dist/ai/McpServer.d.ts.map +1 -1
  123. package/dist/ai/McpServer.js +763 -136
  124. package/dist/ai/McpServer.js.map +1 -1
  125. package/dist/ai/McpTest.d.ts +130 -0
  126. package/dist/ai/McpTest.d.ts.map +1 -0
  127. package/dist/ai/McpTest.js +237 -0
  128. package/dist/ai/McpTest.js.map +1 -0
  129. package/dist/ai/Prompt.d.ts.map +1 -1
  130. package/dist/ai/Prompt.js +20 -11
  131. package/dist/ai/Prompt.js.map +1 -1
  132. package/dist/ai/Response.d.ts +1 -25
  133. package/dist/ai/Response.d.ts.map +1 -1
  134. package/dist/ai/Response.js +1 -10
  135. package/dist/ai/Response.js.map +1 -1
  136. package/dist/ai/Tool.d.ts +19 -1
  137. package/dist/ai/Tool.d.ts.map +1 -1
  138. package/dist/ai/Tool.js +5 -7
  139. package/dist/ai/Tool.js.map +1 -1
  140. package/dist/ai/index.d.ts +5 -0
  141. package/dist/ai/index.d.ts.map +1 -1
  142. package/dist/ai/index.js +5 -0
  143. package/dist/ai/index.js.map +1 -1
  144. package/dist/ai/internal/mcpCore.js +89 -15
  145. package/dist/ai/internal/mcpCore.js.map +1 -1
  146. package/dist/ai/internal/mcpProtocol/v2024_11_05.js +7 -6
  147. package/dist/ai/internal/mcpProtocol/v2024_11_05.js.map +1 -1
  148. package/dist/ai/internal/mcpProtocol/v2025_03_26.js +7 -6
  149. package/dist/ai/internal/mcpProtocol/v2025_03_26.js.map +1 -1
  150. package/dist/ai/internal/mcpProtocol/v2025_06_18.js +7 -6
  151. package/dist/ai/internal/mcpProtocol/v2025_06_18.js.map +1 -1
  152. package/dist/ai/internal/mcpProtocol/v2025_11_25.js +7 -6
  153. package/dist/ai/internal/mcpProtocol/v2025_11_25.js.map +1 -1
  154. package/dist/ai/internal/mcpProtocol/v2026_07_28.js +60 -17
  155. package/dist/ai/internal/mcpProtocol/v2026_07_28.js.map +1 -1
  156. package/dist/ai/internal/mcpProtocol.js +25 -0
  157. package/dist/ai/internal/mcpProtocol.js.map +1 -1
  158. package/dist/ai/internal/mcpRuntime.js +8 -6
  159. package/dist/ai/internal/mcpRuntime.js.map +1 -1
  160. package/dist/ai/internal/mcpSkills.d.ts +2 -0
  161. package/dist/ai/internal/mcpSkills.d.ts.map +1 -0
  162. package/dist/ai/internal/mcpSkills.js +428 -0
  163. package/dist/ai/internal/mcpSkills.js.map +1 -0
  164. package/dist/ai/internal/mcpStatefulRuntime.js +6 -1
  165. package/dist/ai/internal/mcpStatefulRuntime.js.map +1 -1
  166. package/dist/cli/Argument.d.ts +6 -0
  167. package/dist/cli/Argument.d.ts.map +1 -1
  168. package/dist/cli/Argument.js +2 -0
  169. package/dist/cli/Argument.js.map +1 -1
  170. package/dist/cli/CliOutput.d.ts +65 -1
  171. package/dist/cli/CliOutput.d.ts.map +1 -1
  172. package/dist/cli/CliOutput.js +94 -37
  173. package/dist/cli/CliOutput.js.map +1 -1
  174. package/dist/cli/Command.d.ts +23 -0
  175. package/dist/cli/Command.d.ts.map +1 -1
  176. package/dist/cli/Command.js +8 -0
  177. package/dist/cli/Command.js.map +1 -1
  178. package/dist/cli/Flag.d.ts +107 -0
  179. package/dist/cli/Flag.d.ts.map +1 -1
  180. package/dist/cli/Flag.js +37 -0
  181. package/dist/cli/Flag.js.map +1 -1
  182. package/dist/cli/HelpDoc.d.ts +15 -1
  183. package/dist/cli/HelpDoc.d.ts.map +1 -1
  184. package/dist/cli/Param.d.ts +6 -0
  185. package/dist/cli/Param.d.ts.map +1 -1
  186. package/dist/cli/Param.js +2 -0
  187. package/dist/cli/Param.js.map +1 -1
  188. package/dist/cli/Primitive.d.ts +14 -0
  189. package/dist/cli/Primitive.d.ts.map +1 -1
  190. package/dist/cli/Primitive.js +15 -1
  191. package/dist/cli/Primitive.js.map +1 -1
  192. package/dist/cli/Prompt.d.ts +1 -0
  193. package/dist/cli/Prompt.d.ts.map +1 -1
  194. package/dist/cli/Prompt.js +1 -0
  195. package/dist/cli/Prompt.js.map +1 -1
  196. package/dist/cli/internal/help.d.ts.map +1 -1
  197. package/dist/cli/internal/help.js +17 -10
  198. package/dist/cli/internal/help.js.map +1 -1
  199. package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
  200. package/dist/cluster/ClusterWorkflowEngine.js +15 -5
  201. package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
  202. package/dist/cluster/Reply.d.ts +1 -1
  203. package/dist/cluster/Reply.d.ts.map +1 -1
  204. package/dist/cluster/Reply.js.map +1 -1
  205. package/dist/cluster/Sharding.d.ts.map +1 -1
  206. package/dist/cluster/Sharding.js +93 -28
  207. package/dist/cluster/Sharding.js.map +1 -1
  208. package/dist/cluster/ShardingConfig.d.ts +72 -6
  209. package/dist/cluster/ShardingConfig.d.ts.map +1 -1
  210. package/dist/cluster/ShardingConfig.js +4 -0
  211. package/dist/cluster/ShardingConfig.js.map +1 -1
  212. package/dist/cluster/SingleRunner.d.ts +3 -3
  213. package/dist/cluster/SingleRunner.d.ts.map +1 -1
  214. package/dist/cluster/SingleRunner.js +1 -1
  215. package/dist/cluster/SqlMessageStorage.d.ts +37 -6
  216. package/dist/cluster/SqlMessageStorage.d.ts.map +1 -1
  217. package/dist/cluster/SqlMessageStorage.js +34 -7
  218. package/dist/cluster/SqlMessageStorage.js.map +1 -1
  219. package/dist/cluster/SqlRunnerStorage.d.ts.map +1 -1
  220. package/dist/cluster/SqlRunnerStorage.js +23 -8
  221. package/dist/cluster/SqlRunnerStorage.js.map +1 -1
  222. package/dist/cluster/internal/entityManager.js +15 -7
  223. package/dist/cluster/internal/entityManager.js.map +1 -1
  224. package/dist/crypto/Aead.d.ts +323 -0
  225. package/dist/crypto/Aead.d.ts.map +1 -0
  226. package/dist/crypto/Aead.js +331 -0
  227. package/dist/crypto/Aead.js.map +1 -0
  228. package/dist/crypto/Cipher.d.ts +236 -0
  229. package/dist/crypto/Cipher.d.ts.map +1 -0
  230. package/dist/crypto/Cipher.js +233 -0
  231. package/dist/crypto/Cipher.js.map +1 -0
  232. package/dist/crypto/CryptoError.d.ts +212 -0
  233. package/dist/crypto/CryptoError.d.ts.map +1 -0
  234. package/dist/crypto/CryptoError.js +202 -0
  235. package/dist/crypto/CryptoError.js.map +1 -0
  236. package/dist/crypto/Digest.d.ts +143 -0
  237. package/dist/crypto/Digest.d.ts.map +1 -0
  238. package/dist/crypto/Digest.js +146 -0
  239. package/dist/crypto/Digest.js.map +1 -0
  240. package/dist/crypto/Kdf.d.ts +220 -0
  241. package/dist/crypto/Kdf.d.ts.map +1 -0
  242. package/dist/crypto/Kdf.js +212 -0
  243. package/dist/crypto/Kdf.js.map +1 -0
  244. package/dist/crypto/KeyAgreement.d.ts +324 -0
  245. package/dist/crypto/KeyAgreement.d.ts.map +1 -0
  246. package/dist/crypto/KeyAgreement.js +303 -0
  247. package/dist/crypto/KeyAgreement.js.map +1 -0
  248. package/dist/crypto/KeyFormat.d.ts +341 -0
  249. package/dist/crypto/KeyFormat.d.ts.map +1 -0
  250. package/dist/crypto/KeyFormat.js +556 -0
  251. package/dist/crypto/KeyFormat.js.map +1 -0
  252. package/dist/crypto/KeyWrap.d.ts +390 -0
  253. package/dist/crypto/KeyWrap.d.ts.map +1 -0
  254. package/dist/crypto/KeyWrap.js +381 -0
  255. package/dist/crypto/KeyWrap.js.map +1 -0
  256. package/dist/crypto/Mac.d.ts +278 -0
  257. package/dist/crypto/Mac.d.ts.map +1 -0
  258. package/dist/crypto/Mac.js +288 -0
  259. package/dist/crypto/Mac.js.map +1 -0
  260. package/dist/crypto/SecureRandom.d.ts +340 -0
  261. package/dist/crypto/SecureRandom.d.ts.map +1 -0
  262. package/dist/crypto/SecureRandom.js +257 -0
  263. package/dist/crypto/SecureRandom.js.map +1 -0
  264. package/dist/crypto/Signature.d.ts +449 -0
  265. package/dist/crypto/Signature.d.ts.map +1 -0
  266. package/dist/crypto/Signature.js +484 -0
  267. package/dist/crypto/Signature.js.map +1 -0
  268. package/dist/crypto/WebCrypto.d.ts +80 -0
  269. package/dist/crypto/WebCrypto.d.ts.map +1 -0
  270. package/dist/crypto/WebCrypto.js +63 -0
  271. package/dist/crypto/WebCrypto.js.map +1 -0
  272. package/dist/crypto/index.d.ts +65 -0
  273. package/dist/crypto/index.d.ts.map +1 -0
  274. package/dist/crypto/index.js +66 -0
  275. package/dist/crypto/index.js.map +1 -0
  276. package/dist/crypto/internal/asymmetric.d.ts +2 -0
  277. package/dist/crypto/internal/asymmetric.d.ts.map +1 -0
  278. package/dist/crypto/internal/asymmetric.js +210 -0
  279. package/dist/crypto/internal/asymmetric.js.map +1 -0
  280. package/dist/crypto/internal/chacha.d.ts +46 -0
  281. package/dist/crypto/internal/chacha.d.ts.map +1 -0
  282. package/dist/crypto/internal/chacha.js +885 -0
  283. package/dist/crypto/internal/chacha.js.map +1 -0
  284. package/dist/crypto/internal/der.d.ts +6 -0
  285. package/dist/crypto/internal/der.d.ts.map +1 -0
  286. package/dist/crypto/internal/der.js +86 -0
  287. package/dist/crypto/internal/der.js.map +1 -0
  288. package/dist/crypto/internal/digest.d.ts +2 -0
  289. package/dist/crypto/internal/digest.d.ts.map +1 -0
  290. package/dist/crypto/internal/digest.js +15 -0
  291. package/dist/crypto/internal/digest.js.map +1 -0
  292. package/dist/crypto/internal/key.d.ts +2 -0
  293. package/dist/crypto/internal/key.d.ts.map +1 -0
  294. package/dist/crypto/internal/key.js +171 -0
  295. package/dist/crypto/internal/key.js.map +1 -0
  296. package/dist/crypto/internal/md5.d.ts +39 -0
  297. package/dist/crypto/internal/md5.d.ts.map +1 -0
  298. package/dist/crypto/internal/md5.js +179 -0
  299. package/dist/crypto/internal/md5.js.map +1 -0
  300. package/dist/crypto/internal/webCrypto.d.ts +2 -0
  301. package/dist/crypto/internal/webCrypto.d.ts.map +1 -0
  302. package/dist/crypto/internal/webCrypto.js +111 -0
  303. package/dist/crypto/internal/webCrypto.js.map +1 -0
  304. package/dist/encoding/Base64Url.d.ts.map +1 -1
  305. package/dist/encoding/Base64Url.js +29 -5
  306. package/dist/encoding/Base64Url.js.map +1 -1
  307. package/dist/encoding/Csv.d.ts +608 -0
  308. package/dist/encoding/Csv.d.ts.map +1 -0
  309. package/dist/encoding/Csv.js +718 -0
  310. package/dist/encoding/Csv.js.map +1 -0
  311. package/dist/encoding/Hex.d.ts +3 -2
  312. package/dist/encoding/Hex.d.ts.map +1 -1
  313. package/dist/encoding/Hex.js +3 -2
  314. package/dist/encoding/Hex.js.map +1 -1
  315. package/dist/encoding/Ndjson.d.ts +5 -4
  316. package/dist/encoding/Ndjson.d.ts.map +1 -1
  317. package/dist/encoding/Ndjson.js +6 -5
  318. package/dist/encoding/Ndjson.js.map +1 -1
  319. package/dist/encoding/SchemaBinary.d.ts.map +1 -1
  320. package/dist/encoding/SchemaBinary.js +42 -4
  321. package/dist/encoding/SchemaBinary.js.map +1 -1
  322. package/dist/encoding/Sse.d.ts +3 -1
  323. package/dist/encoding/Sse.d.ts.map +1 -1
  324. package/dist/encoding/Sse.js +5 -3
  325. package/dist/encoding/Sse.js.map +1 -1
  326. package/dist/encoding/Toml.d.ts +17 -3
  327. package/dist/encoding/Toml.d.ts.map +1 -1
  328. package/dist/encoding/Toml.js +104 -16
  329. package/dist/encoding/Toml.js.map +1 -1
  330. package/dist/encoding/Yaml.d.ts +8 -1
  331. package/dist/encoding/Yaml.d.ts.map +1 -1
  332. package/dist/encoding/Yaml.js +54 -18
  333. package/dist/encoding/Yaml.js.map +1 -1
  334. package/dist/encoding/index.d.ts +5 -0
  335. package/dist/encoding/index.d.ts.map +1 -1
  336. package/dist/encoding/index.js +5 -0
  337. package/dist/encoding/index.js.map +1 -1
  338. package/dist/eventlog/EventJournal.d.ts.map +1 -1
  339. package/dist/eventlog/EventJournal.js +6 -3
  340. package/dist/eventlog/EventJournal.js.map +1 -1
  341. package/dist/eventlog/EventLog.d.ts +126 -4
  342. package/dist/eventlog/EventLog.d.ts.map +1 -1
  343. package/dist/eventlog/EventLog.js +207 -12
  344. package/dist/eventlog/EventLog.js.map +1 -1
  345. package/dist/eventlog/EventLogEncryption.d.ts +41 -4
  346. package/dist/eventlog/EventLogEncryption.d.ts.map +1 -1
  347. package/dist/eventlog/EventLogEncryption.js +83 -64
  348. package/dist/eventlog/EventLogEncryption.js.map +1 -1
  349. package/dist/eventlog/EventLogMessage.d.ts +279 -0
  350. package/dist/eventlog/EventLogMessage.d.ts.map +1 -1
  351. package/dist/eventlog/EventLogMessage.js +217 -1
  352. package/dist/eventlog/EventLogMessage.js.map +1 -1
  353. package/dist/eventlog/EventLogRemote.d.ts +200 -28
  354. package/dist/eventlog/EventLogRemote.d.ts.map +1 -1
  355. package/dist/eventlog/EventLogRemote.js +186 -16
  356. package/dist/eventlog/EventLogRemote.js.map +1 -1
  357. package/dist/eventlog/EventLogServer.d.ts +10 -1
  358. package/dist/eventlog/EventLogServer.d.ts.map +1 -1
  359. package/dist/eventlog/EventLogServer.js +45 -22
  360. package/dist/eventlog/EventLogServer.js.map +1 -1
  361. package/dist/eventlog/EventLogServerEncrypted.d.ts +336 -5
  362. package/dist/eventlog/EventLogServerEncrypted.d.ts.map +1 -1
  363. package/dist/eventlog/EventLogServerEncrypted.js +769 -14
  364. package/dist/eventlog/EventLogServerEncrypted.js.map +1 -1
  365. package/dist/eventlog/EventLogServerUnencrypted.d.ts +17 -0
  366. package/dist/eventlog/EventLogServerUnencrypted.d.ts.map +1 -1
  367. package/dist/eventlog/EventLogServerUnencrypted.js +14 -2
  368. package/dist/eventlog/EventLogServerUnencrypted.js.map +1 -1
  369. package/dist/eventlog/EventLogSessionAuth.d.ts +26 -3
  370. package/dist/eventlog/EventLogSessionAuth.d.ts.map +1 -1
  371. package/dist/eventlog/EventLogSessionAuth.js +63 -64
  372. package/dist/eventlog/EventLogSessionAuth.js.map +1 -1
  373. package/dist/eventlog/EventRow.d.ts +4 -0
  374. package/dist/eventlog/EventRow.d.ts.map +1 -1
  375. package/dist/eventlog/EventRow.js +12 -2
  376. package/dist/eventlog/EventRow.js.map +1 -1
  377. package/dist/eventlog/SqlEventJournal.js +2 -2
  378. package/dist/eventlog/SqlEventJournal.js.map +1 -1
  379. package/dist/eventlog/SqlEventLogServerEncrypted.d.ts +21 -5
  380. package/dist/eventlog/SqlEventLogServerEncrypted.d.ts.map +1 -1
  381. package/dist/eventlog/SqlEventLogServerEncrypted.js +1048 -113
  382. package/dist/eventlog/SqlEventLogServerEncrypted.js.map +1 -1
  383. package/dist/eventlog/SqlEventLogServerUnencrypted.js +2 -2
  384. package/dist/eventlog/SqlEventLogServerUnencrypted.js.map +1 -1
  385. package/dist/eventlog/internal/batches.d.ts +12 -0
  386. package/dist/eventlog/internal/batches.d.ts.map +1 -0
  387. package/dist/eventlog/internal/batches.js +26 -0
  388. package/dist/eventlog/internal/batches.js.map +1 -0
  389. package/dist/eventlog/internal/compaction.d.ts +38 -0
  390. package/dist/eventlog/internal/compaction.d.ts.map +1 -0
  391. package/dist/eventlog/internal/compaction.js +33 -0
  392. package/dist/eventlog/internal/compaction.js.map +1 -0
  393. package/dist/eventlog/internal/identityRootSecretDerivation.js +66 -67
  394. package/dist/eventlog/internal/identityRootSecretDerivation.js.map +1 -1
  395. package/dist/eventlog/internal/remoteCompaction.d.ts +31 -0
  396. package/dist/eventlog/internal/remoteCompaction.d.ts.map +1 -0
  397. package/dist/eventlog/internal/remoteCompaction.js +76 -0
  398. package/dist/eventlog/internal/remoteCompaction.js.map +1 -0
  399. package/dist/graphql/GraphQLClient.d.ts +3 -1
  400. package/dist/graphql/GraphQLClient.d.ts.map +1 -1
  401. package/dist/graphql/GraphQLClient.js.map +1 -1
  402. package/dist/graphql/GraphQLClientError.d.ts +14 -9
  403. package/dist/graphql/GraphQLClientError.d.ts.map +1 -1
  404. package/dist/graphql/GraphQLClientError.js +14 -21
  405. package/dist/graphql/GraphQLClientError.js.map +1 -1
  406. package/dist/graphql/GraphQLProtocol.d.ts +12 -3
  407. package/dist/graphql/GraphQLProtocol.d.ts.map +1 -1
  408. package/dist/graphql/GraphQLProtocol.js +4 -1
  409. package/dist/graphql/GraphQLProtocol.js.map +1 -1
  410. package/dist/http/Cookies.d.ts +172 -0
  411. package/dist/http/Cookies.d.ts.map +1 -1
  412. package/dist/http/Cookies.js +143 -1
  413. package/dist/http/Cookies.js.map +1 -1
  414. package/dist/http/FetchHttpClient.d.ts +26 -2
  415. package/dist/http/FetchHttpClient.d.ts.map +1 -1
  416. package/dist/http/FetchHttpClient.js +78 -15
  417. package/dist/http/FetchHttpClient.js.map +1 -1
  418. package/dist/http/HttpClient.d.ts +268 -15
  419. package/dist/http/HttpClient.d.ts.map +1 -1
  420. package/dist/http/HttpClient.js +140 -7
  421. package/dist/http/HttpClient.js.map +1 -1
  422. package/dist/http/HttpClientRequest.d.ts +9 -5
  423. package/dist/http/HttpClientRequest.d.ts.map +1 -1
  424. package/dist/http/HttpClientRequest.js +2 -3
  425. package/dist/http/HttpClientRequest.js.map +1 -1
  426. package/dist/http/HttpClientResponse.d.ts.map +1 -1
  427. package/dist/http/HttpClientResponse.js +3 -2
  428. package/dist/http/HttpClientResponse.js.map +1 -1
  429. package/dist/http/HttpMethod.d.ts +7 -1
  430. package/dist/http/HttpMethod.d.ts.map +1 -1
  431. package/dist/http/HttpMethod.js +3 -8
  432. package/dist/http/HttpMethod.js.map +1 -1
  433. package/dist/http/HttpServerRequest.d.ts +5 -2
  434. package/dist/http/HttpServerRequest.d.ts.map +1 -1
  435. package/dist/http/HttpServerRequest.js +44 -39
  436. package/dist/http/HttpServerRequest.js.map +1 -1
  437. package/dist/http/HttpServerResponse.d.ts.map +1 -1
  438. package/dist/http/HttpServerResponse.js +3 -2
  439. package/dist/http/HttpServerResponse.js.map +1 -1
  440. package/dist/http/HttpTraceContext.d.ts +2 -1
  441. package/dist/http/HttpTraceContext.d.ts.map +1 -1
  442. package/dist/http/HttpTraceContext.js +7 -5
  443. package/dist/http/HttpTraceContext.js.map +1 -1
  444. package/dist/http/ProblemDetails.d.ts +96 -0
  445. package/dist/http/ProblemDetails.d.ts.map +1 -0
  446. package/dist/http/ProblemDetails.js +98 -0
  447. package/dist/http/ProblemDetails.js.map +1 -0
  448. package/dist/http/index.d.ts +5 -0
  449. package/dist/http/index.d.ts.map +1 -1
  450. package/dist/http/index.js +5 -0
  451. package/dist/http/index.js.map +1 -1
  452. package/dist/http/internal/decompression.js +3 -2
  453. package/dist/http/internal/decompression.js.map +1 -1
  454. package/dist/http/internal/mimeTypes.d.ts +4 -1
  455. package/dist/http/internal/mimeTypes.d.ts.map +1 -1
  456. package/dist/http/internal/mimeTypes.js +4 -1
  457. package/dist/http/internal/mimeTypes.js.map +1 -1
  458. package/dist/http/internal/urlParams.js +8 -0
  459. package/dist/http/internal/urlParams.js.map +1 -1
  460. package/dist/http-api/HttpApiBuilder.js +19 -5
  461. package/dist/http-api/HttpApiBuilder.js.map +1 -1
  462. package/dist/http-api/HttpApiClient.d.ts +63 -0
  463. package/dist/http-api/HttpApiClient.d.ts.map +1 -1
  464. package/dist/http-api/HttpApiClient.js +51 -0
  465. package/dist/http-api/HttpApiClient.js.map +1 -1
  466. package/dist/http-api/HttpApiEndpoint.d.ts.map +1 -1
  467. package/dist/http-api/HttpApiEndpoint.js +14 -5
  468. package/dist/http-api/HttpApiEndpoint.js.map +1 -1
  469. package/dist/http-api/HttpApiError.d.ts +185 -13
  470. package/dist/http-api/HttpApiError.d.ts.map +1 -1
  471. package/dist/http-api/HttpApiError.js +128 -0
  472. package/dist/http-api/HttpApiError.js.map +1 -1
  473. package/dist/http-api/HttpApiMiddleware.d.ts +64 -17
  474. package/dist/http-api/HttpApiMiddleware.d.ts.map +1 -1
  475. package/dist/http-api/HttpApiMiddleware.js +85 -1
  476. package/dist/http-api/HttpApiMiddleware.js.map +1 -1
  477. package/dist/http-api/HttpApiSchema.d.ts +76 -14
  478. package/dist/http-api/HttpApiSchema.d.ts.map +1 -1
  479. package/dist/http-api/HttpApiSchema.js +54 -1
  480. package/dist/http-api/HttpApiSchema.js.map +1 -1
  481. package/dist/index.d.ts +5 -5
  482. package/dist/index.d.ts.map +1 -1
  483. package/dist/index.js +5 -5
  484. package/dist/index.js.map +1 -1
  485. package/dist/internal/dateTime.js +49 -24
  486. package/dist/internal/dateTime.js.map +1 -1
  487. package/dist/internal/effect.js +35 -14
  488. package/dist/internal/effect.js.map +1 -1
  489. package/dist/internal/glob.d.ts +2 -0
  490. package/dist/internal/glob.d.ts.map +1 -0
  491. package/dist/internal/glob.js +808 -0
  492. package/dist/internal/glob.js.map +1 -0
  493. package/dist/internal/graphql.js +21 -7
  494. package/dist/internal/graphql.js.map +1 -1
  495. package/dist/internal/graphqlHeaders.d.ts +7 -0
  496. package/dist/internal/graphqlHeaders.d.ts.map +1 -1
  497. package/dist/internal/graphqlHeaders.js +11 -0
  498. package/dist/internal/graphqlHeaders.js.map +1 -1
  499. package/dist/internal/matcher.js +10 -0
  500. package/dist/internal/matcher.js.map +1 -1
  501. package/dist/internal/persistence.js +9 -0
  502. package/dist/internal/persistence.js.map +1 -1
  503. package/dist/internal/rcRef.js +4 -1
  504. package/dist/internal/rcRef.js.map +1 -1
  505. package/dist/internal/request.js +29 -42
  506. package/dist/internal/request.js.map +1 -1
  507. package/dist/internal/schema/fromJsonSchemaDocument.js +7 -8
  508. package/dist/internal/schema/fromJsonSchemaDocument.js.map +1 -1
  509. package/dist/internal/schema/toCodeDocument.js +6 -3
  510. package/dist/internal/schema/toCodeDocument.js.map +1 -1
  511. package/dist/internal/trie.js +42 -13
  512. package/dist/internal/trie.js.map +1 -1
  513. package/dist/internal/ulid.js +41 -0
  514. package/dist/internal/ulid.js.map +1 -1
  515. package/dist/internal/uuid.js +52 -8
  516. package/dist/internal/uuid.js.map +1 -1
  517. package/dist/internal/version.js +1 -1
  518. package/dist/jose/JoseError.d.ts +285 -0
  519. package/dist/jose/JoseError.d.ts.map +1 -0
  520. package/dist/jose/JoseError.js +269 -0
  521. package/dist/jose/JoseError.js.map +1 -0
  522. package/dist/jose/Jwe.d.ts +128 -0
  523. package/dist/jose/Jwe.d.ts.map +1 -0
  524. package/dist/jose/Jwe.js +134 -0
  525. package/dist/jose/Jwe.js.map +1 -0
  526. package/dist/jose/Jwk.d.ts +597 -0
  527. package/dist/jose/Jwk.d.ts.map +1 -0
  528. package/dist/jose/Jwk.js +503 -0
  529. package/dist/jose/Jwk.js.map +1 -0
  530. package/dist/jose/Jwks.d.ts +236 -0
  531. package/dist/jose/Jwks.d.ts.map +1 -0
  532. package/dist/jose/Jwks.js +306 -0
  533. package/dist/jose/Jwks.js.map +1 -0
  534. package/dist/jose/Jws.d.ts +177 -0
  535. package/dist/jose/Jws.d.ts.map +1 -0
  536. package/dist/jose/Jws.js +183 -0
  537. package/dist/jose/Jws.js.map +1 -0
  538. package/dist/jose/Jwt.d.ts +270 -0
  539. package/dist/jose/Jwt.d.ts.map +1 -0
  540. package/dist/jose/Jwt.js +293 -0
  541. package/dist/jose/Jwt.js.map +1 -0
  542. package/dist/jose/index.d.ts +51 -0
  543. package/dist/jose/index.d.ts.map +1 -0
  544. package/dist/jose/index.js +52 -0
  545. package/dist/jose/index.js.map +1 -0
  546. package/dist/jose/internal/compact.d.ts +2 -0
  547. package/dist/jose/internal/compact.d.ts.map +1 -0
  548. package/dist/jose/internal/compact.js +179 -0
  549. package/dist/jose/internal/compact.js.map +1 -0
  550. package/dist/net/Host.d.ts.map +1 -1
  551. package/dist/net/Host.js +5 -10
  552. package/dist/net/Host.js.map +1 -1
  553. package/dist/observability/Otlp.d.ts +15 -4
  554. package/dist/observability/Otlp.d.ts.map +1 -1
  555. package/dist/observability/Otlp.js +10 -0
  556. package/dist/observability/Otlp.js.map +1 -1
  557. package/dist/observability/OtlpResource.d.ts +7 -0
  558. package/dist/observability/OtlpResource.d.ts.map +1 -1
  559. package/dist/observability/OtlpResource.js +11 -1
  560. package/dist/observability/OtlpResource.js.map +1 -1
  561. package/dist/observability/OtlpSerialization.d.ts +1 -1
  562. package/dist/observability/OtlpSerialization.d.ts.map +1 -1
  563. package/dist/observability/OtlpSerialization.js +10 -4
  564. package/dist/observability/OtlpSerialization.js.map +1 -1
  565. package/dist/observability/internal/otlpProtobuf.js +3 -3
  566. package/dist/observability/internal/otlpProtobuf.js.map +1 -1
  567. package/dist/observability/internal/protobuf.js +6 -0
  568. package/dist/observability/internal/protobuf.js.map +1 -1
  569. package/dist/persistence/CircuitBreaker.d.ts +98 -38
  570. package/dist/persistence/CircuitBreaker.d.ts.map +1 -1
  571. package/dist/persistence/CircuitBreaker.js +67 -29
  572. package/dist/persistence/CircuitBreaker.js.map +1 -1
  573. package/dist/persistence/KeyValueStore.d.ts +47 -2
  574. package/dist/persistence/KeyValueStore.d.ts.map +1 -1
  575. package/dist/persistence/KeyValueStore.js +129 -18
  576. package/dist/persistence/KeyValueStore.js.map +1 -1
  577. package/dist/persistence/PersistedQueue.d.ts +9 -0
  578. package/dist/persistence/PersistedQueue.d.ts.map +1 -1
  579. package/dist/persistence/PersistedQueue.js +94 -52
  580. package/dist/persistence/PersistedQueue.js.map +1 -1
  581. package/dist/persistence/Persistence.d.ts +10 -4
  582. package/dist/persistence/Persistence.d.ts.map +1 -1
  583. package/dist/persistence/Persistence.js +18 -11
  584. package/dist/persistence/Persistence.js.map +1 -1
  585. package/dist/persistence/RateLimiter.d.ts +8 -0
  586. package/dist/persistence/RateLimiter.d.ts.map +1 -1
  587. package/dist/persistence/RateLimiter.js +63 -12
  588. package/dist/persistence/RateLimiter.js.map +1 -1
  589. package/dist/persistence/index.d.ts +1 -1
  590. package/dist/persistence/index.js +1 -1
  591. package/dist/process/ChildProcess.d.ts +207 -67
  592. package/dist/process/ChildProcess.d.ts.map +1 -1
  593. package/dist/process/ChildProcess.js +56 -158
  594. package/dist/process/ChildProcess.js.map +1 -1
  595. package/dist/process/ChildProcessSpawner.d.ts +5 -0
  596. package/dist/process/ChildProcessSpawner.d.ts.map +1 -1
  597. package/dist/process/ChildProcessSpawner.js.map +1 -1
  598. package/dist/process/CommandLine.d.ts +294 -0
  599. package/dist/process/CommandLine.d.ts.map +1 -0
  600. package/dist/process/CommandLine.js +481 -0
  601. package/dist/process/CommandLine.js.map +1 -0
  602. package/dist/process/index.d.ts +5 -0
  603. package/dist/process/index.d.ts.map +1 -1
  604. package/dist/process/index.js +5 -0
  605. package/dist/process/index.js.map +1 -1
  606. package/dist/reactivity/Atom.d.ts +2 -1
  607. package/dist/reactivity/Atom.d.ts.map +1 -1
  608. package/dist/reactivity/Atom.js +3 -4
  609. package/dist/reactivity/Atom.js.map +1 -1
  610. package/dist/reactivity/AtomRegistry.js +17 -7
  611. package/dist/reactivity/AtomRegistry.js.map +1 -1
  612. package/dist/rpc/Rpc.d.ts +1 -1
  613. package/dist/rpc/Rpc.d.ts.map +1 -1
  614. package/dist/rpc/Rpc.js.map +1 -1
  615. package/dist/rpc/RpcClient.d.ts +28 -1
  616. package/dist/rpc/RpcClient.d.ts.map +1 -1
  617. package/dist/rpc/RpcClient.js +78 -27
  618. package/dist/rpc/RpcClient.js.map +1 -1
  619. package/dist/rpc/RpcMessage.d.ts +13 -3
  620. package/dist/rpc/RpcMessage.d.ts.map +1 -1
  621. package/dist/rpc/RpcMessage.js +1 -0
  622. package/dist/rpc/RpcMessage.js.map +1 -1
  623. package/dist/rpc/RpcSerialization.d.ts.map +1 -1
  624. package/dist/rpc/RpcSerialization.js +6 -0
  625. package/dist/rpc/RpcSerialization.js.map +1 -1
  626. package/dist/rpc/RpcServer.d.ts +31 -0
  627. package/dist/rpc/RpcServer.d.ts.map +1 -1
  628. package/dist/rpc/RpcServer.js +139 -66
  629. package/dist/rpc/RpcServer.js.map +1 -1
  630. package/dist/schema/Model.d.ts +14 -0
  631. package/dist/schema/Model.d.ts.map +1 -1
  632. package/dist/schema/Model.js +18 -3
  633. package/dist/schema/Model.js.map +1 -1
  634. package/dist/sql/Migrator.d.ts +9 -20
  635. package/dist/sql/Migrator.d.ts.map +1 -1
  636. package/dist/sql/Migrator.js +20 -53
  637. package/dist/sql/Migrator.js.map +1 -1
  638. package/dist/sql/MigratorFileSystem.d.ts +21 -0
  639. package/dist/sql/MigratorFileSystem.d.ts.map +1 -0
  640. package/dist/sql/MigratorFileSystem.js +57 -0
  641. package/dist/sql/MigratorFileSystem.js.map +1 -0
  642. package/dist/sql/SqlClient.d.ts +38 -3
  643. package/dist/sql/SqlClient.d.ts.map +1 -1
  644. package/dist/sql/SqlClient.js +9 -12
  645. package/dist/sql/SqlClient.js.map +1 -1
  646. package/dist/sql/Statement.d.ts +61 -9
  647. package/dist/sql/Statement.d.ts.map +1 -1
  648. package/dist/sql/Statement.js +24 -33
  649. package/dist/sql/Statement.js.map +1 -1
  650. package/dist/sql/index.js +1 -1
  651. package/dist/testing/index.d.ts +0 -5
  652. package/dist/testing/index.d.ts.map +1 -1
  653. package/dist/testing/index.js +0 -5
  654. package/dist/testing/index.js.map +1 -1
  655. package/dist/workflow/Workflow.d.ts +4 -0
  656. package/dist/workflow/Workflow.d.ts.map +1 -1
  657. package/dist/workflow/Workflow.js.map +1 -1
  658. package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
  659. package/dist/workflow/WorkflowEngine.js +5 -0
  660. package/dist/workflow/WorkflowEngine.js.map +1 -1
  661. package/dist/workflow/internal/crypto.js +9 -8
  662. package/dist/workflow/internal/crypto.js.map +1 -1
  663. package/package.json +7 -1
  664. package/src/BigDecimal.ts +173 -16
  665. package/src/Channel.ts +17 -11
  666. package/src/Config.ts +7 -1
  667. package/src/Context.ts +34 -10
  668. package/src/Cron.ts +178 -29
  669. package/src/Duration.ts +140 -0
  670. package/src/Effect.ts +914 -85
  671. package/src/Equal.ts +3 -3
  672. package/src/FileSystem.ts +65 -4
  673. package/src/Glob.ts +205 -0
  674. package/src/Hash.ts +5 -4
  675. package/src/Iterable.ts +8 -5
  676. package/src/Match.ts +127 -0
  677. package/src/Path.ts +6 -1
  678. package/src/Pool.ts +75 -16
  679. package/src/Random.ts +3 -3
  680. package/src/RcMap.ts +5 -1
  681. package/src/Schedule.ts +26 -3
  682. package/src/Schema.ts +1191 -63
  683. package/src/SchemaGetter.ts +27 -11
  684. package/src/SchemaRepresentation.ts +23 -2
  685. package/src/SchemaTransformation.ts +10 -5
  686. package/src/ScopedCache.ts +5 -9
  687. package/src/Semaphore.ts +141 -0
  688. package/src/Stream.ts +15 -6
  689. package/src/Terminal.ts +19 -1
  690. package/src/ai/AiError.ts +56 -80
  691. package/src/ai/Decision.ts +257 -6
  692. package/src/ai/DecisionModel.ts +171 -28
  693. package/src/ai/McpClient.ts +488 -91
  694. package/src/ai/McpSchema.ts +119 -0
  695. package/src/ai/McpServer.ts +1525 -319
  696. package/src/ai/McpTest.ts +380 -0
  697. package/src/ai/Prompt.ts +16 -11
  698. package/src/ai/Response.ts +2 -22
  699. package/src/ai/Tool.ts +32 -18
  700. package/src/ai/index.ts +6 -0
  701. package/src/ai/internal/mcpCore.ts +243 -56
  702. package/src/ai/internal/mcpProtocol/v2024_11_05.ts +7 -8
  703. package/src/ai/internal/mcpProtocol/v2025_03_26.ts +7 -8
  704. package/src/ai/internal/mcpProtocol/v2025_06_18.ts +7 -8
  705. package/src/ai/internal/mcpProtocol/v2025_11_25.ts +7 -8
  706. package/src/ai/internal/mcpProtocol/v2026_07_28.ts +56 -17
  707. package/src/ai/internal/mcpProtocol.ts +44 -0
  708. package/src/ai/internal/mcpRuntime.ts +15 -8
  709. package/src/ai/internal/mcpSkills.ts +480 -0
  710. package/src/ai/internal/mcpStatefulRuntime.ts +14 -2
  711. package/src/cli/Argument.ts +6 -0
  712. package/src/cli/CliOutput.ts +117 -49
  713. package/src/cli/Command.ts +23 -0
  714. package/src/cli/Flag.ts +107 -0
  715. package/src/cli/HelpDoc.ts +18 -1
  716. package/src/cli/Param.ts +6 -0
  717. package/src/cli/Primitive.ts +16 -1
  718. package/src/cli/Prompt.ts +1 -0
  719. package/src/cli/internal/help.ts +21 -9
  720. package/src/cluster/ClusterWorkflowEngine.ts +22 -8
  721. package/src/cluster/Reply.ts +1 -1
  722. package/src/cluster/Sharding.ts +96 -26
  723. package/src/cluster/ShardingConfig.ts +41 -3
  724. package/src/cluster/SingleRunner.ts +3 -3
  725. package/src/cluster/SqlMessageStorage.ts +49 -17
  726. package/src/cluster/SqlRunnerStorage.ts +37 -27
  727. package/src/cluster/internal/entityManager.ts +24 -10
  728. package/src/crypto/Aead.ts +517 -0
  729. package/src/crypto/Cipher.ts +326 -0
  730. package/src/crypto/CryptoError.ts +242 -0
  731. package/src/crypto/Digest.ts +167 -0
  732. package/src/crypto/Kdf.ts +315 -0
  733. package/src/crypto/KeyAgreement.ts +489 -0
  734. package/src/crypto/KeyFormat.ts +741 -0
  735. package/src/crypto/KeyWrap.ts +639 -0
  736. package/src/crypto/Mac.ts +386 -0
  737. package/src/crypto/SecureRandom.ts +459 -0
  738. package/src/crypto/Signature.ts +673 -0
  739. package/src/crypto/WebCrypto.ts +84 -0
  740. package/src/crypto/index.ts +78 -0
  741. package/src/crypto/internal/asymmetric.ts +330 -0
  742. package/src/crypto/internal/chacha.ts +1088 -0
  743. package/src/crypto/internal/der.ts +110 -0
  744. package/src/crypto/internal/digest.ts +16 -0
  745. package/src/crypto/internal/key.ts +242 -0
  746. package/src/crypto/internal/md5.ts +170 -0
  747. package/src/crypto/internal/webCrypto.ts +150 -0
  748. package/src/encoding/Base64Url.ts +32 -5
  749. package/src/encoding/Csv.ts +1298 -0
  750. package/src/encoding/Hex.ts +3 -2
  751. package/src/encoding/Ndjson.ts +6 -5
  752. package/src/encoding/SchemaBinary.ts +40 -4
  753. package/src/encoding/Sse.ts +5 -3
  754. package/src/encoding/Toml.ts +85 -20
  755. package/src/encoding/Yaml.ts +61 -18
  756. package/src/encoding/index.ts +6 -0
  757. package/src/eventlog/EventJournal.ts +4 -3
  758. package/src/eventlog/EventLog.ts +347 -15
  759. package/src/eventlog/EventLogEncryption.ts +118 -110
  760. package/src/eventlog/EventLogMessage.ts +273 -1
  761. package/src/eventlog/EventLogRemote.ts +367 -23
  762. package/src/eventlog/EventLogServer.ts +54 -20
  763. package/src/eventlog/EventLogServerEncrypted.ts +1135 -67
  764. package/src/eventlog/EventLogServerUnencrypted.ts +19 -2
  765. package/src/eventlog/EventLogSessionAuth.ts +82 -70
  766. package/src/eventlog/EventRow.ts +12 -3
  767. package/src/eventlog/SqlEventJournal.ts +2 -2
  768. package/src/eventlog/SqlEventLogServerEncrypted.ts +1244 -136
  769. package/src/eventlog/SqlEventLogServerUnencrypted.ts +2 -2
  770. package/src/eventlog/internal/batches.ts +30 -0
  771. package/src/eventlog/internal/compaction.ts +64 -0
  772. package/src/eventlog/internal/identityRootSecretDerivation.ts +93 -123
  773. package/src/eventlog/internal/remoteCompaction.ts +92 -0
  774. package/src/graphql/GraphQLClient.ts +3 -1
  775. package/src/graphql/GraphQLClientError.ts +15 -22
  776. package/src/graphql/GraphQLProtocol.ts +12 -3
  777. package/src/http/Cookies.ts +281 -1
  778. package/src/http/FetchHttpClient.ts +88 -16
  779. package/src/http/HttpClient.ts +299 -33
  780. package/src/http/HttpClientRequest.ts +12 -9
  781. package/src/http/HttpClientResponse.ts +3 -2
  782. package/src/http/HttpMethod.ts +10 -2
  783. package/src/http/HttpServerRequest.ts +76 -53
  784. package/src/http/HttpServerResponse.ts +3 -2
  785. package/src/http/HttpTraceContext.ts +7 -4
  786. package/src/http/ProblemDetails.ts +149 -0
  787. package/src/http/index.ts +6 -0
  788. package/src/http/internal/decompression.ts +4 -4
  789. package/src/http/internal/mimeTypes.ts +4 -1
  790. package/src/http/internal/urlParams.ts +8 -0
  791. package/src/http-api/HttpApiBuilder.ts +24 -12
  792. package/src/http-api/HttpApiClient.ts +67 -1
  793. package/src/http-api/HttpApiEndpoint.ts +14 -5
  794. package/src/http-api/HttpApiError.ts +250 -0
  795. package/src/http-api/HttpApiMiddleware.ts +95 -1
  796. package/src/http-api/HttpApiSchema.ts +106 -15
  797. package/src/index.ts +6 -6
  798. package/src/internal/dateTime.ts +54 -24
  799. package/src/internal/effect.ts +40 -18
  800. package/src/internal/glob.ts +952 -0
  801. package/src/internal/graphql.ts +27 -9
  802. package/src/internal/graphqlHeaders.ts +13 -0
  803. package/src/internal/matcher.ts +17 -0
  804. package/src/internal/persistence.ts +11 -0
  805. package/src/internal/rcRef.ts +4 -1
  806. package/src/internal/request.ts +51 -58
  807. package/src/internal/schema/fromJsonSchemaDocument.ts +11 -10
  808. package/src/internal/schema/toCodeDocument.ts +7 -3
  809. package/src/internal/trie.ts +43 -14
  810. package/src/internal/ulid.ts +44 -0
  811. package/src/internal/uuid.ts +57 -16
  812. package/src/internal/version.ts +1 -1
  813. package/src/jose/JoseError.ts +329 -0
  814. package/src/jose/Jwe.ts +196 -0
  815. package/src/jose/Jwk.ts +777 -0
  816. package/src/jose/Jwks.ts +418 -0
  817. package/src/jose/Jws.ts +312 -0
  818. package/src/jose/Jwt.ts +493 -0
  819. package/src/jose/index.ts +58 -0
  820. package/src/jose/internal/compact.ts +195 -0
  821. package/src/net/Host.ts +5 -10
  822. package/src/observability/Otlp.ts +21 -4
  823. package/src/observability/OtlpResource.ts +9 -1
  824. package/src/observability/OtlpSerialization.ts +13 -5
  825. package/src/observability/internal/otlpProtobuf.ts +6 -6
  826. package/src/observability/internal/protobuf.ts +10 -0
  827. package/src/persistence/CircuitBreaker.ts +113 -48
  828. package/src/persistence/KeyValueStore.ts +219 -22
  829. package/src/persistence/PersistedQueue.ts +128 -59
  830. package/src/persistence/Persistence.ts +20 -13
  831. package/src/persistence/RateLimiter.ts +84 -15
  832. package/src/persistence/index.ts +1 -1
  833. package/src/process/ChildProcess.ts +255 -260
  834. package/src/process/ChildProcessSpawner.ts +5 -0
  835. package/src/process/CommandLine.ts +630 -0
  836. package/src/process/index.ts +6 -0
  837. package/src/reactivity/Atom.ts +5 -5
  838. package/src/reactivity/AtomRegistry.ts +20 -9
  839. package/src/rpc/Rpc.ts +3 -1
  840. package/src/rpc/RpcClient.ts +94 -38
  841. package/src/rpc/RpcMessage.ts +13 -3
  842. package/src/rpc/RpcSerialization.ts +3 -0
  843. package/src/rpc/RpcServer.ts +176 -78
  844. package/src/schema/Model.ts +26 -3
  845. package/src/sql/Migrator.ts +38 -80
  846. package/src/sql/MigratorFileSystem.ts +71 -0
  847. package/src/sql/SqlClient.ts +45 -24
  848. package/src/sql/Statement.ts +60 -29
  849. package/src/sql/index.ts +1 -1
  850. package/src/testing/index.ts +0 -6
  851. package/src/workflow/Workflow.ts +4 -0
  852. package/src/workflow/WorkflowEngine.ts +5 -0
  853. package/src/workflow/internal/crypto.ts +15 -11
  854. package/dist/Crypto.d.ts +0 -244
  855. package/dist/Crypto.d.ts.map +0 -1
  856. package/dist/Crypto.js +0 -139
  857. package/dist/Crypto.js.map +0 -1
  858. package/dist/testing/TestCrypto.d.ts +0 -73
  859. package/dist/testing/TestCrypto.d.ts.map +0 -1
  860. package/dist/testing/TestCrypto.js +0 -87
  861. package/dist/testing/TestCrypto.js.map +0 -1
  862. package/src/Crypto.ts +0 -347
  863. package/src/testing/TestCrypto.ts +0 -94
@@ -14,8 +14,10 @@
14
14
  import * as Arr from "../Array.ts"
15
15
  import * as Cause from "../Cause.ts"
16
16
  import * as Context from "../Context.ts"
17
+ import * as Digest from "../crypto/Digest.ts"
17
18
  import * as Data from "../Data.ts"
18
19
  import * as Deferred from "../Deferred.ts"
20
+ import * as Duration from "../Duration.ts"
19
21
  import * as Effect from "../Effect.ts"
20
22
  import * as ErrorReporter from "../ErrorReporter.ts"
21
23
  import * as Exit from "../Exit.ts"
@@ -46,10 +48,13 @@ import * as SchemaAST from "../SchemaAST.ts"
46
48
  import * as Scope from "../Scope.ts"
47
49
  import type { Stdio } from "../Stdio.ts"
48
50
  import * as Stream from "../Stream.ts"
51
+ import * as Tracer from "../Tracer.ts"
52
+ import type * as Types from "../Types.ts"
49
53
  import * as AiError from "./AiError.ts"
50
54
  import * as McpCore from "./internal/mcpCore.ts"
51
55
  import * as McpProtocolInternal from "./internal/mcpProtocol.ts"
52
56
  import * as McpRuntime from "./internal/mcpRuntime.ts"
57
+ import * as McpSkills from "./internal/mcpSkills.ts"
53
58
  import * as InternalStructuredOutput from "./internal/structured-output.ts"
54
59
  import type * as McpProtocol from "./McpProtocol.ts"
55
60
  import * as McpSchema from "./McpSchema.ts"
@@ -103,8 +108,11 @@ interface QueuedServerNotification {
103
108
 
104
109
  const internalState = new WeakMap<object, {
105
110
  readonly core: McpCore.McpCore
111
+ // Registers a skill's own file, skipping the check that reserves it for the skill.
112
+ readonly addSkillFile: McpServer["Service"]["addResource"]
106
113
  readonly notifications: Queue.Dequeue<QueuedServerNotification>
107
114
  readonly notificationDelivery: { consumers: number; listChangeRevision: number; requestEndpoints: number }
115
+ readonly globalMiddleware: Array<middleware.Fn<any, any, any>>
108
116
  }>()
109
117
 
110
118
  // Request-scoped HTTP servers deliver a request's own notifications through
@@ -166,13 +174,29 @@ const toInternalServerNotification = (
166
174
  }
167
175
  }
168
176
 
169
- // Request services must come from the invocation, including when a handler is registered during a request.
170
- const omitRequestServices = Context.omit(
171
- McpRequestContext,
172
- McpServerClient,
173
- HttpServerRequest.HttpServerRequest,
174
- CurrentLogLevel
175
- )
177
+ const middlewareKeyPrefix = "effect/ai/McpServer/Middleware-"
178
+
179
+ // Do not capture request services or middleware stacks at registration.
180
+ const requestServiceKeys = new Set<string>([
181
+ McpRequestContext.key,
182
+ McpServerClient.key,
183
+ HttpServerRequest.HttpServerRequest.key,
184
+ HttpServerRequest.ParsedSearchParams.key,
185
+ HttpRouter.RouteContext.key,
186
+ CurrentLogLevel.key,
187
+ Scope.Scope.key,
188
+ Tracer.ParentSpan.key
189
+ ])
190
+
191
+ const omitRequestServices = <Services>(context: Context.Context<Services>): Context.Context<Services> => {
192
+ const services = new Map<string, any>()
193
+ for (const [key, value] of context.mapUnsafe) {
194
+ if (!requestServiceKeys.has(key) && !key.startsWith(middlewareKeyPrefix)) {
195
+ services.set(key, value)
196
+ }
197
+ }
198
+ return Context.makeUnsafe(services)
199
+ }
176
200
 
177
201
  const provideInvocationContext = <A, E, R>(
178
202
  effect: Effect.Effect<A, E, R>,
@@ -199,6 +223,714 @@ const provideInvocationContext = <A, E, R>(
199
223
  >
200
224
  }
201
225
 
226
+ // -----------------------------------------------------------------------------
227
+ // Request-level dependencies
228
+ // -----------------------------------------------------------------------------
229
+
230
+ /**
231
+ * Marks a request-level dependency of an MCP registration or middleware.
232
+ *
233
+ * **Details**
234
+ *
235
+ * Registrations carry handler dependencies as `McpRequest<"Requires", S>`.
236
+ * MCP middleware and transports discharge these markers; providing `S` with
237
+ * `Layer.provide` or `Effect.provide` does not.
238
+ *
239
+ * `layerHttp` and `layerHttpRequestScoped` convert the markers they don't
240
+ * discharge into `HttpRouter.Request` markers, so `HttpRouter.middleware` can
241
+ * satisfy them. On stdio and custom transports an undischarged marker is a
242
+ * compile error.
243
+ *
244
+ * @see {@link middleware} for discharging request-level dependencies
245
+ *
246
+ * @stability unstable
247
+ * @category utility types
248
+ * @since 4.0.0
249
+ */
250
+ export interface McpRequest<Kind extends string, T> {
251
+ readonly _: unique symbol
252
+ readonly kind: Kind
253
+ readonly type: T
254
+ }
255
+
256
+ /**
257
+ * Helper types for `McpRequest` markers.
258
+ *
259
+ * @stability unstable
260
+ * @category utility types
261
+ * @since 4.0.0
262
+ */
263
+ export declare namespace McpRequest {
264
+ /**
265
+ * Wraps each member of a union in an `McpRequest` marker of the supplied kind.
266
+ *
267
+ * @stability unstable
268
+ * @category utility types
269
+ * @since 4.0.0
270
+ */
271
+ export type From<Kind extends string, R> = R extends infer T ? McpRequest<Kind, T> : never
272
+
273
+ /**
274
+ * Extracts the services from `McpRequest` markers of the supplied kind.
275
+ *
276
+ * @stability unstable
277
+ * @category utility types
278
+ * @since 4.0.0
279
+ */
280
+ export type Only<Kind extends string, A> = A extends McpRequest<Kind, infer T> ? T : never
281
+
282
+ /**
283
+ * Removes `McpRequest` markers from a union.
284
+ *
285
+ * @stability unstable
286
+ * @category utility types
287
+ * @since 4.0.0
288
+ */
289
+ export type Without<A> = A extends McpRequest<infer _Kind, infer _> ? never : A
290
+ }
291
+
292
+ /**
293
+ * Opaque handler result. Middleware can wrap execution and provide services,
294
+ * but cannot inspect or replace the result.
295
+ *
296
+ * @stability unstable
297
+ * @category middleware
298
+ * @since 4.0.0
299
+ */
300
+ export interface MiddlewareSuccess {
301
+ readonly _: unique symbol
302
+ }
303
+
304
+ /**
305
+ * The request methods that run MCP middleware. More methods may be added, so
306
+ * don't `switch` on it exhaustively without a default case.
307
+ *
308
+ * @stability unstable
309
+ * @category middleware
310
+ * @since 4.0.0
311
+ */
312
+ export type MiddlewareMethod =
313
+ | "tools/call"
314
+ | "resources/read"
315
+ | "prompts/get"
316
+ | "completion/complete"
317
+ | "tools/list"
318
+ | "resources/list"
319
+ | "resources/templates/list"
320
+ | "prompts/list"
321
+ | "skills/list"
322
+ | "skills/get"
323
+ | "resources/directory/read"
324
+
325
+ /**
326
+ * Request metadata passed to MCP middleware.
327
+ *
328
+ * **Details**
329
+ *
330
+ * `target` is the tool name, the requested resource URI, or the prompt name.
331
+ * For `completion/complete` it is the prompt name, or the URI template of the
332
+ * resource template being completed. For `skills/get` it is the URI of the
333
+ * skill's `SKILL.md`. `payload` holds the request parameters.
334
+ *
335
+ * On list requests, middleware runs only when it wraps a {@link visibility},
336
+ * once for each registration it wraps. `target` is then the tool name, the
337
+ * resource URI, the URI template or the prompt name of that registration, and
338
+ * `payload` is `undefined`. `skills/list` and `resources/directory/read` are
339
+ * list requests whose `target` is the `SKILL.md` URI of each skill; a
340
+ * directory read checks only the skills that have the directory. A skill's
341
+ * files are resources, checked as `resources/list` and `resources/read` with
342
+ * their own URIs.
343
+ *
344
+ * `headers` are the HTTP request headers. They are empty on stdio, on custom
345
+ * transports and for in-process calls. `sessionId` is the `Mcp-Session-Id`
346
+ * header, so it is `undefined` outside sessionful HTTP.
347
+ *
348
+ * @stability unstable
349
+ * @category middleware
350
+ * @since 4.0.0
351
+ */
352
+ export interface MiddlewareOptions {
353
+ readonly method: MiddlewareMethod
354
+ readonly target: string
355
+ readonly payload: unknown
356
+ readonly requestContext: McpRequestContext["Service"]
357
+ readonly headers: Headers.Headers
358
+ readonly sessionId: string | undefined
359
+ }
360
+
361
+ const MiddlewareTypeId = "~effect/ai/McpServer/Middleware"
362
+
363
+ type MiddlewareConfig = {
364
+ provides: any
365
+ error: McpErrorBase
366
+ requires: any
367
+ layerError: any
368
+ layerRequires: any
369
+ }
370
+
371
+ type MiddlewareLayer<Config extends MiddlewareConfig, R> = Layer.Layer<
372
+ McpRequest.From<"Requires", Config["provides"]>,
373
+ Config["layerError"],
374
+ R | Config["layerRequires"] | McpRequest.From<"Requires", Config["requires"]>
375
+ >
376
+
377
+ /**
378
+ * Composable MCP middleware.
379
+ *
380
+ * **Details**
381
+ *
382
+ * Provide `layer` to registration layers, or to the Effect form of a
383
+ * registration, to run the middleware for those registrations. Use
384
+ * `layerGlobal` to run it for every request on the server.
385
+ *
386
+ * Services the middleware reads per request are `McpRequest<"Requires", S>`
387
+ * requirements of `layer` and `layerGlobal`, like the request-level
388
+ * dependencies of a registration. A middleware that provides `S` meets them
389
+ * when it runs outside this one: `a.combine(b)` runs `b` outside `a`, and so
390
+ * does providing `b.layer` or `b.layerGlobal` outside `a.layer`, though
391
+ * `layerGlobal` installs `b` for the whole server. The transport discharges
392
+ * the services it supplies, and `layerHttp` turns the rest into
393
+ * `HttpRouter.Request` requirements that an `HttpRouter.middleware` can meet.
394
+ *
395
+ * @see {@link middleware} for creating MCP middleware
396
+ *
397
+ * @stability unstable
398
+ * @category middleware
399
+ * @since 4.0.0
400
+ */
401
+ export interface Middleware<Config extends MiddlewareConfig> {
402
+ readonly [MiddlewareTypeId]: Config
403
+ readonly layer: MiddlewareLayer<Config, never>
404
+ readonly layerGlobal: MiddlewareLayer<Config, McpServer>
405
+ readonly combine: <Config2 extends MiddlewareConfig>(other: Middleware<Config2>) => Middleware<{
406
+ provides: Config2["provides"] | Config["provides"]
407
+ error: Config2["error"] | Config["error"]
408
+ requires: Exclude<Config["requires"], Config2["provides"]> | Config2["requires"]
409
+ layerError: Config["layerError"] | Config2["layerError"]
410
+ layerRequires: Config["layerRequires"] | Config2["layerRequires"]
411
+ }>
412
+ }
413
+
414
+ /**
415
+ * Creates MCP middleware that runs around `tools/call`, `resources/read`,
416
+ * `prompts/get` and `completion/complete` requests.
417
+ *
418
+ * **Details**
419
+ *
420
+ * Middleware is how request-level dependencies are satisfied: declare the
421
+ * services it provides with `middleware<{ provides: S }>()` and provide them to
422
+ * the handler effect. It receives the request headers, session id and request
423
+ * context, so it can resolve the current user per request.
424
+ *
425
+ * Pass a function, or an Effect that builds the function. Services the Effect
426
+ * reads are requirements of the middleware layer. Services the function reads
427
+ * per request, other than `McpRequestContext`, are per-request requirements
428
+ * of the result; see {@link Middleware} for how they are met.
429
+ *
430
+ * Failures must be `McpErrorBase` values. A middleware failure is sent as a
431
+ * JSON-RPC error with its `code`, `message` and `data`, never as a tool
432
+ * result. Pick custom codes from the implementation-defined range
433
+ * (-32000 to -32019): any numeric `code` is sent as is. Defects are logged,
434
+ * reported to the `ErrorReporter` and sent as `InternalError("Internal error")`.
435
+ * Interruption propagates.
436
+ *
437
+ * Local middleware runs inside global middleware, and middleware provided both
438
+ * locally and globally runs once. Middleware never runs for `initialize`. It
439
+ * runs for list requests only when it wraps a {@link visibility}, so that the
440
+ * visibility check can read the services it provides.
441
+ *
442
+ * **Example** (Resolving the current user per request)
443
+ *
444
+ * ```ts
445
+ * import { Context, Effect, Layer, Schema } from "effect"
446
+ * import { McpSchema, McpServer, Tool, Toolkit } from "effect/ai"
447
+ *
448
+ * class CurrentUser extends Context.Service<CurrentUser, { readonly id: string }>()("CurrentUser") {}
449
+ *
450
+ * class Unauthorized extends Schema.Error<Unauthorized>("Unauthorized")({
451
+ * ...McpSchema.McpErrorBase.fields,
452
+ * _tag: Schema.tag("Unauthorized"),
453
+ * code: Schema.tag(-32001)
454
+ * }) {}
455
+ *
456
+ * const WhoAmI = Tool.make("WhoAmI", { success: Schema.String, dependencies: [CurrentUser] })
457
+ * const Tools = Toolkit.make(WhoAmI)
458
+ *
459
+ * const Auth = McpServer.middleware<{ provides: CurrentUser }>()((effect, { headers }) => {
460
+ * const token = headers["authorization"]
461
+ * return token === undefined
462
+ * ? Effect.fail(new Unauthorized({ message: "Missing credentials" }))
463
+ * : Effect.provideService(effect, CurrentUser, { id: token })
464
+ * })
465
+ *
466
+ * const Registrations = McpServer.toolkit(Tools).pipe(
467
+ * Layer.provide(Auth.layer),
468
+ * Layer.provide(Tools.toLayer({
469
+ * WhoAmI: () => Effect.map(CurrentUser, (user) => user.id)
470
+ * }))
471
+ * )
472
+ * ```
473
+ *
474
+ * @stability unstable
475
+ * @category middleware
476
+ * @since 4.0.0
477
+ */
478
+ export const middleware:
479
+ & middleware.Make<never>
480
+ & (<Config extends { provides?: any } = {}>() => middleware.Make<
481
+ Config extends { provides: infer P } ? P : never
482
+ >) = function() {
483
+ if (arguments.length === 0) {
484
+ return makeMiddleware as any
485
+ }
486
+ return makeMiddleware(arguments[0], arguments[1]) as any
487
+ }
488
+
489
+ /**
490
+ * Types used by `middleware`.
491
+ *
492
+ * @stability unstable
493
+ * @category middleware
494
+ * @since 4.0.0
495
+ */
496
+ export declare namespace middleware {
497
+ /**
498
+ * The middleware function.
499
+ *
500
+ * @stability unstable
501
+ * @category middleware
502
+ * @since 4.0.0
503
+ */
504
+ export type Fn<Provides, E, R> = (
505
+ effect: Effect.Effect<MiddlewareSuccess, McpErrorBase, Types.NoInfer<Provides>>,
506
+ options: MiddlewareOptions
507
+ ) => Effect.Effect<MiddlewareSuccess, E, R>
508
+
509
+ /**
510
+ * The overloads of a middleware constructor.
511
+ *
512
+ * @stability unstable
513
+ * @category middleware
514
+ * @since 4.0.0
515
+ */
516
+ export type Make<Provides> = {
517
+ <E extends McpErrorBase, R, EX, RX, const Global extends boolean = false>(
518
+ middleware: Effect.Effect<Fn<Provides, E, R>, EX, RX>,
519
+ options?: { readonly global?: Global | undefined }
520
+ ): Made<Global, {
521
+ provides: Provides
522
+ error: E
523
+ requires: Exclude<R, McpRequestContext>
524
+ layerError: EX
525
+ layerRequires: Exclude<RX, Scope.Scope>
526
+ }>
527
+ <E extends McpErrorBase, R, const Global extends boolean = false>(
528
+ middleware: Fn<Provides, E, R>,
529
+ options?: { readonly global?: Global | undefined }
530
+ ): Made<Global, {
531
+ provides: Provides
532
+ error: E
533
+ requires: Exclude<R, McpRequestContext>
534
+ layerError: never
535
+ layerRequires: never
536
+ }>
537
+ }
538
+ }
539
+
540
+ /**
541
+ * Creates middleware that hides registrations per request.
542
+ *
543
+ * **Details**
544
+ *
545
+ * The check runs for every registration the middleware is provided to, on list
546
+ * requests and on calls, reads, gets and completions. When it returns `false`
547
+ * the registration is left out of list results, and requests for it fail as if
548
+ * it was not registered.
549
+ *
550
+ * The result is a `Middleware` and composes like one. The check receives the
551
+ * same {@link MiddlewareOptions} as middleware, and services it reads per
552
+ * request, other than `McpRequestContext`, are met the same way. Scope a
553
+ * visibility to some tools by providing its layer to their toolkit only, or
554
+ * branch on `target`.
555
+ *
556
+ * On a list request, the check and the middleware outside the innermost
557
+ * visibility run once for each registration. Middleware inside it does not
558
+ * run. A failure of that middleware or of a check fails the whole list
559
+ * request. It never hides a registration.
560
+ *
561
+ * Unlike `EnabledWhen`, a visibility runs the middleware around it on list
562
+ * requests, and middleware sees requests for hidden registrations.
563
+ *
564
+ * **Example** (Hiding admin tools from other users)
565
+ *
566
+ * ```ts
567
+ * import { Context, Effect, Layer, Schema } from "effect"
568
+ * import { McpServer, Tool, Toolkit } from "effect/ai"
569
+ *
570
+ * class CurrentUser extends Context.Service<CurrentUser, { readonly isAdmin: boolean }>()("CurrentUser") {}
571
+ *
572
+ * const AdminTools = Toolkit.make(Tool.make("DeleteUser", { success: Schema.String }))
573
+ *
574
+ * const Auth = McpServer.middleware<{ provides: CurrentUser }>()((effect, { headers }) =>
575
+ * Effect.provideService(effect, CurrentUser, { isAdmin: headers["x-role"] === "admin" })
576
+ * )
577
+ * const AdminOnly = McpServer.visibility(() => Effect.map(CurrentUser, (user) => user.isAdmin))
578
+ *
579
+ * const Registrations = McpServer.toolkit(AdminTools).pipe(
580
+ * Layer.provide(AdminOnly.combine(Auth).layer),
581
+ * Layer.provide(AdminTools.toLayer({ DeleteUser: () => Effect.succeed("deleted") }))
582
+ * )
583
+ * ```
584
+ *
585
+ * @see {@link middleware} for providing the services a check reads
586
+ *
587
+ * @stability unstable
588
+ * @category middleware
589
+ * @since 4.0.0
590
+ */
591
+ export const visibility: visibility.Make = ((
592
+ check: AnyVisibilityCheck | Effect.Effect<AnyVisibilityCheck, any, any>,
593
+ options?: { readonly global?: boolean | undefined }
594
+ ) => makeMiddleware(Effect.isEffect(check) ? Effect.map(check, makeGate) : makeGate(check), options)) as any
595
+
596
+ /**
597
+ * Types used by `visibility`.
598
+ *
599
+ * @stability unstable
600
+ * @category middleware
601
+ * @since 4.0.0
602
+ */
603
+ export declare namespace visibility {
604
+ /**
605
+ * The visibility check.
606
+ *
607
+ * @stability unstable
608
+ * @category middleware
609
+ * @since 4.0.0
610
+ */
611
+ export type Check<E, R> = (options: MiddlewareOptions) => Effect.Effect<boolean, E, R>
612
+
613
+ /**
614
+ * The overloads of `visibility`.
615
+ *
616
+ * @stability unstable
617
+ * @category middleware
618
+ * @since 4.0.0
619
+ */
620
+ export type Make = {
621
+ <E extends McpErrorBase, R, EX, RX, const Global extends boolean = false>(
622
+ check: Effect.Effect<Check<E, R>, EX, RX>,
623
+ options?: { readonly global?: Global | undefined }
624
+ ): Made<Global, {
625
+ provides: never
626
+ error: E
627
+ requires: Exclude<R, McpRequestContext>
628
+ layerError: EX
629
+ layerRequires: Exclude<RX, Scope.Scope>
630
+ }>
631
+ <E extends McpErrorBase, R, const Global extends boolean = false>(
632
+ check: Check<E, R>,
633
+ options?: { readonly global?: Global | undefined }
634
+ ): Made<Global, {
635
+ provides: never
636
+ error: E
637
+ requires: Exclude<R, McpRequestContext>
638
+ layerError: never
639
+ layerRequires: never
640
+ }>
641
+ }
642
+ }
643
+
644
+ type AnyVisibilityCheck = visibility.Check<any, any>
645
+
646
+ // Raised by a visibility gate. It is left out of the types because `makeInvoke`
647
+ // replaces it with the not-found error of the request. It still has the shape
648
+ // of an MCP error, since middleware outside the gate sees it as one.
649
+ class Hidden extends Data.TaggedError("effect/ai/McpServer/Hidden")<{
650
+ readonly code: number
651
+ readonly message: string
652
+ }> {}
653
+
654
+ const failHidden = Effect.fail(
655
+ new Hidden({ code: McpSchema.INVALID_PARAMS_ERROR_CODE, message: "Not found" })
656
+ ) as Effect.Effect<never>
657
+
658
+ // Marks the middleware functions created by `visibility`.
659
+ const gates = new WeakSet<AnyMiddlewareFn>()
660
+
661
+ const makeGate = (check: AnyVisibilityCheck): AnyMiddlewareFn => {
662
+ const gate: AnyMiddlewareFn = (effect, options) =>
663
+ Effect.flatMap(check(options), (visible) => visible ? effect : failHidden)
664
+ gates.add(gate)
665
+ return gate
666
+ }
667
+
668
+ type Made<Global extends boolean, Config extends MiddlewareConfig> = Global extends true
669
+ ? MiddlewareLayer<Config, McpServer>
670
+ : Middleware<Config>
671
+
672
+ type AnyMiddlewareFn = middleware.Fn<any, any, any>
673
+
674
+ class MiddlewareFn extends Context.Service<MiddlewareFn, AnyMiddlewareFn>()("effect/ai/McpServer/MiddlewareFn") {}
675
+
676
+ const makeMiddleware = (
677
+ fn: AnyMiddlewareFn | Effect.Effect<AnyMiddlewareFn, any, any>,
678
+ options?: { readonly global?: boolean | undefined }
679
+ ) => {
680
+ const middleware = new MiddlewareImpl(
681
+ Effect.isEffect(fn) ? Layer.effect(MiddlewareFn)(fn) : Layer.succeed(MiddlewareFn, fn)
682
+ )
683
+ return options?.global ? middleware.layerGlobal : middleware
684
+ }
685
+
686
+ let middlewareId = 0
687
+
688
+ class MiddlewareImpl {
689
+ readonly [MiddlewareTypeId] = {} as any
690
+ readonly layer: Layer.Layer<never, any, any>
691
+ readonly layerGlobal: Layer.Layer<never, any, any>
692
+ readonly layerFn: Layer.Layer<MiddlewareFn, any, any>
693
+ readonly dependencies: Layer.Layer<any, any, any> | undefined
694
+
695
+ constructor(
696
+ layerFn: Layer.Layer<MiddlewareFn, any, any>,
697
+ dependencies?: Layer.Layer<any, any, any> | undefined
698
+ ) {
699
+ this.layerFn = layerFn
700
+ this.dependencies = dependencies
701
+ const contextKey = `${middlewareKeyPrefix}${++middlewareId}`
702
+ this.layer = Layer.effectContext(Effect.gen(function*() {
703
+ const stack: Array<AnyMiddlewareFn> = [yield* MiddlewareFn]
704
+ if (dependencies) {
705
+ const memoMap = yield* Layer.CurrentMemoMap
706
+ const scope = yield* Effect.scope
707
+ stack.push(...getMiddleware(yield* Layer.buildWithMemoMap(dependencies, memoMap, scope)))
708
+ }
709
+ return Context.makeUnsafe<never>(new Map([[contextKey, stack]]))
710
+ })).pipe(Layer.provide(layerFn))
711
+ this.layerGlobal = Layer.effectDiscard(Effect.gen(function*() {
712
+ const stack: ReadonlyArray<AnyMiddlewareFn> = Context.getOrUndefinedUnsafe(
713
+ yield* Effect.context<never>(),
714
+ contextKey as any
715
+ )!
716
+ const { globalMiddleware } = internalState.get(yield* McpServer)!
717
+ yield* Effect.acquireRelease(
718
+ Effect.sync(() => {
719
+ globalMiddleware.push(...stack)
720
+ }),
721
+ () =>
722
+ Effect.sync(() => {
723
+ for (const fn of stack) {
724
+ const index = globalMiddleware.indexOf(fn)
725
+ if (index !== -1) globalMiddleware.splice(index, 1)
726
+ }
727
+ })
728
+ )
729
+ })).pipe(Layer.provide(this.layer))
730
+ }
731
+
732
+ combine(other: Middleware<any>): Middleware<any> {
733
+ return new MiddlewareImpl(
734
+ this.layerFn,
735
+ this.dependencies ? Layer.provideMerge(this.dependencies, other.layer as any) : other.layer as any
736
+ ) as any
737
+ }
738
+ }
739
+
740
+ // The innermost middleware comes first.
741
+ const getMiddleware = (context: Context.Context<never>): ReadonlyArray<AnyMiddlewareFn> => {
742
+ const stacks: Array<ReadonlyArray<AnyMiddlewareFn>> = []
743
+ let maxLength = 0
744
+ for (const [key, value] of context.mapUnsafe) {
745
+ if (key.startsWith(middlewareKeyPrefix)) {
746
+ stacks.push(value)
747
+ maxLength = Math.max(maxLength, value.length)
748
+ }
749
+ }
750
+ const unique = new Set<AnyMiddlewareFn>()
751
+ for (let i = maxLength - 1; i >= 0; i--) {
752
+ for (const stack of stacks) {
753
+ if (i < stack.length) unique.add(stack[i])
754
+ }
755
+ }
756
+ return Arr.fromIterable(unique).reverse()
757
+ }
758
+
759
+ const isMcpError = (error: unknown): error is McpErrorBase =>
760
+ Predicate.hasProperty(error, "code") && typeof error.code === "number" &&
761
+ Predicate.hasProperty(error, "message") && typeof error.message === "string"
762
+
763
+ // Distinguishes handler failures from failures raised or rewritten by middleware.
764
+ const HandlerFailure = Context.Reference<boolean>("effect/ai/McpServer/HandlerFailure", {
765
+ defaultValue: () => false
766
+ })
767
+ const handlerFailure = Context.make(HandlerFailure, true)
768
+
769
+ const internalError = new InternalError({ message: "Internal error" })
770
+
771
+ const rejectWith = (error: McpErrorBase) =>
772
+ Effect.fail(new McpCore.RequestRejected({ code: error.code, message: error.message, data: error.data, error }))
773
+
774
+ type CallMethod = "tools/call" | "resources/read" | "prompts/get" | "completion/complete" | "skills/get"
775
+
776
+ type ListMethod = Exclude<MiddlewareMethod, CallMethod>
777
+
778
+ interface NotFoundErrors {
779
+ readonly "tools/call": McpCore.ToolNotFound
780
+ readonly "resources/read": McpCore.ResourceNotFound
781
+ readonly "prompts/get": McpCore.PromptNotFound
782
+ readonly "completion/complete": InvalidParams
783
+ readonly "skills/get": McpCore.SkillNotFound
784
+ }
785
+
786
+ const notFound = (method: CallMethod, target: string): NotFoundErrors[CallMethod] => {
787
+ switch (method) {
788
+ case "tools/call":
789
+ return new McpCore.ToolNotFound({ name: target })
790
+ case "resources/read":
791
+ return new McpCore.ResourceNotFound({ uri: target })
792
+ case "prompts/get":
793
+ return new McpCore.PromptNotFound({ name: target })
794
+ case "completion/complete":
795
+ return new InvalidParams({ message: "Unknown completion reference or argument" })
796
+ case "skills/get":
797
+ return new McpCore.SkillNotFound({ uri: target })
798
+ }
799
+ }
800
+
801
+ const isHidden = (error: unknown): error is Hidden => error instanceof Hidden
802
+
803
+ // Recovers a request rejected by a visibility gate. Any other cause, including
804
+ // one that also holds an interrupt, is propagated unchanged.
805
+ const catchHidden =
806
+ <B, E2>(onHidden: () => Effect.Effect<B, E2>) =>
807
+ <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A | B, Exclude<E, Hidden> | E2, R> =>
808
+ Effect.catchCause(self, (cause): Effect.Effect<B, Exclude<E, Hidden> | E2> => {
809
+ const failure = Cause.findFail(cause)
810
+ return !Cause.hasInterrupts(cause) && Result.isSuccess(failure) && isHidden(failure.success.error)
811
+ ? onHidden()
812
+ : Effect.failCause(cause as Cause.Cause<Exclude<E, Hidden>>)
813
+ })
814
+
815
+ // The innermost middleware comes first. Middleware provided both locally and
816
+ // globally runs once, at its outermost position.
817
+ const middlewareStack = (
818
+ localMiddleware: ReadonlyArray<AnyMiddlewareFn>,
819
+ globalMiddleware: ReadonlyArray<AnyMiddlewareFn>
820
+ ): ReadonlyArray<AnyMiddlewareFn> => {
821
+ if (globalMiddleware.length === 0) {
822
+ return localMiddleware
823
+ }
824
+ if (localMiddleware.length === 0) {
825
+ return globalMiddleware
826
+ }
827
+ const stack = [...localMiddleware, ...globalMiddleware]
828
+ return stack.filter((fn, index) => stack.lastIndexOf(fn) === index)
829
+ }
830
+
831
+ // Runs a handler inside middleware. The handler's own failures pass through, a
832
+ // visibility gate fails with `Hidden`, and other failures become
833
+ // `RequestRejected`: middleware failures as JSON-RPC errors, anything else as
834
+ // a reported internal error.
835
+ const runMiddleware = <A, E>(
836
+ handler: Effect.Effect<A, E, any>,
837
+ middleware: ReadonlyArray<AnyMiddlewareFn>,
838
+ invocation: McpCore.McpInvocation,
839
+ request: Pick<MiddlewareOptions, "method" | "target" | "payload">
840
+ ): Effect.Effect<A, E | Hidden | McpCore.RequestRejected> => {
841
+ const effect = middleware.length === 0 ? handler : Effect.withFiber((fiber) => {
842
+ const headers = Context.getOrUndefined(fiber.context, HttpServerRequest.HttpServerRequest)?.headers ??
843
+ Headers.empty
844
+ const options: MiddlewareOptions = {
845
+ ...request,
846
+ requestContext: invocation.requestContext,
847
+ headers,
848
+ sessionId: headers[MCP_SESSION_ID_HEADER]
849
+ }
850
+ const handled = Effect.catchCause(handler, (cause) => Effect.failCause(Cause.annotate(cause, handlerFailure)))
851
+ return middleware.reduce((effect: Effect.Effect<any, any, any>, fn) => fn(effect, options), handled)
852
+ })
853
+ return provideInvocationContext(effect, invocation).pipe(
854
+ Effect.catchCause((cause): Effect.Effect<never, E | Hidden | McpCore.RequestRejected> => {
855
+ if (Cause.hasInterrupts(cause)) {
856
+ return Effect.failCause(cause)
857
+ }
858
+ const failure = Cause.findFail(cause)
859
+ if (Result.isSuccess(failure) && !Cause.hasDies(cause)) {
860
+ const error = failure.success.error
861
+ if (isHidden(error)) {
862
+ return Effect.fail(error)
863
+ }
864
+ if (middleware.length === 0 || Context.get(Cause.reasonAnnotations(failure.success), HandlerFailure)) {
865
+ return Effect.failCause(cause)
866
+ }
867
+ if (isMcpError(error)) {
868
+ return rejectWith(error)
869
+ }
870
+ }
871
+ return Effect.logError(cause).pipe(
872
+ Effect.andThen(ErrorReporter.report(cause)),
873
+ Effect.andThen(rejectWith(internalError))
874
+ )
875
+ })
876
+ ) as Effect.Effect<A, E | Hidden | McpCore.RequestRejected>
877
+ }
878
+
879
+ // Request services override captured services; global middleware wraps local middleware.
880
+ const makeInvoke = (
881
+ context: Context.Context<never> | undefined,
882
+ globalMiddleware: ReadonlyArray<AnyMiddlewareFn>
883
+ ) => {
884
+ const services = context === undefined ? Context.empty() : omitRequestServices(context)
885
+ const localMiddleware = context === undefined ? [] : getMiddleware(context)
886
+ const invoke = <A, E, M extends CallMethod>(
887
+ handler: Effect.Effect<A, E, any>,
888
+ invocation: McpCore.McpInvocation,
889
+ request: {
890
+ readonly method: M
891
+ readonly target: string
892
+ readonly payload: unknown
893
+ }
894
+ ): Effect.Effect<A, E | NotFoundErrors[M] | McpCore.RequestRejected> =>
895
+ runMiddleware(
896
+ services.mapUnsafe.size === 0
897
+ ? handler
898
+ : Effect.updateContext(handler, (context: Context.Context<any>) => Context.merge(services, context)),
899
+ middlewareStack(localMiddleware, globalMiddleware),
900
+ invocation,
901
+ request
902
+ ).pipe(
903
+ catchHidden(() => Effect.fail(notFound(request.method, request.target) as NotFoundErrors[M]))
904
+ ) as Effect.Effect<A, E | NotFoundErrors[M] | McpCore.RequestRejected>
905
+ // On list requests only the middleware outside the innermost visibility runs.
906
+ const visible = (method: ListMethod, target: string): McpCore.Visible => (invocation) => {
907
+ const middleware = middlewareStack(localMiddleware, globalMiddleware)
908
+ const innermost = middleware.findIndex((fn) => gates.has(fn))
909
+ if (innermost === -1) {
910
+ return Effect.succeed(true)
911
+ }
912
+ return runMiddleware(Effect.void, middleware.slice(innermost), invocation, { method, target, payload: undefined })
913
+ .pipe(
914
+ Effect.as(true),
915
+ catchHidden(() => Effect.succeed(false))
916
+ )
917
+ }
918
+ return { invoke, visible }
919
+ }
920
+
921
+ // Applies the `EnabledWhen` annotation of a registration.
922
+ const isEnabled = (annotations: Context.Context<never>) => {
923
+ const enabledWhen = Context.getOrUndefined(annotations, EnabledWhen)
924
+ return (profile: McpCore.NegotiatedProtocolProfile<string>): boolean =>
925
+ enabledWhen === undefined || enabledWhen({
926
+ protocolVersion: profile.protocolVersion,
927
+ capabilities: profile.clientCapabilities,
928
+ clientInfo: profile.clientInfo
929
+ })
930
+ }
931
+
932
+ const rejectedError = (rejected: McpCore.RequestRejected) => Effect.fail(rejected.error)
933
+
202
934
  /**
203
935
  * Service that stores and serves an MCP server's registered tools, resources,
204
936
  * prompts, completions, and outgoing notifications.
@@ -225,6 +957,7 @@ export class McpServer extends Context.Service<McpServer, {
225
957
  readonly addTool: (options: {
226
958
  readonly tool: McpTool
227
959
  readonly annotations: Context.Context<never>
960
+ readonly services?: Context.Context<never> | undefined
228
961
  readonly handle: (
229
962
  payload: any
230
963
  ) => Effect.Effect<
@@ -235,7 +968,7 @@ export class McpServer extends Context.Service<McpServer, {
235
968
  }) => Effect.Effect<void>
236
969
  readonly callTool: (
237
970
  requests: typeof CallTool.payloadSchema.Type
238
- ) => Effect.Effect<CallToolResult, InternalError | InvalidParams, McpServerClient>
971
+ ) => Effect.Effect<CallToolResult, McpErrorBase | InternalError | InvalidParams, McpServerClient>
239
972
 
240
973
  readonly resources: ReadonlyArray<{
241
974
  readonly resource: Resource
@@ -244,6 +977,7 @@ export class McpServer extends Context.Service<McpServer, {
244
977
  readonly addResource: (options: {
245
978
  readonly resource: Resource
246
979
  readonly annotations: Context.Context<never>
980
+ readonly services?: Context.Context<never> | undefined
247
981
  readonly handle: Effect.Effect<
248
982
  ReadResourceResult,
249
983
  InternalError,
@@ -259,6 +993,7 @@ export class McpServer extends Context.Service<McpServer, {
259
993
  options: {
260
994
  readonly template: ResourceTemplate
261
995
  readonly annotations: Context.Context<never>
996
+ readonly services?: Context.Context<never> | undefined
262
997
  readonly routerPath: string
263
998
  readonly completions: Record<
264
999
  string,
@@ -289,6 +1024,7 @@ export class McpServer extends Context.Service<McpServer, {
289
1024
  readonly addPrompt: (options: {
290
1025
  readonly prompt: Prompt
291
1026
  readonly annotations: Context.Context<never>
1027
+ readonly services?: Context.Context<never> | undefined
292
1028
  readonly completions: Record<
293
1029
  string,
294
1030
  (
@@ -302,11 +1038,11 @@ export class McpServer extends Context.Service<McpServer, {
302
1038
  }) => Effect.Effect<void>
303
1039
  readonly getPromptResult: (
304
1040
  request: typeof GetPrompt.payloadSchema.Type
305
- ) => Effect.Effect<GetPromptResult, InternalError | InvalidParams, McpServerClient>
1041
+ ) => Effect.Effect<GetPromptResult, McpErrorBase | InternalError | InvalidParams, McpServerClient>
306
1042
 
307
1043
  readonly completion: (
308
1044
  complete: typeof Complete.payloadSchema.Type
309
- ) => Effect.Effect<CompleteResult, InvalidParams | InternalError, McpServerClient>
1045
+ ) => Effect.Effect<CompleteResult, McpErrorBase | InvalidParams | InternalError, McpServerClient>
310
1046
  }>()("effect/ai/McpServer") {
311
1047
  /**
312
1048
  * Builds an MCP server service from registered tools, prompts, resources, and completions.
@@ -333,6 +1069,7 @@ export class McpServer extends Context.Service<McpServer, {
333
1069
  readonly annotations: Context.Context<never>
334
1070
  }> = []
335
1071
  const notificationsQueue = yield* Queue.make<QueuedServerNotification>()
1072
+ const globalMiddleware: Array<AnyMiddlewareFn> = []
336
1073
  const notificationDelivery = { consumers: 0, listChangeRevision: 0, requestEndpoints: 0 }
337
1074
  // With only request-scoped endpoints, no long-lived server ever takes from the shared queue.
338
1075
  const withoutSharedConsumer = () =>
@@ -405,6 +1142,38 @@ export class McpServer extends Context.Service<McpServer, {
405
1142
  ))
406
1143
  })
407
1144
 
1145
+ // Checking skill ownership and both writes happen in one synchronous step,
1146
+ // so a skill cannot claim the URI in between. Skill files skip the check.
1147
+ const addResource = (
1148
+ options: Parameters<McpServer["Service"]["addResource"]>[0],
1149
+ checkOwnership: boolean
1150
+ ): Effect.Effect<void> =>
1151
+ Effect.suspend(() => {
1152
+ if (checkOwnership && internalCore.skills.ownsFile(options.resource.uri)) {
1153
+ return Effect.die(
1154
+ new Cause.IllegalArgumentError(`Resource ${options.resource.uri} is a file of a registered skill`)
1155
+ )
1156
+ }
1157
+ const existingIndex = resources.findIndex(({ resource }) => resource.uri === options.resource.uri)
1158
+ if (existingIndex === -1) {
1159
+ resources.push(options)
1160
+ } else {
1161
+ resources[existingIndex] = options
1162
+ }
1163
+ const { invoke, visible } = makeInvoke(options.services, globalMiddleware)
1164
+ internalCore.resources.register({
1165
+ descriptor: options.resource,
1166
+ visible: visible("resources/list", options.resource.uri),
1167
+ isVisible: isEnabled(options.annotations),
1168
+ read: (invocation) =>
1169
+ invoke(options.handle, invocation, {
1170
+ method: "resources/read",
1171
+ target: options.resource.uri,
1172
+ payload: { uri: options.resource.uri }
1173
+ })
1174
+ })
1175
+ return notifications.client["notifications/resources/list_changed"]({})
1176
+ })
408
1177
  const service = McpServer.of({
409
1178
  notifications: notifications.client,
410
1179
  notifyElicitationComplete: ({ clientId, elicitationId }) =>
@@ -431,22 +1200,20 @@ export class McpServer extends Context.Service<McpServer, {
431
1200
  } else {
432
1201
  tools[existingIndex] = options
433
1202
  }
434
- const enabledWhen = Context.getOrUndefined(options.annotations, EnabledWhen)
1203
+ const { invoke, visible } = makeInvoke(options.services, globalMiddleware)
435
1204
  yield* internalCore.tools.register({
436
1205
  descriptor: new McpTool({
437
1206
  ...options.tool,
438
1207
  title: options.tool.title ?? options.tool.annotations?.title
439
1208
  }),
440
- isVisible: (profile) =>
441
- enabledWhen === undefined || enabledWhen(
442
- {
443
- protocolVersion: profile.protocolVersion,
444
- capabilities: profile.clientCapabilities,
445
- clientInfo: profile.clientInfo
446
- }
447
- ),
1209
+ visible: visible("tools/list", options.tool.name),
1210
+ isVisible: isEnabled(options.annotations),
448
1211
  handle: (call, invocation) =>
449
- provideInvocationContext(options.handle(call.arguments), invocation).pipe(
1212
+ invoke(options.handle(call.arguments), invocation, {
1213
+ method: "tools/call",
1214
+ target: call.name,
1215
+ payload: call
1216
+ }).pipe(
450
1217
  Effect.catchTags({
451
1218
  InternalError: (error) =>
452
1219
  Effect.fail(
@@ -481,12 +1248,14 @@ export class McpServer extends Context.Service<McpServer, {
481
1248
  request,
482
1249
  McpProtocolInternal.invocationFromClient(client)
483
1250
  ).pipe(
484
- Effect.mapError((error) =>
485
- new InvalidParams({
486
- message: error._tag === "ToolNotFound"
487
- ? `Tool '${error.name}' not found`
488
- : error.message
489
- })
1251
+ Effect.catch((error) =>
1252
+ error._tag === "RequestRejected" ? rejectedError(error) : Effect.fail(
1253
+ new InvalidParams({
1254
+ message: error._tag === "ToolNotFound"
1255
+ ? `Tool '${error.name}' not found`
1256
+ : error.message
1257
+ })
1258
+ )
490
1259
  )
491
1260
  )
492
1261
  if (result._tag === "InputRequired") {
@@ -500,87 +1269,74 @@ export class McpServer extends Context.Service<McpServer, {
500
1269
  get resourceTemplates() {
501
1270
  return resourceTemplates
502
1271
  },
503
- addResource: Effect.fnUntraced(function*(options) {
504
- const existingIndex = resources.findIndex(({ resource }) => resource.uri === options.resource.uri)
505
- if (existingIndex === -1) {
506
- resources.push(options)
507
- } else {
508
- resources[existingIndex] = options
509
- }
510
- yield* internalCore.resources.register({
511
- descriptor: options.resource,
512
- isVisible: (profile) => {
513
- const enabledWhen = Context.getOrUndefined(options.annotations, EnabledWhen)
514
- return enabledWhen === undefined || enabledWhen({
515
- protocolVersion: profile.protocolVersion,
516
- capabilities: profile.clientCapabilities,
517
- clientInfo: profile.clientInfo
518
- })
519
- },
520
- read: (invocation) => provideInvocationContext(options.handle, invocation)
521
- })
522
- yield* notifications.client["notifications/resources/list_changed"]({})
523
- }),
524
- addResourceTemplate: Effect.fnUntraced(function*({ annotations, completions, handle, routerPath, template }) {
525
- const existingIndex = resourceTemplates.findIndex(({ template: current }) =>
526
- current.uriTemplate === template.uriTemplate
527
- )
528
- if (existingIndex === -1) {
529
- resourceTemplates.push({ template, annotations })
530
- } else {
531
- resourceTemplates[existingIndex] = { template, annotations }
532
- }
533
- const templateMatcher = makeUriMatcher<true>()
534
- templateMatcher.add(routerPath, true)
535
- yield* internalCore.resources.registerTemplate({
536
- descriptor: template,
537
- isVisible: (profile) => {
538
- const enabledWhen = Context.getOrUndefined(annotations, EnabledWhen)
539
- return enabledWhen === undefined || enabledWhen({
540
- protocolVersion: profile.protocolVersion,
541
- capabilities: profile.clientCapabilities,
542
- clientInfo: profile.clientInfo
543
- })
544
- },
545
- match: (uri) => {
546
- const match = templateMatcher.find(uri)
547
- if (match === undefined) {
548
- return undefined
549
- }
550
- const params: Array<string> = []
551
- for (const key of Object.keys(match.params)) {
552
- params[Number(key)] = match.params[key]!
553
- }
554
- return params
555
- },
556
- read: (uri, params, invocation) => provideInvocationContext(handle(uri, Array.from(params)), invocation)
557
- })
558
- for (const [param, handle] of Object.entries(completions)) {
559
- yield* internalCore.completions.register(
560
- `resource/${template.uriTemplate}/${param}`,
561
- (request, invocation) =>
562
- provideInvocationContext(handle(request.argument.value, request.context), invocation).pipe(
563
- Effect.map((result) => ({
564
- values: result.completion.values,
565
- total: result.completion.total,
566
- hasMore: result.completion.hasMore,
567
- metadata: result._meta
568
- }))
569
- )
1272
+ addResource: (options) => addResource(options, true),
1273
+ addResourceTemplate: Effect.fnUntraced(
1274
+ function*({ annotations, completions, handle, routerPath, services, template }) {
1275
+ const existingIndex = resourceTemplates.findIndex(({ template: current }) =>
1276
+ current.uriTemplate === template.uriTemplate
570
1277
  )
1278
+ if (existingIndex === -1) {
1279
+ resourceTemplates.push({ template, annotations })
1280
+ } else {
1281
+ resourceTemplates[existingIndex] = { template, annotations }
1282
+ }
1283
+ const { invoke, visible } = makeInvoke(services, globalMiddleware)
1284
+ const templateMatcher = makeUriMatcher<true>()
1285
+ templateMatcher.add(routerPath, true)
1286
+ yield* internalCore.resources.registerTemplate({
1287
+ descriptor: template,
1288
+ visible: visible("resources/templates/list", template.uriTemplate),
1289
+ isVisible: isEnabled(annotations),
1290
+ match: (uri) => {
1291
+ const match = templateMatcher.find(uri)
1292
+ if (match === undefined) {
1293
+ return undefined
1294
+ }
1295
+ const params: Array<string> = []
1296
+ for (const key of Object.keys(match.params)) {
1297
+ params[Number(key)] = match.params[key]!
1298
+ }
1299
+ return params
1300
+ },
1301
+ read: (uri, params, invocation) =>
1302
+ invoke(handle(uri, Array.from(params)), invocation, {
1303
+ method: "resources/read",
1304
+ target: uri,
1305
+ payload: { uri }
1306
+ })
1307
+ })
1308
+ for (const [param, handle] of Object.entries(completions)) {
1309
+ yield* internalCore.completions.register(
1310
+ `resource/${template.uriTemplate}/${param}`,
1311
+ (request, invocation) =>
1312
+ invoke(handle(request.argument.value, request.context), invocation, {
1313
+ method: "completion/complete",
1314
+ target: template.uriTemplate,
1315
+ payload: request
1316
+ }).pipe(
1317
+ Effect.map((result) => ({
1318
+ values: result.completion.values,
1319
+ total: result.completion.total,
1320
+ hasMore: result.completion.hasMore,
1321
+ metadata: result._meta
1322
+ }))
1323
+ )
1324
+ )
1325
+ }
1326
+ yield* notifications.client["notifications/resources/list_changed"]({})
571
1327
  }
572
- yield* notifications.client["notifications/resources/list_changed"]({})
573
- }),
1328
+ ),
574
1329
  findResource: Effect.fnUntraced(function*(uri) {
575
1330
  const client = yield* McpServerClient
576
1331
  return yield* internalCore.resources.read(
577
1332
  uri,
578
1333
  McpProtocolInternal.invocationFromClient(client)
579
1334
  ).pipe(
580
- Effect.catchTag(
581
- "ResourceNotFound",
582
- (error) => Effect.fail(new InvalidParams({ message: `Resource '${error.uri}' not found` }))
583
- )
1335
+ Effect.catchTags({
1336
+ ResourceNotFound: (error) =>
1337
+ Effect.fail(new InvalidParams({ message: `Resource '${error.uri}' not found` })),
1338
+ RequestRejected: rejectedError
1339
+ })
584
1340
  )
585
1341
  }),
586
1342
  get prompts() {
@@ -593,18 +1349,17 @@ export class McpServer extends Context.Service<McpServer, {
593
1349
  } else {
594
1350
  prompts[existingIndex] = options
595
1351
  }
1352
+ const { invoke, visible } = makeInvoke(options.services, globalMiddleware)
596
1353
  yield* internalCore.prompts.register({
597
1354
  descriptor: options.prompt,
598
- isVisible: (profile) => {
599
- const enabledWhen = Context.getOrUndefined(options.annotations, EnabledWhen)
600
- return enabledWhen === undefined || enabledWhen({
601
- protocolVersion: profile.protocolVersion,
602
- capabilities: profile.clientCapabilities,
603
- clientInfo: profile.clientInfo
604
- })
605
- },
1355
+ visible: visible("prompts/list", options.prompt.name),
1356
+ isVisible: isEnabled(options.annotations),
606
1357
  get: (params, invocation) =>
607
- provideInvocationContext(options.handle(params), invocation).pipe(
1358
+ invoke(options.handle(params), invocation, {
1359
+ method: "prompts/get",
1360
+ target: options.prompt.name,
1361
+ payload: { name: options.prompt.name, arguments: params }
1362
+ }).pipe(
608
1363
  Effect.map((result) =>
609
1364
  Predicate.isTagged(result, "InputRequired")
610
1365
  ? McpCore.OperationOutcome.InputRequired(result)
@@ -616,7 +1371,11 @@ export class McpServer extends Context.Service<McpServer, {
616
1371
  yield* internalCore.completions.register(
617
1372
  `prompt/${options.prompt.name}/${param}`,
618
1373
  (request, invocation) =>
619
- provideInvocationContext(handle(request.argument.value, request.context), invocation).pipe(
1374
+ invoke(handle(request.argument.value, request.context), invocation, {
1375
+ method: "completion/complete",
1376
+ target: options.prompt.name,
1377
+ payload: request
1378
+ }).pipe(
620
1379
  Effect.map((result) => ({
621
1380
  values: result.completion.values,
622
1381
  total: result.completion.total,
@@ -635,7 +1394,10 @@ export class McpServer extends Context.Service<McpServer, {
635
1394
  params ?? {},
636
1395
  McpProtocolInternal.invocationFromClient(client)
637
1396
  ).pipe(
638
- Effect.catchTag("PromptNotFound", () => new InvalidParams({ message: `Prompt '${name}' not found` }))
1397
+ Effect.catchTags({
1398
+ PromptNotFound: () => new InvalidParams({ message: `Prompt '${name}' not found` }),
1399
+ RequestRejected: rejectedError
1400
+ })
639
1401
  )
640
1402
  return outcome._tag === "Complete"
641
1403
  ? outcome.value
@@ -650,7 +1412,9 @@ export class McpServer extends Context.Service<McpServer, {
650
1412
  : { type: "prompt", name: ref.name },
651
1413
  argument: complete.argument,
652
1414
  context: complete.context
653
- }, McpProtocolInternal.invocationFromClient(client))
1415
+ }, McpProtocolInternal.invocationFromClient(client)).pipe(
1416
+ Effect.catchTag("RequestRejected", rejectedError)
1417
+ )
654
1418
  return {
655
1419
  _meta: result.metadata,
656
1420
  completion: {
@@ -661,17 +1425,29 @@ export class McpServer extends Context.Service<McpServer, {
661
1425
  }
662
1426
  })
663
1427
  })
664
- internalState.set(service, { core: internalCore, notifications: notificationsQueue, notificationDelivery })
1428
+ internalState.set(service, {
1429
+ core: internalCore,
1430
+ addSkillFile: (options) => addResource(options, false),
1431
+ notifications: notificationsQueue,
1432
+ notificationDelivery,
1433
+ globalMiddleware
1434
+ })
665
1435
  return service
666
1436
  })
667
1437
 
668
1438
  /**
669
- * Layer that provides the MCP server and client services.
1439
+ * Layer that provides the MCP server service.
1440
+ *
1441
+ * **Details**
1442
+ *
1443
+ * It doesn't run a transport or discharge request-level dependencies. Use it
1444
+ * to call registrations in process, providing their request-level
1445
+ * dependencies with MCP middleware.
670
1446
  *
671
1447
  * @stability unstable
672
1448
  * @since 4.0.0
673
1449
  */
674
- static readonly layer: Layer.Layer<McpServer | McpServerClient> = Layer.effect(McpServer)(McpServer.make) as any
1450
+ static readonly layer: Layer.Layer<McpServer> = Layer.effect(McpServer)(McpServer.make)
675
1451
  }
676
1452
 
677
1453
  const MCP_SESSION_ID_HEADER = "mcp-session-id"
@@ -681,17 +1457,96 @@ const cancelledResponses = new WeakMap<object, string | number>()
681
1457
  const httpPostResponses = new WeakMap<HttpServerRequest.HttpServerRequest, { expected: number }>()
682
1458
  const requestKey = (requestId: string | number): string => `${typeof requestId}:${requestId}`
683
1459
 
684
- interface ActiveRequest {
685
- readonly requestId: RpcMessage.RequestId
686
- readonly prepared: McpRuntime.PreparedRequest
687
- readonly cancelled: boolean
688
- readonly httpPost: { expected: number } | undefined
1460
+ interface ActiveRequest {
1461
+ readonly requestId: RpcMessage.RequestId
1462
+ readonly prepared: McpRuntime.PreparedRequest
1463
+ readonly cancelled: boolean
1464
+ readonly httpPost: { expected: number } | undefined
1465
+ }
1466
+
1467
+ class McpClientKey extends Data.Class<{
1468
+ readonly clientId: number
1469
+ readonly profile: McpCore.NegotiatedProtocolProfile<string>
1470
+ }> {}
1471
+
1472
+ /**
1473
+ * A client cache hint for one kind of `v2026_07_28` result.
1474
+ *
1475
+ * **Details**
1476
+ *
1477
+ * `ttl` is how long a client may treat the result as fresh. It is sent as a
1478
+ * whole number of milliseconds, rounded down, so it must be finite,
1479
+ * nonnegative and at most `Number.MAX_SAFE_INTEGER` milliseconds. Only
1480
+ * `"private"` scope is supported, so shared caches must not store the result.
1481
+ *
1482
+ * @stability unstable
1483
+ * @category models
1484
+ * @since 4.1.0
1485
+ */
1486
+ export interface CacheHint {
1487
+ readonly ttl: Duration.Input
1488
+ readonly cacheScope: "private"
1489
+ }
1490
+
1491
+ /**
1492
+ * Client cache hints for `v2026_07_28` discovery and list results.
1493
+ *
1494
+ * **Details**
1495
+ *
1496
+ * Each entry sets the freshness and `cacheScope` of one result kind:
1497
+ * `server/discover`, `tools/list`, `resources/list`,
1498
+ * `resources/templates/list` and `prompts/list`. `skills` covers the Skills
1499
+ * extension's `skills/list`, `skills/get` and `resources/directory/read`.
1500
+ * Omitted entries, and `resources/read` results, keep
1501
+ * `{ ttlMs: 0, cacheScope: "private" }`. Earlier protocol revisions have no
1502
+ * cache hints and ignore this option.
1503
+ *
1504
+ * These are hints for clients. The server does not cache results, and
1505
+ * visibility and invocation checks still run on every request.
1506
+ *
1507
+ * **Gotchas**
1508
+ *
1509
+ * A positive `ttl` lets a client keep showing a list after registrations or
1510
+ * per-request visibility change, until the hint expires. Private scope does
1511
+ * not key a client's cache by user, so a client shared between users can
1512
+ * reuse one user's list for another.
1513
+ *
1514
+ * @stability unstable
1515
+ * @category models
1516
+ * @since 4.1.0
1517
+ */
1518
+ export interface CacheHints {
1519
+ readonly discover?: CacheHint | undefined
1520
+ readonly tools?: CacheHint | undefined
1521
+ readonly resources?: CacheHint | undefined
1522
+ readonly resourceTemplates?: CacheHint | undefined
1523
+ readonly prompts?: CacheHint | undefined
1524
+ readonly skills?: CacheHint | undefined
689
1525
  }
690
1526
 
691
- class McpClientKey extends Data.Class<{
692
- readonly clientId: number
693
- readonly profile: McpCore.NegotiatedProtocolProfile<string>
694
- }> {}
1527
+ // Converts each hint to the wire's nonnegative integer `ttlMs` once, when the server is built.
1528
+ const normalizeCacheHints = (
1529
+ cacheHints: CacheHints | undefined
1530
+ ): Effect.Effect<McpProtocolInternal.CacheHints | undefined, Cause.IllegalArgumentError> => {
1531
+ if (cacheHints === undefined) return Effect.succeed(undefined)
1532
+ const normalized: Record<string, { readonly ttlMs: number; readonly cacheScope: "private" }> = {}
1533
+ for (const [name, hint] of Object.entries(cacheHints)) {
1534
+ if (hint === undefined) continue
1535
+ const ttlMs = Option.match(Duration.fromInput(hint.ttl), {
1536
+ onNone: () => NaN,
1537
+ onSome: (ttl) => Math.floor(Duration.toMillis(ttl))
1538
+ })
1539
+ if (!Number.isSafeInteger(ttlMs) || ttlMs < 0 || hint.cacheScope !== "private") {
1540
+ return Effect.fail(
1541
+ new Cause.IllegalArgumentError(
1542
+ `McpServer cacheHints.${name} must have a finite, nonnegative ttl and a "private" cacheScope`
1543
+ )
1544
+ )
1545
+ }
1546
+ normalized[name] = { ttlMs, cacheScope: "private" }
1547
+ }
1548
+ return Effect.succeed(normalized)
1549
+ }
695
1550
 
696
1551
  /**
697
1552
  * Runs an MCP server over the current `RpcServer.Protocol`.
@@ -715,6 +1570,7 @@ export const run: (options: {
715
1570
  readonly icons?: ReadonlyArray<McpSchema.Icon> | undefined
716
1571
  readonly protocols: Arr.NonEmptyReadonlyArray<McpProtocol.ProtocolAdapter>
717
1572
  readonly extensions?: ServerExtensions | undefined
1573
+ readonly cacheHints?: CacheHints | undefined
718
1574
  }) => Effect.Effect<
719
1575
  never,
720
1576
  Cause.IllegalArgumentError,
@@ -728,12 +1584,14 @@ export const run: (options: {
728
1584
  readonly icons?: ReadonlyArray<McpSchema.Icon> | undefined
729
1585
  readonly protocols: Arr.NonEmptyReadonlyArray<McpProtocol.ProtocolAdapter>
730
1586
  readonly extensions?: ServerExtensions | undefined
1587
+ readonly cacheHints?: CacheHints | undefined
731
1588
  }) {
1589
+ const cacheHints = yield* normalizeCacheHints(options.cacheHints)
732
1590
  const runtimeOption = yield* Effect.serviceOption(McpRuntime.ServerRuntime)
733
1591
  const runtime = Option.isSome(runtimeOption)
734
1592
  ? runtimeOption.value
735
1593
  : yield* McpRuntime.make(options.protocols)
736
- return yield* runWithRuntime(options, runtime, "custom")
1594
+ return yield* runWithRuntime({ ...options, cacheHints }, runtime, "custom")
737
1595
  })
738
1596
 
739
1597
  const runWithRuntime = Effect.fnUntraced(function*(
@@ -745,6 +1603,7 @@ const runWithRuntime = Effect.fnUntraced(function*(
745
1603
  readonly websiteUrl?: string | undefined
746
1604
  readonly icons?: ReadonlyArray<McpSchema.Icon> | undefined
747
1605
  readonly extensions?: ServerExtensions | undefined
1606
+ readonly cacheHints?: McpProtocolInternal.CacheHints | undefined
748
1607
  readonly allowSubscriptions?: boolean | undefined
749
1608
  },
750
1609
  runtime: McpRuntime.ServerRuntimeShape,
@@ -1365,7 +2224,8 @@ const runWithRuntime = Effect.fnUntraced(function*(
1365
2224
  (requestContext?.clientId === clientId ? requestHeaders : undefined) ??
1366
2225
  clientStates.get(clientId)?.sessionHeaders ?? Headers.empty,
1367
2226
  notification,
1368
- defaultLogLevel
2227
+ defaultLogLevel,
2228
+ listChangeRevision
1369
2229
  )
1370
2230
  ) {
1371
2231
  return
@@ -1412,6 +2272,37 @@ const runWithRuntime = Effect.fnUntraced(function*(
1412
2272
  )
1413
2273
  }, Effect.scoped)
1414
2274
 
2275
+ type StatefulProtocolAdapter = McpProtocol.ProtocolAdapter<
2276
+ McpProtocol.ProtocolVersion,
2277
+ McpProtocol.StatefulRuntimeDescriptor
2278
+ >
2279
+
2280
+ /**
2281
+ * Request-level services supplied by a transport.
2282
+ *
2283
+ * **Details**
2284
+ *
2285
+ * Every transport supplies `Scope`. `McpServerClient` is supplied only when
2286
+ * every configured protocol is known to be sessionful: a `v2026_07_28` request
2287
+ * has no client session, and a protocol array widened to `ProtocolAdapter`
2288
+ * might contain one. HTTP transports also supply `HttpServerRequest`.
2289
+ *
2290
+ * @stability unstable
2291
+ * @category utility types
2292
+ * @since 4.0.0
2293
+ */
2294
+ export type ProvidedServices<
2295
+ Protocols extends ReadonlyArray<McpProtocol.ProtocolAdapter>,
2296
+ Http extends boolean = false
2297
+ > =
2298
+ | Scope.Scope
2299
+ | (Protocols[number] extends StatefulProtocolAdapter ? McpServerClient : never)
2300
+ | (Http extends true ? HttpServerRequest.HttpServerRequest : never)
2301
+
2302
+ type RemainingRequestServices<RR, Provided> = Exclude<McpRequest.Only<"Requires", RR>, Provided>
2303
+
2304
+ type RegistrationServices<RR> = Exclude<McpRequest.Without<RR>, McpServer>
2305
+
1415
2306
  /**
1416
2307
  * Creates a layer that starts an MCP server over an existing
1417
2308
  * `RpcServer.Protocol` and provides `McpServer`. Request handlers receive
@@ -1430,6 +2321,11 @@ const runWithRuntime = Effect.fnUntraced(function*(
1430
2321
  * `McpServer.layer`, so registration layers can use the `McpServer` service
1431
2322
  * while the server is running.
1432
2323
  *
2324
+ * Pass registration layers as `registrations` to build them before the server
2325
+ * reads its first request. The transport discharges the request-level
2326
+ * dependencies it supplies (see `ProvidedServices`); any other `McpRequest`
2327
+ * marker stays in the layer's requirements and must be met by MCP middleware.
2328
+ *
1433
2329
  * **Gotchas**
1434
2330
  *
1435
2331
  * Unlike `layerStdio` and `layerHttp`, this layer does not install a concrete
@@ -1443,19 +2339,32 @@ const runWithRuntime = Effect.fnUntraced(function*(
1443
2339
  * @category layers
1444
2340
  * @since 4.0.0
1445
2341
  */
1446
- export const layer = (options: {
2342
+ export const layer = <
2343
+ const Protocols extends Arr.NonEmptyReadonlyArray<McpProtocol.ProtocolAdapter>,
2344
+ RA = never,
2345
+ RE = never,
2346
+ RR = never
2347
+ >(options: {
1447
2348
  readonly name: string
1448
2349
  readonly version: string
1449
2350
  readonly instructions?: string | undefined
1450
2351
  readonly description?: string | undefined
1451
2352
  readonly websiteUrl?: string | undefined
1452
2353
  readonly icons?: ReadonlyArray<McpSchema.Icon> | undefined
1453
- readonly protocols: Arr.NonEmptyReadonlyArray<McpProtocol.ProtocolAdapter>
2354
+ readonly protocols: Protocols
1454
2355
  readonly extensions?: ServerExtensions | undefined
1455
- }): Layer.Layer<McpServer | McpServerClient, Cause.IllegalArgumentError, RpcServer.Protocol> =>
2356
+ readonly cacheHints?: CacheHints | undefined
2357
+ readonly registrations?: Layer.Layer<RA, RE, RR> | undefined
2358
+ }): Layer.Layer<
2359
+ McpServer | McpRequest.From<"Requires", ProvidedServices<Protocols>>,
2360
+ Cause.IllegalArgumentError | RE,
2361
+ | RpcServer.Protocol
2362
+ | RegistrationServices<RR>
2363
+ | McpRequest.From<"Requires", RemainingRequestServices<RR, ProvidedServices<Protocols>>>
2364
+ > =>
1456
2365
  layerWithRuntime(options, "custom").pipe(
1457
2366
  Layer.provide(McpRuntime.layer(options.protocols))
1458
- )
2367
+ ) as any
1459
2368
 
1460
2369
  const layerWithRuntime = (options: {
1461
2370
  readonly name: string
@@ -1465,18 +2374,18 @@ const layerWithRuntime = (options: {
1465
2374
  readonly websiteUrl?: string | undefined
1466
2375
  readonly icons?: ReadonlyArray<McpSchema.Icon> | undefined
1467
2376
  readonly extensions?: ServerExtensions | undefined
2377
+ readonly cacheHints?: CacheHints | undefined
1468
2378
  readonly allowSubscriptions?: boolean | undefined
1469
- }, transport: "custom" | "http" | "stdio"): Layer.Layer<
1470
- McpServer | McpServerClient,
1471
- never,
1472
- RpcServer.Protocol | McpRuntime.ServerRuntime
1473
- > =>
2379
+ readonly registrations?: Layer.Layer<any, any, any> | undefined
2380
+ }, transport: "custom" | "http" | "stdio") =>
1474
2381
  Layer.effectDiscard(
1475
2382
  Effect.gen(function*() {
2383
+ const cacheHints = yield* normalizeCacheHints(options.cacheHints)
1476
2384
  const runtime = yield* McpRuntime.ServerRuntime
1477
- yield* Effect.forkScoped(runWithRuntime(options, runtime, transport))
2385
+ yield* Effect.forkScoped(runWithRuntime({ ...options, cacheHints }, runtime, transport))
1478
2386
  })
1479
2387
  ).pipe(
2388
+ Layer.provide(options.registrations ?? Layer.empty),
1480
2389
  Layer.provideMerge(McpServer.layer)
1481
2390
  )
1482
2391
 
@@ -1495,6 +2404,11 @@ const layerWithRuntime = (options: {
1495
2404
  * `McpRequestContext` and legacy `McpServerClient` services to handlers, and
1496
2405
  * requires `Stdio`.
1497
2406
  *
2407
+ * Pass registration layers as `registrations` to build them before the server
2408
+ * reads its first request. The transport discharges the request-level
2409
+ * dependencies it supplies (see `ProvidedServices`); any other `McpRequest`
2410
+ * marker stays in the layer's requirements and must be met by MCP middleware.
2411
+ *
1498
2412
  * @see {@link layer} for running over an existing `RpcServer.Protocol`
1499
2413
  * @see {@link layerHttp} for the single-endpoint HTTP transport
1500
2414
  *
@@ -1502,16 +2416,29 @@ const layerWithRuntime = (options: {
1502
2416
  * @category layers
1503
2417
  * @since 4.0.0
1504
2418
  */
1505
- export const layerStdio = (options: {
2419
+ export const layerStdio = <
2420
+ const Protocols extends Arr.NonEmptyReadonlyArray<McpProtocol.ProtocolAdapter>,
2421
+ RA = never,
2422
+ RE = never,
2423
+ RR = never
2424
+ >(options: {
1506
2425
  readonly name: string
1507
2426
  readonly version: string
1508
2427
  readonly instructions?: string | undefined
1509
2428
  readonly description?: string | undefined
1510
2429
  readonly websiteUrl?: string | undefined
1511
2430
  readonly icons?: ReadonlyArray<McpSchema.Icon> | undefined
1512
- readonly protocols: Arr.NonEmptyReadonlyArray<McpProtocol.ProtocolAdapter>
2431
+ readonly protocols: Protocols
1513
2432
  readonly extensions?: ServerExtensions | undefined
1514
- }): Layer.Layer<McpServer | McpServerClient, Cause.IllegalArgumentError, Stdio> =>
2433
+ readonly cacheHints?: CacheHints | undefined
2434
+ readonly registrations?: Layer.Layer<RA, RE, RR> | undefined
2435
+ }): Layer.Layer<
2436
+ McpServer | McpRequest.From<"Requires", ProvidedServices<Protocols>>,
2437
+ Cause.IllegalArgumentError | RE,
2438
+ | Stdio
2439
+ | RegistrationServices<RR>
2440
+ | McpRequest.From<"Requires", RemainingRequestServices<RR, ProvidedServices<Protocols>>>
2441
+ > =>
1515
2442
  layerWithRuntime(options, "stdio").pipe(
1516
2443
  Layer.provide(McpRuntime.layer(options.protocols)),
1517
2444
  Layer.provide(RpcServer.layerProtocolStdio),
@@ -1519,7 +2446,7 @@ export const layerStdio = (options: {
1519
2446
  RpcSerialization.RpcSerialization,
1520
2447
  mcpStdioSerialization(options.protocols)
1521
2448
  ))
1522
- )
2449
+ ) as any
1523
2450
 
1524
2451
  const mcpStdioSerialization = (
1525
2452
  protocols: Arr.NonEmptyReadonlyArray<McpProtocol.ProtocolAdapter>
@@ -1621,6 +2548,13 @@ const mcpStdioSerialization = (
1621
2548
  * serverless hosts where execution must belong to each request, use
1622
2549
  * `layerHttpRequestScoped` instead.
1623
2550
  *
2551
+ * Pass registration layers as `registrations` to build them before the
2552
+ * endpoint serves its first request. The transport discharges the
2553
+ * request-level dependencies it supplies (see `ProvidedServices`) and converts
2554
+ * the remaining `McpRequest` markers into `HttpRouter.Request` markers, so
2555
+ * `HttpRouter.middleware` can provide them, for example to authenticate the
2556
+ * request and resolve the current user.
2557
+ *
1624
2558
  * `layerHttp` always implements the single-endpoint Streamable HTTP topology.
1625
2559
  * Using `v2024_11_05` here is a custom compatibility transport for that
1626
2560
  * revision's schema. It does not implement the historical two-endpoint
@@ -1638,7 +2572,12 @@ const mcpStdioSerialization = (
1638
2572
  * @category layers
1639
2573
  * @since 4.0.0
1640
2574
  */
1641
- export const layerHttp = (options: {
2575
+ export const layerHttp = <
2576
+ const Protocols extends Arr.NonEmptyReadonlyArray<McpProtocol.ProtocolAdapter>,
2577
+ RA = never,
2578
+ RE = never,
2579
+ RR = never
2580
+ >(options: {
1642
2581
  readonly name: string
1643
2582
  readonly version: string
1644
2583
  readonly instructions?: string | undefined
@@ -1646,18 +2585,26 @@ export const layerHttp = (options: {
1646
2585
  readonly websiteUrl?: string | undefined
1647
2586
  readonly icons?: ReadonlyArray<McpSchema.Icon> | undefined
1648
2587
  readonly path: HttpRouter.PathInput
1649
- readonly protocols: Arr.NonEmptyReadonlyArray<McpProtocol.ProtocolAdapter>
2588
+ readonly protocols: Protocols
1650
2589
  readonly extensions?: ServerExtensions | undefined
2590
+ readonly cacheHints?: CacheHints | undefined
1651
2591
  readonly allowedOrigins?: ReadonlyArray<string> | undefined
1652
2592
  readonly allowSessionTermination?: boolean | undefined
1653
2593
  readonly allowSubscriptions?: boolean | undefined
1654
- }): Layer.Layer<McpServer | McpServerClient, Cause.IllegalArgumentError, HttpRouter.HttpRouter> => {
2594
+ readonly registrations?: Layer.Layer<RA, RE, RR> | undefined
2595
+ }): Layer.Layer<
2596
+ McpServer | McpRequest.From<"Requires", ProvidedServices<Protocols, true>>,
2597
+ Cause.IllegalArgumentError | RE,
2598
+ | HttpRouter.HttpRouter
2599
+ | RegistrationServices<RR>
2600
+ | HttpRouter.Request.From<"Requires", RemainingRequestServices<RR, ProvidedServices<Protocols, true>>>
2601
+ > => {
1655
2602
  const runtime = McpRuntime.layer(options.protocols)
1656
2603
  return layerWithRuntime(options, "http").pipe(
1657
2604
  Layer.provide(layerMcpProtocolHttp(options)),
1658
2605
  Layer.provide(runtime),
1659
2606
  Layer.provide(RpcSerialization.layerJsonRpc())
1660
- )
2607
+ ) as any
1661
2608
  }
1662
2609
 
1663
2610
  /**
@@ -1688,13 +2635,24 @@ export const layerHttp = (options: {
1688
2635
  * Configuring a sessionful protocol through an untyped caller fails layer
1689
2636
  * construction with `IllegalArgumentError`.
1690
2637
  *
2638
+ * Registrations passed as `registrations` are built once, before the routes
2639
+ * are added, and shared by every POST. Remaining `McpRequest` markers become
2640
+ * `HttpRouter.Request` markers, as with `layerHttp`.
2641
+ *
1691
2642
  * @see {@link layerHttp} for the long-lived HTTP transport and HTTP admission policy
1692
2643
  *
1693
2644
  * @stability unstable
1694
2645
  * @category layers
1695
2646
  * @since 4.0.0
1696
2647
  */
1697
- export const layerHttpRequestScoped = (options: {
2648
+ export const layerHttpRequestScoped = <
2649
+ const Protocols extends Arr.NonEmptyReadonlyArray<
2650
+ McpProtocol.ProtocolAdapter<McpProtocol.ProtocolVersion, McpProtocol.StatelessRuntimeDescriptor>
2651
+ >,
2652
+ RA = never,
2653
+ RE = never,
2654
+ RR = never
2655
+ >(options: {
1698
2656
  readonly name: string
1699
2657
  readonly version: string
1700
2658
  readonly instructions?: string | undefined
@@ -1702,12 +2660,18 @@ export const layerHttpRequestScoped = (options: {
1702
2660
  readonly websiteUrl?: string | undefined
1703
2661
  readonly icons?: ReadonlyArray<McpSchema.Icon> | undefined
1704
2662
  readonly path: HttpRouter.PathInput
1705
- readonly protocols: Arr.NonEmptyReadonlyArray<
1706
- McpProtocol.ProtocolAdapter<McpProtocol.ProtocolVersion, McpProtocol.StatelessRuntimeDescriptor>
1707
- >
2663
+ readonly protocols: Protocols
1708
2664
  readonly extensions?: ServerExtensions | undefined
2665
+ readonly cacheHints?: CacheHints | undefined
1709
2666
  readonly allowedOrigins?: ReadonlyArray<string> | undefined
1710
- }): Layer.Layer<McpServer | McpServerClient, Cause.IllegalArgumentError, HttpRouter.HttpRouter> =>
2667
+ readonly registrations?: Layer.Layer<RA, RE, RR> | undefined
2668
+ }): Layer.Layer<
2669
+ McpServer | McpRequest.From<"Requires", ProvidedServices<Protocols, true>>,
2670
+ Cause.IllegalArgumentError | RE,
2671
+ | HttpRouter.HttpRouter
2672
+ | RegistrationServices<RR>
2673
+ | HttpRouter.Request.From<"Requires", RemainingRequestServices<RR, ProvidedServices<Protocols, true>>>
2674
+ > =>
1711
2675
  Layer.effectDiscard(Effect.gen(function*() {
1712
2676
  const runtime = yield* McpRuntime.ServerRuntime
1713
2677
  const stateful = runtime.protocols.find((protocol) => protocol.runtime._tag === "Stateful")
@@ -1716,6 +2680,7 @@ export const layerHttpRequestScoped = (options: {
1716
2680
  `McpServer.layerHttpRequestScoped does not support the sessionful MCP protocol ${stateful.protocolVersion}`
1717
2681
  )
1718
2682
  }
2683
+ const serverOptions = { ...options, cacheHints: yield* normalizeCacheHints(options.cacheHints) }
1719
2684
  const server = yield* McpServer
1720
2685
  const { core, notificationDelivery } = internalState.get(server)!
1721
2686
  // Subscriptions are disabled, so handlers hold no per-request state and
@@ -1726,7 +2691,7 @@ export const layerHttpRequestScoped = (options: {
1726
2691
  subscribeServerNotifications: Effect.die("Subscriptions are disabled for request-scoped MCP servers"),
1727
2692
  getListChangeRevision: () => notificationDelivery.listChangeRevision,
1728
2693
  defaultLogLevel: yield* CurrentLogLevel,
1729
- serverInfo: options
2694
+ serverInfo: serverOptions
1730
2695
  }) as Effect.Effect<Context.Context<never>>)
1731
2696
  yield* Effect.acquireRelease(
1732
2697
  Effect.sync(() => {
@@ -1746,7 +2711,7 @@ export const layerHttpRequestScoped = (options: {
1746
2711
  Effect.provideService(RpcSerialization.RpcSerialization, mcpHttpSerialization)
1747
2712
  )
1748
2713
  const notifications = yield* Queue.make<QueuedServerNotification>()
1749
- yield* runWithRuntime(options, runtime, "http", { notifications, handlers }).pipe(
2714
+ yield* runWithRuntime(serverOptions, runtime, "http", { notifications, handlers }).pipe(
1750
2715
  Effect.provideService(RpcServer.Protocol, protocol),
1751
2716
  Effect.provideService(McpServer, server),
1752
2717
  Effect.forkScoped({ startImmediately: true })
@@ -1755,9 +2720,10 @@ export const layerHttpRequestScoped = (options: {
1755
2720
  })
1756
2721
  )
1757
2722
  })).pipe(
2723
+ Layer.provide(options.registrations ?? Layer.empty),
1758
2724
  Layer.provideMerge(McpServer.layer),
1759
2725
  Layer.provide(McpRuntime.layer(options.protocols))
1760
- )
2726
+ ) as any
1761
2727
 
1762
2728
  const layerMcpProtocolHttp = (options: {
1763
2729
  readonly path: HttpRouter.PathInput
@@ -2026,20 +2992,50 @@ const toolErrorResult = (message: string): CallToolResult =>
2026
2992
  const toolResultContent = (encoded: unknown): CallToolResult["content"] =>
2027
2993
  encoded === undefined ? [] : [{ type: "text", text: JSON.stringify(encoded) }]
2028
2994
 
2995
+ /**
2996
+ * The requirements of a toolkit registration.
2997
+ *
2998
+ * **Details**
2999
+ *
3000
+ * Services a tool declares with `dependencies` or `Tool.addDependency` are
3001
+ * request-level: they are carried as `McpRequest<"Requires", S>` markers and
3002
+ * must be provided by MCP middleware or the transport. Parameter decoding and
3003
+ * result encoding services are required when the toolkit is registered,
3004
+ * unless a tool also declares them.
3005
+ *
3006
+ * @stability unstable
3007
+ * @category utility types
3008
+ * @since 4.0.0
3009
+ */
3010
+ export type ToolkitRequirements<Tools extends Record<string, Tool.Any>> = 0 extends
3011
+ (1 & Tool.Requirements<Tools[keyof Tools]>) ? any :
3012
+ | Tool.HandlersFor<Tools>
3013
+ | RegistrationRequirements<Tool.SchemaServices<Tools[keyof Tools]>, Tool.Requirements<Tools[keyof Tools]>>
3014
+
3015
+ type RegistrationRequirements<SchemaServices, RequestServices> =
3016
+ | McpServer
3017
+ | Exclude<SchemaServices, RequestServices | McpRequestContext>
3018
+ | McpRequest.From<"Requires", Exclude<RequestServices, McpRequestContext>>
3019
+
2029
3020
  /**
2030
3021
  * Registers a `Toolkit` with the `McpServer`.
2031
3022
  *
3023
+ * **Details**
3024
+ *
3025
+ * The MCP middleware in the current context, provided with
3026
+ * `Effect.provide(middleware.layer)`, runs around every call to the toolkit.
3027
+ *
3028
+ * @see {@link ToolkitRequirements} for which services are request-level
3029
+ *
2032
3030
  * @stability unstable
2033
3031
  * @category handlers
2034
3032
  * @since 4.0.0
2035
3033
  */
2036
3034
  export const registerToolkit: <Tools extends Record<string, Tool.Any>>(
2037
3035
  toolkit: Toolkit.Toolkit<Tools>
2038
- ) => Effect.Effect<
2039
- void,
2040
- never,
2041
- McpServer | Tool.HandlersFor<Tools> | Exclude<Tool.HandlerServices<Tools[keyof Tools]>, McpRequestContext>
2042
- > = Effect.fnUntraced(function*<Tools extends Record<string, Tool.Any>>(
3036
+ ) => Effect.Effect<void, never, ToolkitRequirements<Tools>> = Effect.fnUntraced(function*<
3037
+ Tools extends Record<string, Tool.Any>
3038
+ >(
2043
3039
  toolkit: Toolkit.Toolkit<Tools>
2044
3040
  ) {
2045
3041
  const registry = yield* McpServer
@@ -2058,19 +3054,14 @@ export const registerToolkit: <Tools extends Record<string, Tool.Any>>(
2058
3054
  }
2059
3055
  return Context.makeUnsafe(services)
2060
3056
  }))
2061
- const services = omitRequestServices(
2062
- yield* Effect.context<
2063
- Exclude<Tool.HandlerServices<Tools[keyof Tools]>, McpRequestContext>
2064
- >()
2065
- )
2066
- const reportCause = (cause: Cause.Cause<unknown>) => Effect.provideContext(ErrorReporter.report(cause), services)
3057
+ const services = yield* Effect.context<never>()
2067
3058
  // Interruption propagates; anything else is logged, reported and scrubbed.
2068
3059
  const internalToolError = (cause: Cause.Cause<unknown>) => {
2069
3060
  const failure = Cause.findFail(cause)
2070
3061
  return Result.isFailure(failure) && !Cause.hasDies(cause)
2071
3062
  ? Effect.failCause(failure.failure)
2072
3063
  : Effect.logError(cause).pipe(
2073
- Effect.andThen(reportCause(cause)),
3064
+ Effect.andThen(ErrorReporter.report(cause)),
2074
3065
  Effect.as(toolErrorResult(INTERNAL_TOOL_ERROR_MESSAGE))
2075
3066
  )
2076
3067
  }
@@ -2098,6 +3089,32 @@ export const registerToolkit: <Tools extends Record<string, Tool.Any>>(
2098
3089
  ? Effect.succeed(toolErrorResult(error.message))
2099
3090
  : Effect.map(encodeFailure(error), (encoded) =>
2100
3091
  new CallToolResult({ isError: true, content: toolResultContent(encoded) }))
3092
+ // `structuredContent` must be JSON and match the advertised `outputSchema`, which is derived from the JSON codec.
3093
+ // The Toolkit has already encoded the result, so only the JSON conversion of its encoded form runs here.
3094
+ const encodeStructured = Schema.encodeUnknownEffect(Schema.toCodecJson(Schema.toEncoded(tool.successSchema))) as (
3095
+ result: unknown
3096
+ ) => Effect.Effect<unknown, Schema.SchemaError, Tool.HandlerServices<Tools[keyof Tools]>>
3097
+ const successResult = (result: unknown) =>
3098
+ encodeStructured(result).pipe(
3099
+ Effect.mapError((cause) =>
3100
+ AiError.make({
3101
+ module: "McpServer",
3102
+ method: "registerToolkit",
3103
+ reason: new AiError.ToolResultEncodingError({
3104
+ toolName: tool.name,
3105
+ toolResult: result,
3106
+ description: cause.message
3107
+ })
3108
+ })
3109
+ ),
3110
+ Effect.map((structuredContent) =>
3111
+ new CallToolResult({
3112
+ isError: false,
3113
+ structuredContent,
3114
+ content: toolResultContent(structuredContent)
3115
+ })
3116
+ )
3117
+ )
2101
3118
  const handleCause = (cause: Cause.Cause<unknown>) => {
2102
3119
  const failure = Cause.findFail(cause)
2103
3120
  if (Result.isSuccess(failure)) {
@@ -2153,25 +3170,31 @@ export const registerToolkit: <Tools extends Record<string, Tool.Any>>(
2153
3170
  Stream.unwrap,
2154
3171
  Stream.runLast,
2155
3172
  Effect.flatMap(Effect.fromOption),
2156
- Effect.flatMap((result) =>
3173
+ Effect.flatMap((result): Effect.Effect<
3174
+ CallToolResult,
3175
+ unknown,
3176
+ Tool.HandlerServices<Tools[keyof Tools]>
3177
+ > => {
3178
+ if (!result.isFailure) {
3179
+ // An absent result, such as `Schema.Void`, has no structured form.
3180
+ return result.encodedResult === undefined
3181
+ ? Effect.succeed(new CallToolResult({ isError: false, content: [] }))
3182
+ : successResult(result.encodedResult)
3183
+ }
2157
3184
  // Declared failures return their encoded payload; anything else is classified by origin.
2158
- result.isFailure && result.failureOrigin !== "handler"
2159
- ? Effect.failCause(Cause.annotate(
3185
+ return result.failureOrigin === "handler"
3186
+ ? Effect.succeed(
3187
+ new CallToolResult({ isError: true, content: toolResultContent(result.encodedResult) })
3188
+ )
3189
+ : Effect.failCause(Cause.annotate(
2160
3190
  Cause.fail(result.result),
2161
3191
  Context.make(Toolkit.FailureOrigin, result.failureOrigin ?? "result")
2162
3192
  ))
2163
- : Effect.succeed(
2164
- new CallToolResult({
2165
- isError: result.isFailure,
2166
- structuredContent: result.isFailure ? undefined : result.encodedResult,
2167
- content: toolResultContent(result.encodedResult)
2168
- })
2169
- )
2170
- ),
2171
- Effect.catchCause(handleCause),
2172
- Effect.provideContext(services as Context.Context<Tool.HandlerServices<Tools[keyof Tools]>>)
2173
- )
2174
- }
3193
+ }),
3194
+ Effect.catchCause(handleCause)
3195
+ ) as Effect.Effect<CallToolResult, InvalidParams, never>
3196
+ },
3197
+ services
2175
3198
  })
2176
3199
  }
2177
3200
  for (const registration of registrations) {
@@ -2201,7 +3224,14 @@ const toolJsonSchema = (schema: Schema.Constraint, strict: boolean): JsonSchema.
2201
3224
  }
2202
3225
 
2203
3226
  /**
2204
- * Registers an `AiToolkit` with the `McpServer`.
3227
+ * Creates a layer that registers a `Toolkit` with the `McpServer`.
3228
+ *
3229
+ * **Details**
3230
+ *
3231
+ * The layer requires `McpServer`. Pass it to a transport through the
3232
+ * `registrations` option, or provide the transport layer to it.
3233
+ *
3234
+ * @see {@link ToolkitRequirements} for which services are request-level
2205
3235
  *
2206
3236
  * @stability unstable
2207
3237
  * @category layers
@@ -2209,14 +3239,7 @@ const toolJsonSchema = (schema: Schema.Constraint, strict: boolean): JsonSchema.
2209
3239
  */
2210
3240
  export const toolkit = <Tools extends Record<string, Tool.Any>>(
2211
3241
  toolkit: Toolkit.Toolkit<Tools>
2212
- ): Layer.Layer<
2213
- never,
2214
- never,
2215
- Tool.HandlersFor<Tools> | Exclude<Tool.HandlerServices<Tools[keyof Tools]>, McpRequestContext>
2216
- > =>
2217
- Layer.effectDiscard(registerToolkit(toolkit)).pipe(
2218
- Layer.provide(McpServer.layer)
2219
- )
3242
+ ): Layer.Layer<never, never, ToolkitRequirements<Tools>> => Layer.effectDiscard(registerToolkit(toolkit))
2220
3243
 
2221
3244
  /**
2222
3245
  * Utility type that validates a completion-handler record against the allowed
@@ -2272,6 +3295,90 @@ export type ResourceCompletions<Schemas extends ReadonlyArray<Schema.Constraint>
2272
3295
  ) => Effect.Effect<Array<Schemas[K]["Type"]>, any, any>
2273
3296
  }
2274
3297
 
3298
+ // Leave defects and interruption to makeInvoke; convert only expected failures.
3299
+ const handlerFailureToInternalError = (cause: Cause.Cause<unknown>): Effect.Effect<never, InternalError> =>
3300
+ Cause.hasDies(cause) || Cause.hasInterrupts(cause)
3301
+ ? Effect.failCause(cause as Cause.Cause<never>)
3302
+ : Effect.fail(new InternalError({ message: Cause.prettyErrors(cause)[0].message }))
3303
+
3304
+ const completionHandler = (
3305
+ handle: (input: string, context: CompletionContext) => Effect.Effect<any, any, any>,
3306
+ encodeValues: (values: unknown) => Effect.Effect<ReadonlyArray<unknown>, any, any>
3307
+ ) =>
3308
+ (input: string, context: CompletionContext): Effect.Effect<CompleteResult, InternalError> =>
3309
+ handle(input, context).pipe(
3310
+ Effect.flatMap(encodeValues),
3311
+ Effect.map((values) => ({
3312
+ completion: {
3313
+ values: values as Array<string>,
3314
+ total: values.length,
3315
+ hasMore: false
3316
+ }
3317
+ })),
3318
+ Effect.catchCause(handlerFailureToInternalError)
3319
+ ) as any
3320
+
3321
+ type TemplateParamKey<Schemas extends ReadonlyArray<Schema.Constraint>, K extends keyof Schemas> = Schemas[K] extends
3322
+ Param<infer Id, infer _S> ? Id : `param${K & string}`
3323
+
3324
+ type TemplateSchemaServices<Schemas extends ReadonlyArray<Schema.Constraint>, Completions> =
3325
+ | Schemas[number]["DecodingServices"]
3326
+ | {
3327
+ [K in Extract<keyof Schemas, `${number}`>]: TemplateParamKey<Schemas, K> extends keyof Completions
3328
+ ? Schemas[K]["EncodingServices"]
3329
+ : never
3330
+ }[Extract<keyof Schemas, `${number}`>]
3331
+
3332
+ type PromptSchemaServices<Params extends Schema.Struct.Fields, Completions> =
3333
+ | Schema.Struct.DecodingServices<Params>
3334
+ | Params[Extract<keyof Completions, keyof Params>]["EncodingServices"]
3335
+
3336
+ /**
3337
+ * The requirements of a resource registration: the content handler's services
3338
+ * are request-level.
3339
+ *
3340
+ * @stability unstable
3341
+ * @category utility types
3342
+ * @since 4.0.0
3343
+ */
3344
+ export type ResourceRequirements<R> = RegistrationRequirements<never, R>
3345
+
3346
+ /**
3347
+ * The requirements of a resource template registration.
3348
+ *
3349
+ * **Details**
3350
+ *
3351
+ * Services read by the content and completion handlers are request-level.
3352
+ * Parameter decoding services, and the encoding services of parameters with a
3353
+ * completion handler, are required when the template is registered, unless a
3354
+ * handler also reads them.
3355
+ *
3356
+ * @stability unstable
3357
+ * @category utility types
3358
+ * @since 4.0.0
3359
+ */
3360
+ export type ResourceTemplateRequirements<Schemas extends ReadonlyArray<Schema.Constraint>, R, Completions> =
3361
+ RegistrationRequirements<TemplateSchemaServices<Schemas, Completions>, R | CompletionServices<Completions>>
3362
+
3363
+ /**
3364
+ * The requirements of a prompt registration.
3365
+ *
3366
+ * **Details**
3367
+ *
3368
+ * Services read by the content and completion handlers are request-level.
3369
+ * Parameter decoding services, and the encoding services of parameters with a
3370
+ * completion handler, are required when the prompt is registered, unless a
3371
+ * handler also reads them.
3372
+ *
3373
+ * @stability unstable
3374
+ * @category utility types
3375
+ * @since 4.0.0
3376
+ */
3377
+ export type PromptRequirements<Params extends Schema.Struct.Fields, R, Completions> = RegistrationRequirements<
3378
+ PromptSchemaServices<Params, Completions>,
3379
+ R | CompletionServices<Completions>
3380
+ >
3381
+
2275
3382
  /**
2276
3383
  * Registers an MCP resource or resource template from an Effect program.
2277
3384
  *
@@ -2306,7 +3413,7 @@ export const registerResource: {
2306
3413
  >
2307
3414
  readonly annotations?: Context.Context<never> | undefined
2308
3415
  }
2309
- ): Effect.Effect<void, never, Exclude<R, McpRequestContext> | McpServer>
3416
+ ): Effect.Effect<void, never, ResourceRequirements<R>>
2310
3417
  /**
2311
3418
  * Registers an MCP resource or resource template from an Effect program.
2312
3419
  *
@@ -2333,18 +3440,7 @@ export const registerResource: {
2333
3440
  R
2334
3441
  >
2335
3442
  readonly annotations?: Context.Context<never> | undefined
2336
- }) => Effect.Effect<
2337
- void,
2338
- never,
2339
- | Exclude<
2340
- | Schemas[number]["DecodingServices"]
2341
- | Schemas[number]["EncodingServices"]
2342
- | R
2343
- | CompletionServices<Completions>,
2344
- McpRequestContext
2345
- >
2346
- | McpServer
2347
- >
3443
+ }) => Effect.Effect<void, never, ResourceTemplateRequirements<Schemas, R, Completions>>
2348
3444
  } = function() {
2349
3445
  if (arguments.length === 1) {
2350
3446
  const options = arguments[0] as {
@@ -2358,20 +3454,17 @@ export const registerResource: {
2358
3454
  readonly annotations?: Context.Context<never> | undefined
2359
3455
  }
2360
3456
  return Effect.gen(function*() {
2361
- const services = omitRequestServices(yield* Effect.context<any>())
3457
+ const services = yield* Effect.context<never>()
2362
3458
  const registry = yield* McpServer
2363
3459
  yield* registry.addResource({
2364
3460
  resource: new Resource({
2365
3461
  ...options,
2366
3462
  annotations: options
2367
3463
  }),
3464
+ services,
2368
3465
  handle: options.content.pipe(
2369
- Effect.provideContext(services),
2370
3466
  Effect.map((content) => resolveResourceContent(options.uri, content)),
2371
- Effect.catchCause((cause) => {
2372
- const prettyError = Cause.prettyErrors(cause)[0]
2373
- return Effect.fail(new InternalError({ message: prettyError.message }))
2374
- })
3467
+ Effect.catchCause(handlerFailureToInternalError)
2375
3468
  ),
2376
3469
  annotations: options.annotations ?? Context.empty()
2377
3470
  })
@@ -2405,7 +3498,7 @@ export const registerResource: {
2405
3498
  >
2406
3499
  readonly annotations?: Context.Context<never> | undefined
2407
3500
  }) {
2408
- const services = omitRequestServices(yield* Effect.context<any>())
3501
+ const services = yield* Effect.context<never>()
2409
3502
  const registry = yield* McpServer
2410
3503
  const decode = Schema.decodeUnknownEffect(schema)
2411
3504
  const template = new ResourceTemplate({
@@ -2421,32 +3514,13 @@ export const registerResource: {
2421
3514
  ) => Effect.Effect<CompleteResult, InternalError>
2422
3515
  > = Object.create(null)
2423
3516
  for (const [param, handle] of Object.entries(options.completion ?? {})) {
2424
- const encodeArray = Schema.encodeUnknownEffect(Schema.Array(params[param]))
2425
- const handler = (
2426
- input: string,
2427
- context: CompletionContext
2428
- ) =>
2429
- handle(input, context).pipe(
2430
- Effect.flatMap(encodeArray),
2431
- Effect.map((values) => ({
2432
- completion: {
2433
- values: values as Array<string>,
2434
- total: values.length,
2435
- hasMore: false
2436
- }
2437
- })),
2438
- Effect.catchCause((cause) => {
2439
- const prettyError = Cause.prettyErrors(cause)[0]
2440
- return Effect.fail(new InternalError({ message: prettyError.message }))
2441
- }),
2442
- Effect.provideContext(services)
2443
- )
2444
- completions[param] = handler
3517
+ completions[param] = completionHandler(handle, Schema.encodeUnknownEffect(Schema.Array(params[param])))
2445
3518
  }
2446
3519
  yield* registry.addResourceTemplate({
2447
3520
  template,
2448
3521
  routerPath,
2449
3522
  completions,
3523
+ services,
2450
3524
  annotations: options.annotations ?? Context.empty(),
2451
3525
  handle: (uri, params) =>
2452
3526
  decode(params).pipe(
@@ -2454,14 +3528,10 @@ export const registerResource: {
2454
3528
  Effect.flatMap((params: any) =>
2455
3529
  options.content(uri, ...params).pipe(
2456
3530
  Effect.map((content) => resolveResourceContent(uri, content)),
2457
- Effect.catchCause((cause) => {
2458
- const prettyError = Cause.prettyErrors(cause)[0]
2459
- return Effect.fail(new InternalError({ message: prettyError.message }))
2460
- })
3531
+ Effect.catchCause(handlerFailureToInternalError)
2461
3532
  )
2462
- ),
2463
- Effect.provideContext(services)
2464
- )
3533
+ )
3534
+ ) as Effect.Effect<ReadResourceResult, InvalidParams | InternalError>
2465
3535
  })
2466
3536
  })
2467
3537
  } as any
@@ -2469,7 +3539,15 @@ export const registerResource: {
2469
3539
  /**
2470
3540
  * Creates a layer that registers an MCP resource or resource template.
2471
3541
  *
3542
+ * **Details**
3543
+ *
3544
+ * Services read by the content and completion handlers are request-level, so
3545
+ * providing them with `Layer.provide` doesn't satisfy them. Read
3546
+ * construction-time services in an enclosing `Layer.unwrap` and close over
3547
+ * them, and provide per-request services with MCP middleware.
3548
+ *
2472
3549
  * @see {@link registerResource} for the Effect-level resource registration API
3550
+ * @see {@link middleware} for providing request-level dependencies
2473
3551
  *
2474
3552
  * @stability unstable
2475
3553
  * @category layers
@@ -2479,7 +3557,15 @@ export const resource: {
2479
3557
  /**
2480
3558
  * Creates a layer that registers an MCP resource or resource template.
2481
3559
  *
3560
+ * **Details**
3561
+ *
3562
+ * Services read by the content and completion handlers are request-level, so
3563
+ * providing them with `Layer.provide` doesn't satisfy them. Read
3564
+ * construction-time services in an enclosing `Layer.unwrap` and close over
3565
+ * them, and provide per-request services with MCP middleware.
3566
+ *
2482
3567
  * @see {@link registerResource} for the Effect-level resource registration API
3568
+ * @see {@link middleware} for providing request-level dependencies
2483
3569
  *
2484
3570
  * @stability unstable
2485
3571
  * @category layers
@@ -2499,11 +3585,19 @@ export const resource: {
2499
3585
  R
2500
3586
  >
2501
3587
  }
2502
- ): Layer.Layer<never, never, Exclude<R, McpRequestContext>>
3588
+ ): Layer.Layer<never, never, ResourceRequirements<R>>
2503
3589
  /**
2504
3590
  * Creates a layer that registers an MCP resource or resource template.
2505
3591
  *
3592
+ * **Details**
3593
+ *
3594
+ * Services read by the content and completion handlers are request-level, so
3595
+ * providing them with `Layer.provide` doesn't satisfy them. Read
3596
+ * construction-time services in an enclosing `Layer.unwrap` and close over
3597
+ * them, and provide per-request services with MCP middleware.
3598
+ *
2506
3599
  * @see {@link registerResource} for the Effect-level resource registration API
3600
+ * @see {@link middleware} for providing request-level dependencies
2507
3601
  *
2508
3602
  * @stability unstable
2509
3603
  * @category layers
@@ -2525,30 +3619,175 @@ export const resource: {
2525
3619
  E,
2526
3620
  R
2527
3621
  >
2528
- }) => Layer.Layer<
2529
- never,
2530
- never,
2531
- Exclude<
2532
- | Schemas[number]["DecodingServices"]
2533
- | Schemas[number]["EncodingServices"]
2534
- | R
2535
- | CompletionServices<Completions>,
2536
- McpRequestContext
2537
- >
2538
- >
3622
+ }) => Layer.Layer<never, never, ResourceTemplateRequirements<Schemas, R, Completions>>
2539
3623
  } = function() {
2540
3624
  if (arguments.length === 1) {
2541
- return Layer.effectDiscard(registerResource(arguments[0])).pipe(
2542
- Layer.provide(McpServer.layer)
2543
- )
3625
+ return Layer.effectDiscard(registerResource(arguments[0]))
2544
3626
  }
2545
3627
  const register = registerResource(...(arguments as any as [any, any]))
2546
- return (options: any) =>
2547
- Layer.effectDiscard(register(options)).pipe(
2548
- Layer.provide(McpServer.layer)
2549
- )
3628
+ return (options: any) => Layer.effectDiscard(register(options))
2550
3629
  } as any
2551
3630
 
3631
+ /**
3632
+ * A file of a skill: its text, its bytes, or either with an explicit MIME
3633
+ * type. Without one, the MIME type is inferred from the file extension.
3634
+ *
3635
+ * @stability unstable
3636
+ * @category models
3637
+ * @since 4.1.1
3638
+ */
3639
+ export type SkillFile = string | Uint8Array | {
3640
+ readonly content: string | Uint8Array
3641
+ readonly mimeType?: string | undefined
3642
+ }
3643
+
3644
+ /**
3645
+ * Options for {@link registerSkill} and {@link skill}.
3646
+ *
3647
+ * **Details**
3648
+ *
3649
+ * `uri` addresses the skill's `SKILL.md`, as
3650
+ * `skill://<skill-path>/SKILL.md`. Its last path segment is the skill's name,
3651
+ * which must equal the frontmatter's `name`. Other schemes work the same way.
3652
+ *
3653
+ * `files` maps paths relative to the skill root to the skill's files,
3654
+ * `SKILL.md` included. Files are served verbatim, and the skill's listed
3655
+ * frontmatter is parsed from `SKILL.md`. Quote frontmatter strings that a YAML
3656
+ * 1.1 parser reads as another type, such as `yes` or `1.0`.
3657
+ *
3658
+ * @stability unstable
3659
+ * @category models
3660
+ * @since 4.1.1
3661
+ */
3662
+ export interface SkillOptions {
3663
+ readonly uri: string
3664
+ readonly files: { readonly "SKILL.md": SkillFile } & Readonly<Record<string, SkillFile>>
3665
+ readonly annotations?: Context.Context<never> | undefined
3666
+ }
3667
+
3668
+ const skillFileEncoder = new TextEncoder()
3669
+
3670
+ // Bytes are copied so that later changes by the caller cannot alter what is
3671
+ // served under the listed digest. `Buffer#slice` shares memory, so copy with
3672
+ // the `Uint8Array` constructor.
3673
+ const toSkillSourceFile = (path: string, file: SkillFile): McpSkills.SourceFile => {
3674
+ const { content, mimeType } = typeof file === "string" || file instanceof Uint8Array ? { content: file } : file
3675
+ return {
3676
+ path,
3677
+ content: typeof content === "string" ? skillFileEncoder.encode(content) : new Uint8Array(content),
3678
+ mimeType
3679
+ }
3680
+ }
3681
+
3682
+ /**
3683
+ * Registers an Agent Skill under the MCP Skills extension (SEP-2640).
3684
+ *
3685
+ * **Details**
3686
+ *
3687
+ * Each file is registered as a resource, and the skill is listed by
3688
+ * `skills/list` and `skills/get` with a manifest of every file's SHA-256
3689
+ * digest and size, computed from the bytes served. Every directory of the
3690
+ * skill namespace is readable with `resources/directory/read`. The server
3691
+ * declares the extension once any skill is registered.
3692
+ *
3693
+ * Fails when the skill breaks the extension's rules: a name that does not
3694
+ * match the URI, a `SKILL.md` without YAML frontmatter, frontmatter that is
3695
+ * not valid {@link McpSchema.SkillFrontmatter}, a file path that leaves the
3696
+ * skill, or more than 512 files or 16 MiB in all. It also fails when the
3697
+ * skill's directory contains or lies inside another skill's, or one of its
3698
+ * files is already registered as a resource. Registering a resource at the
3699
+ * URI of a skill's file afterwards is a defect.
3700
+ *
3701
+ * SHA-256 runs on `crypto.subtle`.
3702
+ *
3703
+ * @see {@link skill} for the layer-based skill registration wrapper
3704
+ *
3705
+ * @stability unstable
3706
+ * @category handlers
3707
+ * @since 4.1.1
3708
+ */
3709
+ export const registerSkill: (options: SkillOptions) => Effect.Effect<void, Cause.IllegalArgumentError, McpServer> =
3710
+ Effect.fnUntraced(function*(options: SkillOptions) {
3711
+ const files = Object.entries(options.files).map(([path, file]) => toSkillSourceFile(path, file))
3712
+ const skill = yield* McpSkills.makeStaticSkill({ uri: options.uri, files }).pipe(
3713
+ Effect.provide(Digest.layerWebCrypto)
3714
+ )
3715
+
3716
+ const registry = yield* McpServer
3717
+ const { addSkillFile, core, globalMiddleware } = internalState.get(registry)!
3718
+ const services = yield* Effect.context<never>()
3719
+ const annotations = options.annotations ?? Context.empty()
3720
+ const { invoke, visible } = makeInvoke(services, globalMiddleware)
3721
+ // Claims the skill's file URIs before they are registered as resources.
3722
+ yield* core.skills.register({
3723
+ entry: skill.entry,
3724
+ isVisible: isEnabled(annotations),
3725
+ visible: visible("skills/list", options.uri),
3726
+ visibleInDirectories: visible("resources/directory/read", options.uri),
3727
+ get: (invocation) =>
3728
+ invoke(Effect.succeed(skill.entry), invocation, {
3729
+ method: "skills/get",
3730
+ target: options.uri,
3731
+ payload: { uri: options.uri }
3732
+ }),
3733
+ directory: (uri) => skill.directories.get(uri)
3734
+ })
3735
+ for (const { content, resource, text } of skill.files) {
3736
+ const { uri, mimeType } = resource
3737
+ yield* addSkillFile({
3738
+ resource: new Resource(resource),
3739
+ annotations,
3740
+ services,
3741
+ handle: Effect.succeed({
3742
+ contents: [text === undefined ? { uri, mimeType, blob: content } : { uri, mimeType, text }]
3743
+ })
3744
+ })
3745
+ }
3746
+ })
3747
+
3748
+ /**
3749
+ * Creates a layer that registers an Agent Skill under the MCP Skills extension
3750
+ * (SEP-2640).
3751
+ *
3752
+ * **Example** (Publishing a skill with a supporting file)
3753
+ *
3754
+ * ```ts
3755
+ * import { Layer } from "effect"
3756
+ * import { McpProtocol, McpServer } from "effect/ai"
3757
+ *
3758
+ * const RefundsSkill = McpServer.skill({
3759
+ * uri: "skill://billing/refunds/SKILL.md",
3760
+ * files: {
3761
+ * "SKILL.md": `---
3762
+ * name: refunds
3763
+ * description: Process refunds using the billing tools
3764
+ * ---
3765
+ *
3766
+ * Read references/policy.md before issuing a refund.
3767
+ * `,
3768
+ * "references/policy.md": "Refunds above CHF 500 require manager approval.\n"
3769
+ * }
3770
+ * })
3771
+ *
3772
+ * const ServerLayer = RefundsSkill.pipe(
3773
+ * Layer.provide(McpServer.layerHttp({
3774
+ * name: "billing",
3775
+ * version: "1.0.0",
3776
+ * path: "/mcp",
3777
+ * protocols: [McpProtocol.v2026_07_28, McpProtocol.v2025_11_25]
3778
+ * }))
3779
+ * )
3780
+ * ```
3781
+ *
3782
+ * @see {@link registerSkill} for the Effect-level skill registration API
3783
+ *
3784
+ * @stability unstable
3785
+ * @category layers
3786
+ * @since 4.1.1
3787
+ */
3788
+ export const skill = (options: SkillOptions): Layer.Layer<never, Cause.IllegalArgumentError, McpServer> =>
3789
+ Layer.effectDiscard(registerSkill(options))
3790
+
2552
3791
  /**
2553
3792
  * Registers an MCP prompt from an Effect program.
2554
3793
  *
@@ -2585,18 +3824,7 @@ export const registerPrompt = <
2585
3824
  ) => Effect.Effect<Array<PromptMessage> | string, E, R>
2586
3825
  readonly annotations?: Context.Context<never> | undefined
2587
3826
  }
2588
- ): Effect.Effect<
2589
- void,
2590
- never,
2591
- | Exclude<
2592
- | Schema.Struct.DecodingServices<Params>
2593
- | Params[Extract<keyof Completions, keyof Params>]["EncodingServices"]
2594
- | R
2595
- | CompletionServices<Completions>,
2596
- McpRequestContext
2597
- >
2598
- | McpServer
2599
- > => {
3827
+ ): Effect.Effect<void, never, PromptRequirements<Params, R, Completions>> => {
2600
3828
  const args = Arr.empty<PromptArgument>()
2601
3829
  const props: Record<string, Schema.Constraint> = options.parameters ?? {}
2602
3830
  for (const [name, prop] of Object.entries(props)) {
@@ -2624,17 +3852,7 @@ export const registerPrompt = <
2624
3852
  > = options.completion ?? {}
2625
3853
  return Effect.gen(function*() {
2626
3854
  const registry = yield* McpServer
2627
- const services = omitRequestServices(
2628
- yield* Effect.context<
2629
- Exclude<
2630
- | R
2631
- | Schema.Struct.DecodingServices<Params>
2632
- | Params[Extract<keyof Completions, keyof Params>]["EncodingServices"]
2633
- | CompletionServices<Completions>,
2634
- McpRequestContext
2635
- >
2636
- >()
2637
- )
3855
+ const services = yield* Effect.context<never>()
2638
3856
  const completions: Record<
2639
3857
  string,
2640
3858
  (
@@ -2643,41 +3861,19 @@ export const registerPrompt = <
2643
3861
  ) => Effect.Effect<CompleteResult, InternalError, McpRequestContext>
2644
3862
  > = Object.create(null)
2645
3863
  for (const [param, handle] of Object.entries(completion)) {
2646
- const encodeArray = Schema.encodeEffect(Schema.Array(props[param]))
2647
- const handler = (
2648
- input: string,
2649
- context: CompletionContext
2650
- ) =>
2651
- handle(input, context).pipe(
2652
- Effect.flatMap(encodeArray),
2653
- Effect.map((values) => ({
2654
- completion: {
2655
- values: values as Array<string>,
2656
- total: values.length,
2657
- hasMore: false
2658
- }
2659
- })),
2660
- Effect.catchCause((cause) => {
2661
- const prettyError = Cause.prettyErrors(cause)[0]
2662
- return Effect.fail(new InternalError({ message: prettyError.message }))
2663
- }),
2664
- Effect.provide(services)
2665
- )
2666
- completions[param] = handler as any
3864
+ completions[param] = completionHandler(handle, Schema.encodeUnknownEffect(Schema.Array(props[param])))
2667
3865
  }
2668
3866
  yield* registry.addPrompt({
2669
3867
  prompt,
2670
3868
  completions,
3869
+ services,
2671
3870
  annotations: options.annotations ?? Context.empty(),
2672
3871
  handle: (params) =>
2673
3872
  decode(params).pipe(
2674
3873
  Effect.mapError((error) => new InvalidParams({ message: error.message })),
2675
3874
  Effect.flatMap((params) =>
2676
3875
  options.content(params as any).pipe(
2677
- Effect.catchCause((cause) => {
2678
- const prettyError = Cause.prettyErrors(cause)[0]
2679
- return Effect.fail(new InternalError({ message: prettyError.message }))
2680
- })
3876
+ Effect.catchCause(handlerFailureToInternalError)
2681
3877
  )
2682
3878
  ),
2683
3879
  Effect.map((messages) => {
@@ -2688,9 +3884,8 @@ export const registerPrompt = <
2688
3884
  }] :
2689
3885
  messages
2690
3886
  return new GetPromptResult({ messages, description: prompt.description })
2691
- }),
2692
- Effect.provideContext(services as Context.Context<unknown>)
2693
- )
3887
+ })
3888
+ ) as Effect.Effect<GetPromptResult, InvalidParams | InternalError>
2694
3889
  })
2695
3890
  })
2696
3891
  }
@@ -2698,7 +3893,15 @@ export const registerPrompt = <
2698
3893
  /**
2699
3894
  * Creates a layer that registers an MCP prompt.
2700
3895
  *
3896
+ * **Details**
3897
+ *
3898
+ * Services read by the content and completion handlers are request-level, so
3899
+ * providing them with `Layer.provide` doesn't satisfy them. Read
3900
+ * construction-time services in an enclosing `Layer.unwrap` and close over
3901
+ * them, and provide per-request services with MCP middleware.
3902
+ *
2701
3903
  * @see {@link registerPrompt} for the Effect-level prompt registration API
3904
+ * @see {@link middleware} for providing request-level dependencies
2702
3905
  *
2703
3906
  * @stability unstable
2704
3907
  * @category layers
@@ -2726,20 +3929,7 @@ export const prompt = <
2726
3929
  ) => Effect.Effect<Array<PromptMessage> | string, E, R>
2727
3930
  readonly annotations?: Context.Context<never> | undefined
2728
3931
  }
2729
- ): Layer.Layer<
2730
- never,
2731
- never,
2732
- Exclude<
2733
- | Schema.Struct.DecodingServices<Params>
2734
- | Params[Extract<keyof Completions, keyof Params>]["EncodingServices"]
2735
- | R
2736
- | CompletionServices<Completions>,
2737
- McpRequestContext
2738
- >
2739
- > =>
2740
- Layer.effectDiscard(registerPrompt(options)).pipe(
2741
- Layer.provide(McpServer.layer)
2742
- )
3932
+ ): Layer.Layer<never, never, PromptRequirements<Params, R, Completions>> => Layer.effectDiscard(registerPrompt(options))
2743
3933
 
2744
3934
  /**
2745
3935
  * Collects structured input from the current MCP client and decodes the
@@ -2799,6 +3989,22 @@ export const clientCapabilities: Effect.Effect<
2799
3989
  McpRequestContext
2800
3990
  > = McpRequestContext.useSync((_) => _.clientCapabilities)
2801
3991
 
3992
+ /**
3993
+ * Decodes an `Mcp-Name` header, including base64-wrapped values.
3994
+ * Returns `undefined` for malformed values.
3995
+ *
3996
+ * **Details**
3997
+ *
3998
+ * Use in `HttpRouter.middleware` to identify the tool, prompt or resource
3999
+ * targeted by a `2026-07-28` request. Earlier protocols carry the name only
4000
+ * in the JSON-RPC body.
4001
+ *
4002
+ * @stability unstable
4003
+ * @category decoding
4004
+ * @since 4.0.0
4005
+ */
4006
+ export const decodeNameHeader = (value: string): string | undefined => McpProtocolInternal.decodeRoutingHeader(value)
4007
+
2802
4008
  // -----------------------------------------------------------------------------
2803
4009
  // Internal
2804
4010
  // -----------------------------------------------------------------------------