effect 4.0.0-beta.26 → 4.0.0-beta.28

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 (223) hide show
  1. package/dist/Cause.d.ts +1 -1
  2. package/dist/ConfigProvider.d.ts +1 -1
  3. package/dist/Cron.d.ts +1 -1
  4. package/dist/Data.d.ts +3 -3
  5. package/dist/Data.d.ts.map +1 -1
  6. package/dist/Data.js +2 -2
  7. package/dist/Data.js.map +1 -1
  8. package/dist/Effect.d.ts +331 -206
  9. package/dist/Effect.d.ts.map +1 -1
  10. package/dist/Effect.js +113 -72
  11. package/dist/Effect.js.map +1 -1
  12. package/dist/Encoding.d.ts +1 -1
  13. package/dist/ErrorReporter.d.ts +2 -4
  14. package/dist/ErrorReporter.d.ts.map +1 -1
  15. package/dist/ErrorReporter.js +1 -3
  16. package/dist/ErrorReporter.js.map +1 -1
  17. package/dist/Exit.d.ts +24 -12
  18. package/dist/Exit.d.ts.map +1 -1
  19. package/dist/Exit.js +8 -4
  20. package/dist/Exit.js.map +1 -1
  21. package/dist/Fiber.d.ts +1 -0
  22. package/dist/Fiber.d.ts.map +1 -1
  23. package/dist/Fiber.js.map +1 -1
  24. package/dist/Graph.d.ts +1 -1
  25. package/dist/Layer.d.ts +112 -117
  26. package/dist/Layer.d.ts.map +1 -1
  27. package/dist/Layer.js +43 -44
  28. package/dist/Layer.js.map +1 -1
  29. package/dist/LayerMap.d.ts +4 -4
  30. package/dist/LayerMap.js +3 -3
  31. package/dist/ManagedRuntime.d.ts +1 -1
  32. package/dist/ManagedRuntime.js +1 -1
  33. package/dist/Metric.d.ts +2 -4
  34. package/dist/Metric.d.ts.map +1 -1
  35. package/dist/Metric.js +2 -4
  36. package/dist/Metric.js.map +1 -1
  37. package/dist/PlatformError.d.ts +2 -2
  38. package/dist/References.d.ts +6 -1
  39. package/dist/References.d.ts.map +1 -1
  40. package/dist/References.js +6 -1
  41. package/dist/References.js.map +1 -1
  42. package/dist/RequestResolver.d.ts +19 -19
  43. package/dist/RequestResolver.js +10 -10
  44. package/dist/RequestResolver.js.map +1 -1
  45. package/dist/Schedule.d.ts +144 -82
  46. package/dist/Schedule.d.ts.map +1 -1
  47. package/dist/Schedule.js +58 -32
  48. package/dist/Schedule.js.map +1 -1
  49. package/dist/Scheduler.d.ts +9 -0
  50. package/dist/Scheduler.d.ts.map +1 -1
  51. package/dist/Scheduler.js +11 -0
  52. package/dist/Scheduler.js.map +1 -1
  53. package/dist/Schema.d.ts.map +1 -1
  54. package/dist/Schema.js +3 -1
  55. package/dist/Schema.js.map +1 -1
  56. package/dist/Stdio.d.ts +6 -2
  57. package/dist/Stdio.d.ts.map +1 -1
  58. package/dist/Stdio.js +2 -2
  59. package/dist/Stdio.js.map +1 -1
  60. package/dist/Stream.d.ts +8 -4
  61. package/dist/Stream.d.ts.map +1 -1
  62. package/dist/Stream.js +8 -4
  63. package/dist/Stream.js.map +1 -1
  64. package/dist/Types.d.ts +1 -22
  65. package/dist/Types.d.ts.map +1 -1
  66. package/dist/index.d.ts +5 -3
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +5 -3
  69. package/dist/index.js.map +1 -1
  70. package/dist/internal/effect.js +3 -1
  71. package/dist/internal/effect.js.map +1 -1
  72. package/dist/unstable/ai/LanguageModel.d.ts +12 -28
  73. package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
  74. package/dist/unstable/ai/LanguageModel.js +4 -18
  75. package/dist/unstable/ai/LanguageModel.js.map +1 -1
  76. package/dist/unstable/ai/McpSchema.d.ts +20 -1
  77. package/dist/unstable/ai/McpSchema.d.ts.map +1 -1
  78. package/dist/unstable/ai/McpSchema.js +8 -0
  79. package/dist/unstable/ai/McpSchema.js.map +1 -1
  80. package/dist/unstable/ai/McpServer.d.ts +65 -12
  81. package/dist/unstable/ai/McpServer.d.ts.map +1 -1
  82. package/dist/unstable/ai/McpServer.js +159 -45
  83. package/dist/unstable/ai/McpServer.js.map +1 -1
  84. package/dist/unstable/ai/Toolkit.d.ts +1 -1
  85. package/dist/unstable/ai/Toolkit.d.ts.map +1 -1
  86. package/dist/unstable/ai/Toolkit.js +4 -11
  87. package/dist/unstable/ai/Toolkit.js.map +1 -1
  88. package/dist/unstable/ai/internal/codec-transformer.js +0 -5
  89. package/dist/unstable/ai/internal/codec-transformer.js.map +1 -1
  90. package/dist/unstable/cli/CliError.d.ts +4 -4
  91. package/dist/unstable/cli/CliError.js +4 -4
  92. package/dist/unstable/cli/Primitive.d.ts +1 -1
  93. package/dist/unstable/cli/Primitive.js +1 -1
  94. package/dist/unstable/cli/Prompt.js +31 -0
  95. package/dist/unstable/cli/Prompt.js.map +1 -1
  96. package/dist/unstable/cluster/Message.d.ts +5 -5
  97. package/dist/unstable/cluster/Reply.d.ts +3 -3
  98. package/dist/unstable/encoding/Msgpack.d.ts +1 -1
  99. package/dist/unstable/encoding/Ndjson.d.ts +1 -1
  100. package/dist/unstable/encoding/Sse.d.ts +1 -1
  101. package/dist/unstable/eventlog/EventJournal.d.ts +1 -1
  102. package/dist/unstable/eventlog/EventLogRemote.d.ts +1 -1
  103. package/dist/unstable/http/Cookies.d.ts +45 -1
  104. package/dist/unstable/http/Cookies.d.ts.map +1 -1
  105. package/dist/unstable/http/Cookies.js +22 -0
  106. package/dist/unstable/http/Cookies.js.map +1 -1
  107. package/dist/unstable/http/Headers.d.ts +16 -0
  108. package/dist/unstable/http/Headers.d.ts.map +1 -1
  109. package/dist/unstable/http/Headers.js +11 -0
  110. package/dist/unstable/http/Headers.js.map +1 -1
  111. package/dist/unstable/http/HttpBody.d.ts +1 -1
  112. package/dist/unstable/http/HttpClientError.d.ts +7 -7
  113. package/dist/unstable/http/HttpClientRequest.d.ts +5 -0
  114. package/dist/unstable/http/HttpClientRequest.d.ts.map +1 -1
  115. package/dist/unstable/http/HttpClientRequest.js +21 -17
  116. package/dist/unstable/http/HttpClientRequest.js.map +1 -1
  117. package/dist/unstable/http/HttpEffect.d.ts +7 -0
  118. package/dist/unstable/http/HttpEffect.d.ts.map +1 -1
  119. package/dist/unstable/http/HttpEffect.js +6 -0
  120. package/dist/unstable/http/HttpEffect.js.map +1 -1
  121. package/dist/unstable/http/HttpServerError.d.ts +6 -6
  122. package/dist/unstable/http/HttpServerRequest.d.ts +11 -0
  123. package/dist/unstable/http/HttpServerRequest.d.ts.map +1 -1
  124. package/dist/unstable/http/HttpServerRequest.js +291 -1
  125. package/dist/unstable/http/HttpServerRequest.js.map +1 -1
  126. package/dist/unstable/http/HttpServerResponse.d.ts +47 -1
  127. package/dist/unstable/http/HttpServerResponse.d.ts.map +1 -1
  128. package/dist/unstable/http/HttpServerResponse.js +227 -0
  129. package/dist/unstable/http/HttpServerResponse.js.map +1 -1
  130. package/dist/unstable/http/HttpStaticServer.d.ts +69 -0
  131. package/dist/unstable/http/HttpStaticServer.d.ts.map +1 -0
  132. package/dist/unstable/http/HttpStaticServer.js +353 -0
  133. package/dist/unstable/http/HttpStaticServer.js.map +1 -0
  134. package/dist/unstable/http/Multipart.d.ts +1 -1
  135. package/dist/unstable/http/UrlParams.d.ts +1 -1
  136. package/dist/unstable/http/index.d.ts +4 -0
  137. package/dist/unstable/http/index.d.ts.map +1 -1
  138. package/dist/unstable/http/index.js +4 -0
  139. package/dist/unstable/http/index.js.map +1 -1
  140. package/dist/unstable/httpapi/HttpApiBuilder.js +5 -0
  141. package/dist/unstable/httpapi/HttpApiBuilder.js.map +1 -1
  142. package/dist/unstable/httpapi/HttpApiGroup.d.ts +1 -0
  143. package/dist/unstable/httpapi/HttpApiGroup.d.ts.map +1 -1
  144. package/dist/unstable/httpapi/HttpApiGroup.js.map +1 -1
  145. package/dist/unstable/persistence/KeyValueStore.d.ts +1 -1
  146. package/dist/unstable/reactivity/Atom.d.ts.map +1 -1
  147. package/dist/unstable/reactivity/Atom.js +4 -10
  148. package/dist/unstable/reactivity/Atom.js.map +1 -1
  149. package/dist/unstable/reactivity/AtomHttpApi.d.ts +4 -6
  150. package/dist/unstable/reactivity/AtomHttpApi.d.ts.map +1 -1
  151. package/dist/unstable/reactivity/AtomHttpApi.js +39 -9
  152. package/dist/unstable/reactivity/AtomHttpApi.js.map +1 -1
  153. package/dist/unstable/reactivity/AtomRpc.d.ts +8 -8
  154. package/dist/unstable/reactivity/AtomRpc.d.ts.map +1 -1
  155. package/dist/unstable/reactivity/AtomRpc.js +46 -20
  156. package/dist/unstable/reactivity/AtomRpc.js.map +1 -1
  157. package/dist/unstable/rpc/Rpc.d.ts +1 -1
  158. package/dist/unstable/rpc/Rpc.d.ts.map +1 -1
  159. package/dist/unstable/rpc/Rpc.js.map +1 -1
  160. package/dist/unstable/rpc/RpcMiddleware.d.ts +5 -5
  161. package/dist/unstable/rpc/RpcMiddleware.d.ts.map +1 -1
  162. package/dist/unstable/rpc/RpcMiddleware.js.map +1 -1
  163. package/dist/unstable/rpc/RpcServer.js +2 -2
  164. package/dist/unstable/rpc/RpcServer.js.map +1 -1
  165. package/dist/unstable/rpc/Utils.js +1 -1
  166. package/dist/unstable/rpc/Utils.js.map +1 -1
  167. package/dist/unstable/schema/Model.d.ts +21 -0
  168. package/dist/unstable/schema/Model.d.ts.map +1 -1
  169. package/dist/unstable/schema/Model.js +15 -0
  170. package/dist/unstable/schema/Model.js.map +1 -1
  171. package/dist/unstable/socket/SocketServer.d.ts +3 -3
  172. package/dist/unstable/sql/Migrator.d.ts +1 -1
  173. package/dist/unstable/sql/SqlResolver.js +2 -2
  174. package/dist/unstable/sql/SqlResolver.js.map +1 -1
  175. package/dist/unstable/workflow/Workflow.d.ts +1 -1
  176. package/package.json +1 -1
  177. package/src/Cause.ts +1 -1
  178. package/src/Data.ts +3 -4
  179. package/src/Effect.ts +331 -206
  180. package/src/ErrorReporter.ts +2 -4
  181. package/src/Exit.ts +24 -12
  182. package/src/Fiber.ts +1 -0
  183. package/src/Layer.ts +112 -117
  184. package/src/LayerMap.ts +4 -4
  185. package/src/ManagedRuntime.ts +1 -1
  186. package/src/Metric.ts +2 -4
  187. package/src/References.ts +6 -1
  188. package/src/RequestResolver.ts +20 -20
  189. package/src/Schedule.ts +144 -82
  190. package/src/Scheduler.ts +12 -0
  191. package/src/Schema.ts +3 -1
  192. package/src/Stdio.ts +8 -4
  193. package/src/Stream.ts +8 -4
  194. package/src/Types.ts +1 -23
  195. package/src/index.ts +5 -3
  196. package/src/internal/effect.ts +3 -0
  197. package/src/unstable/ai/LanguageModel.ts +16 -37
  198. package/src/unstable/ai/McpSchema.ts +14 -0
  199. package/src/unstable/ai/McpServer.ts +224 -53
  200. package/src/unstable/ai/Toolkit.ts +5 -14
  201. package/src/unstable/ai/internal/codec-transformer.ts +0 -7
  202. package/src/unstable/cli/CliError.ts +4 -4
  203. package/src/unstable/cli/Primitive.ts +1 -1
  204. package/src/unstable/cli/Prompt.ts +27 -0
  205. package/src/unstable/http/Cookies.ts +84 -0
  206. package/src/unstable/http/Headers.ts +34 -0
  207. package/src/unstable/http/HttpClientRequest.ts +21 -17
  208. package/src/unstable/http/HttpEffect.ts +8 -0
  209. package/src/unstable/http/HttpServerRequest.ts +388 -1
  210. package/src/unstable/http/HttpServerResponse.ts +328 -1
  211. package/src/unstable/http/HttpStaticServer.ts +456 -0
  212. package/src/unstable/http/index.ts +5 -0
  213. package/src/unstable/httpapi/HttpApiBuilder.ts +3 -0
  214. package/src/unstable/httpapi/HttpApiGroup.ts +1 -0
  215. package/src/unstable/reactivity/Atom.ts +20 -26
  216. package/src/unstable/reactivity/AtomHttpApi.ts +45 -11
  217. package/src/unstable/reactivity/AtomRpc.ts +48 -17
  218. package/src/unstable/rpc/Rpc.ts +1 -3
  219. package/src/unstable/rpc/RpcMiddleware.ts +12 -6
  220. package/src/unstable/rpc/RpcServer.ts +2 -2
  221. package/src/unstable/rpc/Utils.ts +1 -1
  222. package/src/unstable/schema/Model.ts +31 -0
  223. package/src/unstable/sql/SqlResolver.ts +2 -2
@@ -5,6 +5,7 @@ import * as Arr from "../../Array.ts"
5
5
  import * as Cause from "../../Cause.ts"
6
6
  import * as Effect from "../../Effect.ts"
7
7
  import * as Exit from "../../Exit.ts"
8
+ import * as Fiber from "../../Fiber.ts"
8
9
  import * as Layer from "../../Layer.ts"
9
10
  import * as Option from "../../Option.ts"
10
11
  import * as Queue from "../../Queue.ts"
@@ -19,7 +20,10 @@ import * as Stream from "../../Stream.ts"
19
20
  import type * as Types from "../../Types.ts"
20
21
  import * as FindMyWay from "../http/FindMyWay.ts"
21
22
  import * as Headers from "../http/Headers.ts"
22
- import type * as HttpRouter from "../http/HttpRouter.ts"
23
+ import { appendPreResponseHandlerUnsafe } from "../http/HttpEffect.ts"
24
+ import * as HttpRouter from "../http/HttpRouter.ts"
25
+ import * as HttpServerRequest from "../http/HttpServerRequest.ts"
26
+ import * as HttpServerResponse from "../http/HttpServerResponse.ts"
23
27
  import type * as Rpc from "../rpc/Rpc.ts"
24
28
  import * as RpcClient from "../rpc/RpcClient.ts"
25
29
  import type * as RpcGroup from "../rpc/RpcGroup.ts"
@@ -33,6 +37,7 @@ import {
33
37
  CompleteResult,
34
38
  Elicit,
35
39
  ElicitationDeclined,
40
+ EnabledWhen,
36
41
  GetPromptResult,
37
42
  InternalError,
38
43
  InvalidParams,
@@ -52,10 +57,11 @@ import {
52
57
  Tool as McpTool
53
58
  } from "./McpSchema.ts"
54
59
  import type {
55
- Annotations,
56
60
  CallTool,
61
+ ClientCapabilities,
57
62
  Complete,
58
63
  GetPrompt,
64
+ Initialize,
59
65
  Param,
60
66
  PromptArgument,
61
67
  PromptMessage,
@@ -74,25 +80,37 @@ export class McpServer extends ServiceMap.Service<McpServer, {
74
80
  readonly notificationsQueue: Queue.Dequeue<RpcMessage.Request<any>>
75
81
  readonly initializedClients: Set<number>
76
82
 
77
- readonly tools: ReadonlyArray<McpTool>
83
+ readonly tools: ReadonlyArray<{
84
+ readonly tool: McpTool
85
+ readonly annotations: ServiceMap.ServiceMap<never>
86
+ }>
78
87
  readonly addTool: (options: {
79
88
  readonly tool: McpTool
89
+ readonly annotations: ServiceMap.ServiceMap<never>
80
90
  readonly handle: (payload: any) => Effect.Effect<CallToolResult, never, McpServerClient>
81
91
  }) => Effect.Effect<void>
82
92
  readonly callTool: (
83
93
  requests: typeof CallTool.payloadSchema.Type
84
94
  ) => Effect.Effect<CallToolResult, InternalError | InvalidParams, McpServerClient>
85
95
 
86
- readonly resources: ReadonlyArray<Resource>
87
- readonly addResource: (
88
- resource: Resource,
89
- handle: Effect.Effect<typeof ReadResourceResult.Type, InternalError, McpServerClient>
90
- ) => Effect.Effect<void>
96
+ readonly resources: ReadonlyArray<{
97
+ readonly resource: Resource
98
+ readonly annotations: ServiceMap.ServiceMap<never>
99
+ }>
100
+ readonly addResource: (options: {
101
+ readonly resource: Resource
102
+ readonly annotations: ServiceMap.ServiceMap<never>
103
+ readonly handle: Effect.Effect<typeof ReadResourceResult.Type, InternalError, McpServerClient>
104
+ }) => Effect.Effect<void>
91
105
 
92
- readonly resourceTemplates: ReadonlyArray<ResourceTemplate>
106
+ readonly resourceTemplates: ReadonlyArray<{
107
+ readonly template: ResourceTemplate
108
+ readonly annotations: ServiceMap.ServiceMap<never>
109
+ }>
93
110
  readonly addResourceTemplate: (
94
111
  options: {
95
112
  readonly template: ResourceTemplate
113
+ readonly annotations: ServiceMap.ServiceMap<never>
96
114
  readonly routerPath: string
97
115
  readonly completions: Record<string, (input: string) => Effect.Effect<CompleteResult, InternalError>>
98
116
  readonly handle: (
@@ -106,9 +124,13 @@ export class McpServer extends ServiceMap.Service<McpServer, {
106
124
  uri: string
107
125
  ) => Effect.Effect<typeof ReadResourceResult.Type, InvalidParams | InternalError, McpServerClient>
108
126
 
109
- readonly prompts: ReadonlyArray<Prompt>
127
+ readonly prompts: ReadonlyArray<{
128
+ readonly prompt: Prompt
129
+ readonly annotations: ServiceMap.ServiceMap<never>
130
+ }>
110
131
  readonly addPrompt: (options: {
111
132
  readonly prompt: Prompt
133
+ readonly annotations: ServiceMap.ServiceMap<never>
112
134
  readonly completions: Record<
113
135
  string,
114
136
  (input: string) => Effect.Effect<CompleteResult, InternalError, McpServerClient>
@@ -141,11 +163,23 @@ export class McpServer extends ServiceMap.Service<McpServer, {
141
163
  readonly effect: Effect.Effect<typeof ReadResourceResult.Type, InternalError, McpServerClient>
142
164
  }
143
165
  >()
144
- const tools = Arr.empty<McpTool>()
166
+ const tools = Arr.empty<{
167
+ readonly tool: McpTool
168
+ readonly annotations: ServiceMap.ServiceMap<never>
169
+ }>()
145
170
  const toolMap = new Map<string, (payload: any) => Effect.Effect<CallToolResult, InternalError, McpServerClient>>()
146
- const resources: Array<Resource> = []
147
- const resourceTemplates: Array<ResourceTemplate> = []
148
- const prompts: Array<Prompt> = []
171
+ const resources: Array<{
172
+ readonly resource: Resource
173
+ readonly annotations: ServiceMap.ServiceMap<never>
174
+ }> = []
175
+ const resourceTemplates: Array<{
176
+ readonly template: ResourceTemplate
177
+ readonly annotations: ServiceMap.ServiceMap<never>
178
+ }> = []
179
+ const prompts: Array<{
180
+ readonly prompt: Prompt
181
+ readonly annotations: ServiceMap.ServiceMap<never>
182
+ }> = []
149
183
  const promptMap = new Map<
150
184
  string,
151
185
  (params: Record<string, string>) => Effect.Effect<GetPromptResult, InternalError | InvalidParams, McpServerClient>
@@ -189,13 +223,13 @@ export class McpServer extends ServiceMap.Service<McpServer, {
189
223
  return McpServer.of({
190
224
  notifications: notifications.client,
191
225
  notificationsQueue,
192
- initializedClients: new Set<number>(),
226
+ initializedClients: new Set(),
193
227
  get tools() {
194
228
  return tools
195
229
  },
196
230
  addTool: (options) =>
197
231
  Effect.suspend(() => {
198
- tools.push(options.tool)
232
+ tools.push(options)
199
233
  toolMap.set(options.tool.name, options.handle)
200
234
  return notifications.client["notifications/tools/list_changed"]({})
201
235
  }),
@@ -213,15 +247,15 @@ export class McpServer extends ServiceMap.Service<McpServer, {
213
247
  get resourceTemplates() {
214
248
  return resourceTemplates
215
249
  },
216
- addResource: (resource, effect) =>
250
+ addResource: (options) =>
217
251
  Effect.suspend(() => {
218
- resources.push(resource)
219
- matcher.add(resource.uri, { _tag: "Resource", effect })
252
+ resources.push(options)
253
+ matcher.add(options.resource.uri, { _tag: "Resource", effect: options.handle })
220
254
  return notifications.client["notifications/resources/list_changed"]({})
221
255
  }),
222
- addResourceTemplate: ({ completions, handle, routerPath, template }) =>
256
+ addResourceTemplate: ({ annotations, completions, handle, routerPath, template }) =>
223
257
  Effect.suspend(() => {
224
- resourceTemplates.push(template)
258
+ resourceTemplates.push({ template, annotations })
225
259
  matcher.add(routerPath, { _tag: "ResourceTemplate", handle })
226
260
  for (const [param, handle] of Object.entries(completions)) {
227
261
  completionsMap.set(`ref/resource/${template.uriTemplate}/${param}`, handle)
@@ -247,7 +281,7 @@ export class McpServer extends ServiceMap.Service<McpServer, {
247
281
  },
248
282
  addPrompt: (options) =>
249
283
  Effect.suspend(() => {
250
- prompts.push(options.prompt)
284
+ prompts.push(options)
251
285
  promptMap.set(options.prompt.name, options.handle)
252
286
  for (const [param, handle] of Object.entries(options.completions)) {
253
287
  completionsMap.set(`ref/prompt/${options.prompt.name}/${param}`, handle)
@@ -285,14 +319,18 @@ const SUPPORTED_PROTOCOL_VERSIONS = [
285
319
  "2024-11-05",
286
320
  "2024-10-07"
287
321
  ]
322
+ const mcpSessionIdHeader = "mcp-session-id"
323
+ const mcpProtocolVersionHeader = "mcp-protocol-version"
288
324
 
289
325
  /**
290
326
  * @since 4.0.0
291
327
  * @category constructors
292
328
  */
293
- export const run: (
294
- options: { readonly name: string; readonly version: string }
295
- ) => Effect.Effect<
329
+ export const run: (options: {
330
+ readonly name: string
331
+ readonly version: string
332
+ readonly extensions?: Record<`${string}/${string}`, unknown> | undefined
333
+ }) => Effect.Effect<
296
334
  never,
297
335
  never,
298
336
  McpServer | RpcServer.Protocol
@@ -301,8 +339,10 @@ export const run: (
301
339
  readonly version: string
302
340
  }) {
303
341
  const protocol = yield* RpcServer.Protocol
304
- const handlers = yield* Layer.build(layerHandlers(options))
305
342
  const server = yield* McpServer
343
+ const isHttp = Option.isSome(yield* Effect.serviceOption(HttpRouter.HttpRouter))
344
+ const clientSessions = new Map<string, typeof Initialize.payloadSchema.Type>()
345
+ const handlers = yield* Layer.build(layerHandlers(options, { clientSessions }))
306
346
 
307
347
  const clients = yield* RcMap.make({
308
348
  lookup: Effect.fnUntraced(function*(clientId: number) {
@@ -337,18 +377,24 @@ export const run: (
337
377
  idleTimeToLive: 10000
338
378
  })
339
379
 
340
- const clientMiddleware = McpServerClientMiddleware.of((effect, { clientId }) =>
341
- Effect.provideService(
380
+ const clientMiddleware = McpServerClientMiddleware.of((effect, { clientId, headers, rpc }) => {
381
+ const initializePayload = getInitializedClient(clientSessions, clientId, headers)
382
+ const isInitialize = rpc._tag === "initialize"
383
+ if (!isInitialize && !initializePayload) {
384
+ return Effect.die(new Error(`Mcp-Session-Id does not exist`))
385
+ }
386
+ return Effect.provideService(
342
387
  effect,
343
388
  McpServerClient,
344
389
  McpServerClient.of({
345
390
  clientId,
391
+ initializePayload: initializePayload!,
346
392
  getClient: RcMap.get(clients, clientId).pipe(
347
393
  Effect.map(({ client }) => client)
348
394
  )
349
395
  })
350
396
  )
351
- )
397
+ })
352
398
 
353
399
  const patchedProtocol = RpcServer.Protocol.of({
354
400
  ...protocol,
@@ -359,6 +405,17 @@ export const run: (
359
405
  | RpcMessage.FromClientEncoded
360
406
  switch (request._tag) {
361
407
  case "Request": {
408
+ if (isHttp) {
409
+ const fiber = Fiber.getCurrent()!
410
+ const httpRequest = ServiceMap.getUnsafe(fiber.services, HttpServerRequest.HttpServerRequest)
411
+ const client = getInitializedClient(clientSessions, clientId, httpRequest.headers)
412
+ if (client) {
413
+ appendPreResponseHandlerUnsafe(httpRequest, (_, res) =>
414
+ Effect.succeed(
415
+ HttpServerResponse.setHeader(res, mcpProtocolVersionHeader, client.protocolVersion)
416
+ ))
417
+ }
418
+ }
362
419
  const rpc = ClientNotificationRpcs.requests.get(request.tag)
363
420
  if (rpc) {
364
421
  if (request.tag === "notifications/cancelled") {
@@ -409,7 +466,7 @@ export const run: (
409
466
  payload: encoded
410
467
  } as any
411
468
  const clientIds = yield* patchedProtocol.clientIds
412
- for (const clientId of server.initializedClients) {
469
+ for (const clientId of server.initializedClients.keys()) {
413
470
  if (!clientIds.has(clientId)) {
414
471
  server.initializedClients.delete(clientId)
415
472
  continue
@@ -439,6 +496,7 @@ export const run: (
439
496
  export const layer = (options: {
440
497
  readonly name: string
441
498
  readonly version: string
499
+ readonly extensions?: Record<`${string}/${string}`, unknown> | undefined
442
500
  }): Layer.Layer<McpServer | McpServerClient, never, RpcServer.Protocol> =>
443
501
  Layer.effectDiscard(Effect.forkScoped(run(options))).pipe(
444
502
  Layer.provideMerge(McpServer.layer)
@@ -504,6 +562,7 @@ export const layer = (options: {
504
562
  export const layerStdio = (options: {
505
563
  readonly name: string
506
564
  readonly version: string
565
+ readonly extensions?: Record<`${string}/${string}`, unknown> | undefined
507
566
  }): Layer.Layer<McpServer | McpServerClient, never, Stdio> =>
508
567
  layer(options).pipe(
509
568
  Layer.provide(RpcServer.layerProtocolStdio),
@@ -520,6 +579,7 @@ export const layerHttp = (options: {
520
579
  readonly name: string
521
580
  readonly version: string
522
581
  readonly path: HttpRouter.PathInput
582
+ readonly extensions?: Record<`${string}/${string}`, unknown> | undefined
523
583
  }): Layer.Layer<McpServer | McpServerClient, never, HttpRouter.HttpRouter> =>
524
584
  layer(options).pipe(
525
585
  Layer.provide(RpcServer.layerProtocolHttp(options)),
@@ -549,7 +609,8 @@ export const registerToolkit: <Tools extends Record<string, Tool.Any>>(
549
609
  >)
550
610
  const services = yield* Effect.services<never>()
551
611
  for (const tool of Object.values(built.tools)) {
552
- const toolMeta = ServiceMap.getOrUndefined(tool.annotations, Tool.Meta)
612
+ const annotations = tool.annotations
613
+ const toolMeta = ServiceMap.getOrUndefined(annotations, Tool.Meta)
553
614
  const mcpTool = new McpTool({
554
615
  name: tool.name,
555
616
  description: Tool.getDescription(tool),
@@ -568,6 +629,7 @@ export const registerToolkit: <Tools extends Record<string, Tool.Any>>(
568
629
  })
569
630
  yield* registry.addTool({
570
631
  tool: mcpTool,
632
+ annotations,
571
633
  handle(payload) {
572
634
  return built.handle(tool.name as any, payload).pipe(
573
635
  Stream.unwrap,
@@ -662,6 +724,7 @@ export const registerResource: {
662
724
  E,
663
725
  R
664
726
  >
727
+ readonly annotations?: ServiceMap.ServiceMap<never> | undefined
665
728
  }
666
729
  ): Effect.Effect<void, never, Exclude<R, McpServerClient> | McpServer>
667
730
  /**
@@ -686,6 +749,7 @@ export const registerResource: {
686
749
  E,
687
750
  R
688
751
  >
752
+ readonly annotations?: ServiceMap.ServiceMap<never> | undefined
689
753
  }) => Effect.Effect<
690
754
  void,
691
755
  never,
@@ -702,26 +766,34 @@ export const registerResource: {
702
766
  >
703
767
  } = function() {
704
768
  if (arguments.length === 1) {
705
- const options = arguments[0] as Resource & typeof Annotations.Type & {
706
- readonly content: Effect.Effect<typeof ReadResourceResult.Type | string | Uint8Array>
769
+ const options = arguments[0] as {
770
+ readonly uri: string
771
+ readonly name: string
772
+ readonly description?: string | undefined
773
+ readonly mimeType?: string | undefined
774
+ readonly audience?: ReadonlyArray<"user" | "assistant"> | undefined
775
+ readonly priority?: number | undefined
776
+ readonly content: Effect.Effect<typeof ReadResourceResult.Type | string | Uint8Array, any, any>
777
+ readonly annotations?: ServiceMap.ServiceMap<never> | undefined
707
778
  }
708
779
  return Effect.gen(function*() {
709
780
  const services = yield* Effect.services<any>()
710
781
  const registry = yield* McpServer
711
- yield* registry.addResource(
712
- new Resource({
782
+ yield* registry.addResource({
783
+ resource: new Resource({
713
784
  ...options,
714
785
  annotations: options
715
786
  }),
716
- options.content.pipe(
787
+ handle: options.content.pipe(
717
788
  Effect.provideServices(services),
718
789
  Effect.map((content) => resolveResourceContent(options.uri, content)),
719
790
  Effect.catchCause((cause) => {
720
791
  const prettyError = Cause.prettyErrors(cause)[0]
721
792
  return Effect.fail(new InternalError({ message: prettyError.message }))
722
793
  })
723
- )
724
- )
794
+ ),
795
+ annotations: options.annotations ?? ServiceMap.empty()
796
+ })
725
797
  })
726
798
  }
727
799
  const {
@@ -742,6 +814,7 @@ export const registerResource: {
742
814
  E,
743
815
  R
744
816
  >
817
+ readonly annotations?: ServiceMap.ServiceMap<never> | undefined
745
818
  }) {
746
819
  const services = yield* Effect.services<any>()
747
820
  const registry = yield* McpServer
@@ -776,6 +849,7 @@ export const registerResource: {
776
849
  template,
777
850
  routerPath,
778
851
  completions,
852
+ annotations: options.annotations ?? ServiceMap.empty(),
779
853
  handle: (uri, params) =>
780
854
  decode(params).pipe(
781
855
  Effect.mapError((error) => new InvalidParams({ message: error.message })),
@@ -888,6 +962,7 @@ export const registerPrompt = <
888
962
  readonly parameters?: Params | undefined
889
963
  readonly completion?: ValidateCompletions<Completions, Extract<keyof Params, string>> | undefined
890
964
  readonly content: (params: Params) => Effect.Effect<Array<typeof PromptMessage.Type> | string, E, R>
965
+ readonly annotations?: ServiceMap.ServiceMap<never> | undefined
891
966
  }
892
967
  ): Effect.Effect<void, never, Exclude<Schema.Struct.DecodingServices<Params> | R, McpServerClient> | McpServer> => {
893
968
  const args = Arr.empty<typeof PromptArgument.Type>()
@@ -938,6 +1013,7 @@ export const registerPrompt = <
938
1013
  yield* registry.addPrompt({
939
1014
  prompt,
940
1015
  completions,
1016
+ annotations: options.annotations ?? ServiceMap.empty(),
941
1017
  handle: (params) =>
942
1018
  decode(params).pipe(
943
1019
  Effect.mapError((error) => new InvalidParams({ message: error.message })),
@@ -983,6 +1059,7 @@ export const prompt = <
983
1059
  readonly content: (
984
1060
  params: Schema.Struct.Type<Params>
985
1061
  ) => Effect.Effect<Array<typeof PromptMessage.Type> | string, E, R>
1062
+ readonly annotations?: ServiceMap.ServiceMap<never> | undefined
986
1063
  }
987
1064
  ): Layer.Layer<never, never, Exclude<Schema.Struct.DecodingServices<Params> | R, McpServerClient>> =>
988
1065
  Layer.effectDiscard(registerPrompt(options)).pipe(
@@ -1026,6 +1103,18 @@ export const elicit: <S extends Schema.Encoder<Record<string, unknown>, unknown>
1026
1103
  }
1027
1104
  }, Effect.scoped)
1028
1105
 
1106
+ /**
1107
+ * Access the current client's capabilities.
1108
+ *
1109
+ * @since 4.0.0
1110
+ * @category capabilities
1111
+ */
1112
+ export const clientCapabilities: Effect.Effect<
1113
+ ClientCapabilities,
1114
+ never,
1115
+ McpServerClient
1116
+ > = McpServerClient.useSync((_) => _.initializePayload.capabilities)
1117
+
1029
1118
  // -----------------------------------------------------------------------------
1030
1119
  // Internal
1031
1120
  // -----------------------------------------------------------------------------
@@ -1075,6 +1164,9 @@ const compileUriTemplate = (segments: TemplateStringsArray, ...schemas: Readonly
1075
1164
  const layerHandlers = (serverInfo: {
1076
1165
  readonly name: string
1077
1166
  readonly version: string
1167
+ readonly extensions?: Record<`${string}/${string}`, unknown> | undefined
1168
+ }, options: {
1169
+ readonly clientSessions: Map<string, typeof Initialize.payloadSchema.Type>
1078
1170
  }) =>
1079
1171
  ClientRpcs.toLayer(
1080
1172
  Effect.gen(function*() {
@@ -1085,7 +1177,15 @@ const layerHandlers = (serverInfo: {
1085
1177
  // Requests
1086
1178
  ping: () => Effect.succeed({}),
1087
1179
  initialize(params, { clientId }) {
1088
- const requestedVersion = params.protocolVersion
1180
+ const requestedVersion = SUPPORTED_PROTOCOL_VERSIONS.includes(params.protocolVersion)
1181
+ ? params.protocolVersion
1182
+ : LATEST_PROTOCOL_VERSION
1183
+ if (requestedVersion !== params.protocolVersion) {
1184
+ params = {
1185
+ ...params,
1186
+ protocolVersion: requestedVersion
1187
+ }
1188
+ }
1089
1189
  const capabilities: Types.DeepMutable<typeof ServerCapabilities.Type> = {
1090
1190
  completions: {}
1091
1191
  }
@@ -1101,13 +1201,27 @@ const layerHandlers = (serverInfo: {
1101
1201
  if (server.prompts.length > 0) {
1102
1202
  capabilities.prompts = { listChanged: true }
1103
1203
  }
1104
- server.initializedClients.add(clientId)
1105
- return Effect.succeed({
1106
- capabilities,
1107
- serverInfo,
1108
- protocolVersion: SUPPORTED_PROTOCOL_VERSIONS.includes(requestedVersion)
1109
- ? requestedVersion
1110
- : LATEST_PROTOCOL_VERSION
1204
+ if (serverInfo.extensions) {
1205
+ capabilities.extensions = serverInfo.extensions as any
1206
+ }
1207
+ return Effect.withFiber((fiber) => {
1208
+ const httpRequest = ServiceMap.getOrUndefined(fiber.services, HttpServerRequest.HttpServerRequest)
1209
+ if (httpRequest) {
1210
+ const sessionId = crypto.randomUUID()
1211
+ options.clientSessions.set(sessionId, params)
1212
+ appendPreResponseHandlerUnsafe(httpRequest, (_req, res) =>
1213
+ Effect.succeed(HttpServerResponse.setHeaders(res, {
1214
+ [mcpSessionIdHeader]: sessionId,
1215
+ [mcpProtocolVersionHeader]: requestedVersion
1216
+ })))
1217
+ } else {
1218
+ options.clientSessions.set(String(clientId), params)
1219
+ }
1220
+ return Effect.succeed({
1221
+ capabilities,
1222
+ serverInfo,
1223
+ protocolVersion: requestedVersion
1224
+ })
1111
1225
  })
1112
1226
  },
1113
1227
  "completion/complete": (r) =>
@@ -1141,21 +1255,42 @@ const layerHandlers = (serverInfo: {
1141
1255
  server.getPromptResult(r).pipe(
1142
1256
  Effect.provideService(CurrentLogLevel, currentLogLevel)
1143
1257
  ),
1144
- "prompts/list": () => Effect.sync(() => new ListPromptsResult({ prompts: server.prompts })),
1145
- "resources/list": () => Effect.sync(() => new ListResourcesResult({ resources: server.resources })),
1258
+ "prompts/list": (_, { clientId, headers }) =>
1259
+ Effect.sync(() => {
1260
+ const client = getInitializedClient(options.clientSessions, clientId, headers)
1261
+ return new ListPromptsResult({ prompts: filterByClient(client, server.prompts, "prompt") })
1262
+ }),
1263
+ "resources/list": (_, { clientId, headers }) =>
1264
+ Effect.sync(() => {
1265
+ const client = getInitializedClient(options.clientSessions, clientId, headers)
1266
+ return new ListResourcesResult({ resources: filterByClient(client, server.resources, "resource") })
1267
+ }),
1146
1268
  "resources/read": ({ uri }) =>
1147
1269
  server.findResource(uri).pipe(
1148
1270
  Effect.provideService(CurrentLogLevel, currentLogLevel)
1149
1271
  ),
1150
- "resources/subscribe": () => InternalError.notImplemented.asEffect(),
1151
- "resources/unsubscribe": () => InternalError.notImplemented.asEffect(),
1152
- "resources/templates/list": () =>
1153
- Effect.sync(() => new ListResourceTemplatesResult({ resourceTemplates: server.resourceTemplates })),
1272
+ "resources/subscribe": () =>
1273
+ InternalError.notImplemented.asEffect(),
1274
+ "resources/unsubscribe": () =>
1275
+ InternalError.notImplemented.asEffect(),
1276
+ "resources/templates/list": (_, { clientId, headers }) =>
1277
+ Effect.sync(() => {
1278
+ const client = getInitializedClient(options.clientSessions, clientId, headers)
1279
+ return new ListResourceTemplatesResult({
1280
+ resourceTemplates: filterByClient(client, server.resourceTemplates, "template")
1281
+ })
1282
+ }),
1154
1283
  "tools/call": (r) =>
1155
1284
  server.callTool(r).pipe(
1156
1285
  Effect.provideService(CurrentLogLevel, currentLogLevel)
1157
1286
  ),
1158
- "tools/list": () => Effect.sync(() => new ListToolsResult({ tools: server.tools })),
1287
+ "tools/list": (_, { clientId, headers }) =>
1288
+ Effect.sync(() => {
1289
+ const client = getInitializedClient(options.clientSessions, clientId, headers)
1290
+ return new ListToolsResult({
1291
+ tools: filterByClient(client, server.tools, "tool")
1292
+ })
1293
+ }),
1159
1294
 
1160
1295
  // Notifications
1161
1296
  "notifications/cancelled": (_) => Effect.void,
@@ -1187,3 +1322,39 @@ const resolveResourceContent = (
1187
1322
  }
1188
1323
  return content
1189
1324
  }
1325
+
1326
+ const filterByClient = <
1327
+ A extends {
1328
+ readonly annotations: ServiceMap.ServiceMap<never>
1329
+ },
1330
+ P extends keyof A
1331
+ >(
1332
+ client: typeof Initialize.payloadSchema.Type | undefined,
1333
+ items: ReadonlyArray<A>,
1334
+ prop: P
1335
+ ): Array<A[P]> => {
1336
+ if (!client) {
1337
+ return items.map((item) => item[prop])
1338
+ }
1339
+ const out = Arr.empty<A[P]>()
1340
+ for (let i = 0; i < items.length; i++) {
1341
+ const item = items[i]
1342
+ const enabledWhen = ServiceMap.getOrUndefined(item.annotations, EnabledWhen)
1343
+ if (!enabledWhen || enabledWhen(client)) {
1344
+ out.push(item[prop])
1345
+ }
1346
+ }
1347
+ return out
1348
+ }
1349
+
1350
+ const getInitializedClient = (
1351
+ sessions: Map<string, typeof Initialize.payloadSchema.Type>,
1352
+ clientId: number,
1353
+ headers: Headers.Headers
1354
+ ) => {
1355
+ const sessionId = headers[mcpSessionIdHeader]
1356
+ if (sessionId === undefined) {
1357
+ return sessions.get(String(clientId))
1358
+ }
1359
+ return sessions.get(sessionId)
1360
+ }
@@ -53,9 +53,7 @@ import type * as Scope from "../../Scope.ts"
53
53
  import * as ServiceMap from "../../ServiceMap.ts"
54
54
  import * as Stream from "../../Stream.ts"
55
55
  import * as AiError from "./AiError.ts"
56
- import { CurrentCodecTransformer } from "./internal/codec-transformer.ts"
57
- import type { CodecTransformer } from "./LanguageModel.ts"
58
- import * as Tool from "./Tool.ts"
56
+ import type * as Tool from "./Tool.ts"
59
57
 
60
58
  const TypeId = "~effect/ai/Toolkit" as const
61
59
 
@@ -298,24 +296,18 @@ const Proto = {
298
296
  readonly encodeResult: (u: unknown) => Effect.Effect<unknown, Schema.SchemaError>
299
297
  }>()
300
298
 
301
- const getSchemas = (tool: Tool.Any, transformer: CodecTransformer) => {
299
+ const getSchemas = (tool: Tool.Any) => {
302
300
  let schemas = schemasCache.get(tool)
303
301
  if (Predicate.isUndefined(schemas)) {
304
302
  const handler = services.mapUnsafe.get(tool.id)! as Tool.Handler<any>
305
303
  const resultSchema = tool.failureMode === "return"
306
304
  ? Schema.Union([tool.successSchema, tool.failureSchema, AiError.AiError])
307
305
  : tool.successSchema
308
- // Do not apply the codec transformation to provider defined tools,
309
- // as these are defined internal to the Effect AI SDK and should
310
- // already have valid schemas
311
- const transformedResultSchema = Tool.isProviderDefined(tool)
312
- ? resultSchema
313
- : transformer(resultSchema).codec
314
306
  const decodeParameters = Schema.isSchema(tool.parametersSchema)
315
307
  ? Schema.decodeUnknownEffect(tool.parametersSchema) as any
316
308
  : (u: unknown) => Effect.succeed(u)
317
- const decodeResult = Schema.decodeUnknownEffect(transformedResultSchema) as any
318
- const encodeResult = Schema.encodeUnknownEffect(transformedResultSchema) as any
309
+ const decodeResult = Schema.decodeUnknownEffect(resultSchema) as any
310
+ const encodeResult = Schema.encodeUnknownEffect(resultSchema) as any
319
311
  schemas = {
320
312
  services: handler.services,
321
313
  handler: handler.handler,
@@ -349,8 +341,7 @@ const Proto = {
349
341
  }
350
342
 
351
343
  // Fetch cached schemas / handlers for the tool
352
- const codecTransformer = yield* CurrentCodecTransformer
353
- const schemas = getSchemas(tool, codecTransformer)
344
+ const schemas = getSchemas(tool)
354
345
 
355
346
  // Decode the tool call parameters which will be passed to the handler
356
347
  const decodedParams = yield* schemas.decodeParameters(params).pipe(
@@ -1,5 +1,4 @@
1
1
  import * as Schema from "../../../Schema.ts"
2
- import * as ServiceMap from "../../../ServiceMap.ts"
3
2
  import type { CodecTransformer } from "../LanguageModel.ts"
4
3
 
5
4
  /** @internal */
@@ -11,9 +10,3 @@ export const defaultCodecTransformer: CodecTransformer = (codec) => {
11
10
  }
12
11
  return { codec, jsonSchema }
13
12
  }
14
-
15
- /** @internal */
16
- export const CurrentCodecTransformer = ServiceMap.Reference(
17
- "effect/unstable/ai/CodecTransformer",
18
- { defaultValue: (): CodecTransformer => defaultCodecTransformer }
19
- )
@@ -108,7 +108,7 @@ export type CliError =
108
108
  * // In CLI parsing context
109
109
  * const parseCommand = Effect.gen(function*() {
110
110
  * // If parsing encounters unknown flag
111
- * return yield* Effect.fail(unrecognizedError)
111
+ * return yield* unrecognizedError
112
112
  * })
113
113
  * ```
114
114
  *
@@ -201,7 +201,7 @@ export class DuplicateOption extends Schema.ErrorClass(`${TypeId}/DuplicateOptio
201
201
  * Effect.gen(function*() {
202
202
  * const apiKey = options["api-key"]
203
203
  * if (!apiKey) {
204
- * return yield* Effect.fail(missingOptionError)
204
+ * return yield* missingOptionError
205
205
  * }
206
206
  * return apiKey
207
207
  * })
@@ -246,7 +246,7 @@ export class MissingOption extends Schema.ErrorClass(`${TypeId}/MissingOption`)(
246
246
  * const parseArguments = (args: Array<string>) =>
247
247
  * Effect.gen(function*() {
248
248
  * if (args.length === 0) {
249
- * return yield* Effect.fail(missingArgError)
249
+ * return yield* missingArgError
250
250
  * }
251
251
  * return args[0]
252
252
  * })
@@ -354,7 +354,7 @@ export class InvalidValue extends Schema.ErrorClass(`${TypeId}/InvalidValue`)({
354
354
  * Effect.gen(function*() {
355
355
  * const validCommands = ["deploy", "destroy", "status"]
356
356
  * if (!validCommands.includes(subcommand)) {
357
- * return yield* Effect.fail(unknownSubcommandError)
357
+ * return yield* unknownSubcommandError
358
358
  * }
359
359
  * return subcommand
360
360
  * })
@@ -645,7 +645,7 @@ export const keyValuePair: Primitive<Record<string, string>> = makePrimitive(
645
645
  *
646
646
  * const program = Effect.gen(function*() {
647
647
  * // This will always fail - useful for boolean flags
648
- * const result = yield* Primitive.none.parse("any-value")
648
+ * return yield* Primitive.none.parse("any-value")
649
649
  * })
650
650
  *
651
651
  * // The above effect will fail with "This option does not accept values"