@yolk-sdk/mcp 0.1.0-canary.113 → 0.1.0-canary.114

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.
package/README.md CHANGED
@@ -189,6 +189,15 @@ const step = Effect.gen(function* () {
189
189
  - Legacy-era elicitation (a server-initiated request answered while the call's stream is open) is
190
190
  not supported; resuming against a legacy connection fails with `unsupported_era`.
191
191
 
192
+ ### Files in tool results
193
+
194
+ The client maps embedded resource blobs in tool results to `FilePart`s (named from the URI), so
195
+ `resolveTools({ files })` stores them and the model sees a `fileId` label instead of base64
196
+ ([ADR 0009](https://github.com/magoz/yolk-sdk/blob/main/docs/adr/0009-file-claim-check.md));
197
+ embedded text stays text, and images and audio stay viewable parts. When adapting Yolk tools into
198
+ an MCP server, an inline `FilePart` leaves as an embedded resource blob and a captured one as its
199
+ label.
200
+
192
201
  ## Connect to a local stdio server
193
202
 
194
203
  Node hosts can use the convenience wrappers from `client/node`:
@@ -3,10 +3,10 @@ import { McpClientCapabilityRequiredError, McpError, McpInputRequiredError } fro
3
3
  import { McpElicitationResponses, McpElicitationSupport, McpInputRequired, McpToolCallOutcome } from "./elicitation.mjs";
4
4
  import { McpToolAnnotations, McpToolExposureResolver, mcpToolToToolDef } from "./protocol.mjs";
5
5
  import { Effect } from "effect";
6
- import { Client, ClientOptions } from "@modelcontextprotocol/client";
6
+ import { ToolResult } from "@yolk-sdk/agent/protocol";
7
7
  import { HttpClient } from "effect/http";
8
+ import { Client, ClientOptions } from "@modelcontextprotocol/client";
8
9
  import { ChildProcessSpawner } from "effect/process";
9
- import { ToolResult } from "@yolk-sdk/agent/protocol";
10
10
 
11
11
  //#region src/client/client.d.ts
12
12
  type McpClientOptions = {
@@ -1,12 +1,12 @@
1
1
  import { defaultMcpClientInfo, defaultMcpSecurityPolicy } from "./config.mjs";
2
2
  import { McpClientCapabilityRequiredError, McpError, McpInputRequiredError } from "./errors.mjs";
3
- import { McpPausedTool, McpToolCallComplete, McpToolCallInputRequired, decodeMcpInputRequired, mcpArgumentsDigest, mcpMaxInputRequiredBytes, mcpPausedToolBytes, toMcpInputResponses } from "./elicitation.mjs";
4
3
  import { InitializeClientInfo, InitializeParams, InitializedNotification, JsonRpcRequest, ToolsCallParams, decodeJsonRpcResponseFromJson, decodeToolCallResult, decodeToolsListResult, encodeJsonRpcMessage, jsonRpcErrorToMcpError, legacyMcpProtocolVersion, mcpToolToToolDef, toolCallResultToToolResult } from "./protocol.mjs";
4
+ import { McpPausedTool, McpToolCallComplete, McpToolCallInputRequired, decodeMcpInputRequired, mcpArgumentsDigest, mcpMaxInputRequiredBytes, mcpPausedToolBytes, toMcpInputResponses } from "./elicitation.mjs";
5
5
  import { makeEffectFetch } from "./effect-fetch.mjs";
6
6
  import { Duration, Effect, Option, Stream, Struct } from "effect";
7
7
  import * as Schema from "effect/Schema";
8
- import { CLIENT_CAPABILITIES_META_KEY, Client, MissingRequiredClientCapabilityError, ProtocolError, ProtocolErrorCode, SdkError, SdkErrorCode, StreamableHTTPClientTransport, fromJsonSchema, isInputRequiredResult, isJSONRPCRequest, isJSONRPCResponse, isJSONRPCResultResponse, isSpecType, mergeCapabilities } from "@modelcontextprotocol/client";
9
8
  import { HttpClient } from "effect/http";
9
+ import { CLIENT_CAPABILITIES_META_KEY, Client, MissingRequiredClientCapabilityError, ProtocolError, ProtocolErrorCode, SdkError, SdkErrorCode, StreamableHTTPClientTransport, fromJsonSchema, isInputRequiredResult, isJSONRPCRequest, isJSONRPCResponse, isJSONRPCResultResponse, isSpecType, mergeCapabilities } from "@modelcontextprotocol/client";
10
10
  import { ChildProcess } from "effect/process";
11
11
  //#region src/client/client.ts
12
12
  const defaultRequestTimeoutMs = 3e4;
@@ -1,5 +1,5 @@
1
- import { FetchLike } from "@modelcontextprotocol/client";
2
1
  import { HttpClient } from "effect/http";
2
+ import { FetchLike } from "@modelcontextprotocol/client";
3
3
 
4
4
  //#region src/client/effect-fetch.d.ts
5
5
  declare const makeEffectFetch: (http: HttpClient.HttpClient) => FetchLike;
@@ -1,7 +1,7 @@
1
1
  import { defaultMcpClientInfo, defaultMcpSecurityPolicy } from "./config.mjs";
2
2
  import { McpClientCapabilityRequiredError, McpError, McpErrorCause, McpInputRequiredError, McpInputRequiredErrorReason } from "./errors.mjs";
3
- import { McpElicitationContentValue, McpElicitationProperty, McpElicitationPropertyType, McpElicitationRequestedSchema, McpElicitationResponse, McpElicitationResponses, McpFormElicitation, McpInputRequired, McpPausedTool, McpToolCallComplete, McpToolCallInputRequired, McpToolCallOutcome, canonicalMcpJson, decodeMcpInputRequired, defaultMcpMaxInputRequiredBytes, mcpArgumentsDigest, mcpMaxInputRequests, mcpMaxInputRequiredBytes, toMcpInputResponses } from "./elicitation.mjs";
4
3
  import { GenericContentBlock, InitializeClientInfo, InitializeParams, InitializedNotification, JsonRpcErrorObject, JsonRpcErrorResponse, JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcResponse, JsonRpcSuccessResponse, McpTool, TextContentBlock, ToolCallResult, ToolsCallParams, ToolsListResult, decodeJsonRpcMessageFromJson, decodeJsonRpcResponse, decodeJsonRpcResponseFromJson, decodeToolCallResult, decodeToolsListResult, encodeJsonRpcMessage, jsonRpcErrorToMcpError, latestMcpProtocolVersion, legacyMcpProtocolVersion, makeInitializeParams, makeInitializedNotification, makeJsonRpcRequest, mcpToolToToolDef, sanitizeMcpName, toolCallResultToToolResult } from "./protocol.mjs";
4
+ import { McpElicitationContentValue, McpElicitationProperty, McpElicitationPropertyType, McpElicitationRequestedSchema, McpElicitationResponse, McpElicitationResponses, McpFormElicitation, McpInputRequired, McpPausedTool, McpToolCallComplete, McpToolCallInputRequired, McpToolCallOutcome, canonicalMcpJson, decodeMcpInputRequired, defaultMcpMaxInputRequiredBytes, mcpArgumentsDigest, mcpMaxInputRequests, mcpMaxInputRequiredBytes, toMcpInputResponses } from "./elicitation.mjs";
5
5
  import { callLocalMcpServerTool, callMcpServerTool, callRemoteMcpServerTool, callRemoteMcpServerToolResumable, listLocalMcpServerTools, listMcpServerTools, listMcpTools, listRemoteMcpServerTools, resumeRemoteMcpServerToolCall } from "./client.mjs";
6
6
  export * from "@modelcontextprotocol/client";
7
7
  export { GenericContentBlock, InitializeClientInfo, InitializeParams, InitializedNotification, JsonRpcErrorObject, JsonRpcErrorResponse, JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcResponse, JsonRpcSuccessResponse, McpClientCapabilityRequiredError, McpElicitationContentValue, McpElicitationProperty, McpElicitationPropertyType, McpElicitationRequestedSchema, McpElicitationResponse, McpElicitationResponses, McpError, McpErrorCause, McpFormElicitation, McpInputRequired, McpInputRequiredError, McpInputRequiredErrorReason, McpPausedTool, McpTool, McpToolCallComplete, McpToolCallInputRequired, McpToolCallOutcome, TextContentBlock, ToolCallResult, ToolsCallParams, ToolsListResult, callLocalMcpServerTool, callMcpServerTool, callRemoteMcpServerTool, callRemoteMcpServerToolResumable, canonicalMcpJson, decodeJsonRpcMessageFromJson, decodeJsonRpcResponse, decodeJsonRpcResponseFromJson, decodeMcpInputRequired, decodeToolCallResult, decodeToolsListResult, defaultMcpClientInfo, defaultMcpMaxInputRequiredBytes, defaultMcpSecurityPolicy, encodeJsonRpcMessage, jsonRpcErrorToMcpError, latestMcpProtocolVersion, legacyMcpProtocolVersion, listLocalMcpServerTools, listMcpServerTools, listMcpTools, listRemoteMcpServerTools, makeInitializeParams, makeInitializedNotification, makeJsonRpcRequest, mcpArgumentsDigest, mcpMaxInputRequests, mcpMaxInputRequiredBytes, mcpToolToToolDef, resumeRemoteMcpServerToolCall, sanitizeMcpName, toMcpInputResponses, toolCallResultToToolResult };
@@ -164,8 +164,8 @@ declare const decodeJsonRpcResponse: (input: unknown, options?: import("effect/S
164
164
  readonly jsonrpc: "2.0";
165
165
  readonly id: string | number | null;
166
166
  readonly error: {
167
- readonly message: string;
168
167
  readonly code: number;
168
+ readonly message: string;
169
169
  readonly data?: unknown;
170
170
  };
171
171
  }, Schema.SchemaError, never>;
@@ -173,20 +173,20 @@ declare const decodeToolsListResult: (input: unknown, options?: import("effect/S
173
173
  readonly tools: readonly {
174
174
  readonly name: string;
175
175
  readonly title?: string | undefined;
176
- readonly outputSchema?: unknown;
177
- readonly inputSchema?: Schema.JsonObject | undefined;
178
176
  readonly description?: string | undefined;
177
+ readonly inputSchema?: Schema.JsonObject | undefined;
178
+ readonly outputSchema?: unknown;
179
179
  readonly annotations?: {
180
180
  readonly [x: string]: unknown;
181
181
  } | undefined;
182
182
  }[];
183
183
  }, Schema.SchemaError, never>;
184
184
  declare const decodeToolCallResult: (input: unknown, options?: import("effect/SchemaAST").ParseOptions) => Effect.Effect<{
185
- readonly isError?: boolean | undefined;
186
- readonly structuredContent?: unknown;
187
185
  readonly content?: readonly {
188
186
  readonly [x: string]: unknown;
189
187
  }[] | undefined;
188
+ readonly isError?: boolean | undefined;
189
+ readonly structuredContent?: unknown;
190
190
  }, Schema.SchemaError, never>;
191
191
  declare const encodeJsonRpcMessage: (server: string, message: JsonRpcRequest | JsonRpcNotification) => Effect.Effect<string, McpError, never>;
192
192
  declare const decodeJsonRpcResponseFromJson: (server: string, text: string) => Effect.Effect<{
@@ -197,14 +197,14 @@ declare const decodeJsonRpcResponseFromJson: (server: string, text: string) => E
197
197
  readonly jsonrpc: "2.0";
198
198
  readonly id: string | number | null;
199
199
  readonly error: {
200
- readonly message: string;
201
200
  readonly code: number;
201
+ readonly message: string;
202
202
  readonly data?: unknown;
203
203
  };
204
204
  }, McpError, never>;
205
205
  declare const decodeJsonRpcMessageFromJson: (server: string, text: string) => Effect.Effect<{
206
- readonly id: string | number;
207
206
  readonly jsonrpc: "2.0";
207
+ readonly id: string | number;
208
208
  readonly method: string;
209
209
  readonly params?: unknown;
210
210
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.d.mts","names":[],"sources":["../../src/client/protocol.ts"],"mappings":"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"}
1
+ {"version":3,"file":"protocol.d.mts","names":[],"sources":["../../src/client/protocol.ts"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { McpError } from "./errors.mjs";
2
2
  import { Array, Effect, Option, Predicate } from "effect";
3
3
  import * as Schema from "effect/Schema";
4
- import { AudioPart, ImagePart, TextPart, ToolDef, ToolJsonSchemaObject, ToolResult, decodeToolJsonSchemaObject, inlineBase64Source } from "@yolk-sdk/agent/protocol";
4
+ import { AudioPart, FilePart, ImagePart, TextPart, ToolDef, ToolJsonSchemaObject, ToolResult, decodeToolJsonSchemaObject, inlineBase64Source } from "@yolk-sdk/agent/protocol";
5
5
  //#region src/client/protocol.ts
6
6
  const latestMcpProtocolVersion = "2026-07-28";
7
7
  const legacyMcpProtocolVersion = "2024-11-05";
@@ -175,12 +175,29 @@ const fallbackTextForContentBlock = (block) => {
175
175
  default: return `Unsupported MCP ${type} content.`;
176
176
  }
177
177
  };
178
- const embeddedResourceText = (block) => Schema.decodeUnknownOption(EmbeddedResourceContentBlock)(block).pipe(Option.flatMap(({ resource }) => {
179
- if (resource.text !== void 0) return Option.some(resource.text);
180
- return Option.all({
181
- uri: Option.fromNullishOr(resource.uri),
182
- blob: Option.fromNullishOr(resource.blob)
183
- }).pipe(Option.map(({ uri, blob }) => `MCP resource: ${uri}\n${blob}`));
178
+ const resourceFilename = (uri) => {
179
+ const segments = (uri.split(/[?#]/u, 1)[0] ?? "").split("/").filter((part) => part.length > 0);
180
+ const segment = segments[segments.length - 1];
181
+ if (segment === void 0 || segment.endsWith(":")) return void 0;
182
+ try {
183
+ return decodeURIComponent(segment);
184
+ } catch {
185
+ return segment;
186
+ }
187
+ };
188
+ const embeddedResourcePart = (block) => Schema.decodeUnknownOption(EmbeddedResourceContentBlock)(block).pipe(Option.flatMap(({ resource }) => {
189
+ if (resource.text !== void 0) return Option.some(TextPart.make({ text: resource.text }));
190
+ if (resource.blob === void 0) return Option.none();
191
+ const mimeType = resource.mimeType ?? "application/octet-stream";
192
+ const filename = resource.uri === void 0 ? void 0 : resourceFilename(resource.uri);
193
+ return Option.some(filename === void 0 ? FilePart.make({
194
+ source: inlineBase64Source(resource.blob),
195
+ mimeType
196
+ }) : FilePart.make({
197
+ source: inlineBase64Source(resource.blob),
198
+ mimeType,
199
+ filename
200
+ }));
184
201
  }));
185
202
  const resourceLinkText = (block) => Schema.decodeUnknownOption(ResourceLinkContentBlock)(block).pipe(Option.map(({ name, uri }) => {
186
203
  return `MCP resource link: ${name ?? uri} (${uri})`;
@@ -204,7 +221,7 @@ const contentPartFromBlock = (block) => {
204
221
  if (type === "text") return TextPart.make({ text: Option.getOrElse(contentBlockText(block), () => "") });
205
222
  if (type === "image") return Option.getOrElse(imagePartFromBlock(block), () => TextPart.make({ text: fallbackTextForContentBlock(block) }));
206
223
  if (type === "audio") return Option.getOrElse(audioPartFromBlock(block), () => TextPart.make({ text: fallbackTextForContentBlock(block) }));
207
- if (type === "resource") return TextPart.make({ text: embeddedResourceText(block).pipe(Option.getOrElse(() => fallbackTextForContentBlock(block))) });
224
+ if (type === "resource") return Option.getOrElse(embeddedResourcePart(block), () => TextPart.make({ text: fallbackTextForContentBlock(block) }));
208
225
  if (type === "resource_link") return TextPart.make({ text: resourceLinkText(block).pipe(Option.getOrElse(() => fallbackTextForContentBlock(block))) });
209
226
  return TextPart.make({ text: fallbackTextForContentBlock(block) });
210
227
  };
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.mjs","names":["Arr"],"sources":["../../src/client/protocol.ts"],"sourcesContent":["import { Array as Arr, Effect, Option, Predicate } from 'effect'\nimport * as Schema from 'effect/Schema'\nimport {\n AudioPart,\n ImagePart,\n TextPart,\n ToolDef,\n ToolJsonSchemaObject,\n ToolResult,\n decodeToolJsonSchemaObject,\n inlineBase64Source\n} from '@yolk-sdk/agent/protocol'\nimport type { Content, ContentPart, ToolExposure } from '@yolk-sdk/agent/protocol'\nimport { McpError } from './errors.ts'\n\nexport const latestMcpProtocolVersion = '2026-07-28'\n\nexport const legacyMcpProtocolVersion = '2024-11-05'\n\nexport const JsonRpcErrorObject = Schema.Struct({\n code: Schema.Number,\n message: Schema.String,\n data: Schema.optional(Schema.Unknown)\n})\n\nexport type JsonRpcErrorObject = typeof JsonRpcErrorObject.Type\n\nexport const JsonRpcSuccessResponse = Schema.Struct({\n jsonrpc: Schema.Literal('2.0'),\n id: Schema.Union([Schema.String, Schema.Number, Schema.Null]),\n result: Schema.Unknown\n})\n\nexport type JsonRpcSuccessResponse = typeof JsonRpcSuccessResponse.Type\n\nexport const JsonRpcErrorResponse = Schema.Struct({\n jsonrpc: Schema.Literal('2.0'),\n id: Schema.Union([Schema.String, Schema.Number, Schema.Null]),\n error: JsonRpcErrorObject\n})\n\nexport type JsonRpcErrorResponse = typeof JsonRpcErrorResponse.Type\n\nexport const JsonRpcResponse = Schema.Union([JsonRpcSuccessResponse, JsonRpcErrorResponse])\n\nexport type JsonRpcResponse = typeof JsonRpcResponse.Type\n\nexport const JsonRpcRequest = Schema.Struct({\n jsonrpc: Schema.Literal('2.0'),\n id: Schema.Union([Schema.String, Schema.Number]),\n method: Schema.String,\n params: Schema.optional(Schema.Unknown)\n})\n\nexport type JsonRpcRequest = typeof JsonRpcRequest.Type\n\nexport const JsonRpcNotification = Schema.Struct({\n jsonrpc: Schema.Literal('2.0'),\n method: Schema.String,\n params: Schema.optional(Schema.Unknown)\n})\n\nexport type JsonRpcNotification = typeof JsonRpcNotification.Type\n\nexport const JsonRpcMessage = Schema.Union([JsonRpcRequest, JsonRpcNotification])\n\nexport type JsonRpcMessage = typeof JsonRpcMessage.Type\n\nexport const McpToolAnnotations = Schema.Record(Schema.String, Schema.Unknown)\n\nexport type McpToolAnnotations = typeof McpToolAnnotations.Type\n\nexport const McpTool = Schema.Struct({\n name: Schema.String,\n title: Schema.optional(Schema.String),\n description: Schema.optional(Schema.String),\n inputSchema: Schema.optional(ToolJsonSchemaObject),\n outputSchema: Schema.optional(Schema.Unknown),\n annotations: Schema.optional(McpToolAnnotations)\n})\n\nexport type McpTool = typeof McpTool.Type\n\nexport const ToolsListResult = Schema.Struct({\n tools: Schema.Array(McpTool)\n})\n\nexport type ToolsListResult = typeof ToolsListResult.Type\n\nexport const TextContentBlock = Schema.Struct({\n type: Schema.Literal('text'),\n text: Schema.String\n})\n\nexport type TextContentBlock = typeof TextContentBlock.Type\n\nexport const GenericContentBlock = Schema.Record(Schema.String, Schema.Unknown)\n\nexport type GenericContentBlock = typeof GenericContentBlock.Type\n\nconst EmbeddedResourceContentBlock = Schema.Struct({\n type: Schema.Literal('resource'),\n resource: Schema.Struct({\n uri: Schema.optional(Schema.String),\n text: Schema.optional(Schema.String),\n blob: Schema.optional(Schema.String),\n mimeType: Schema.optional(Schema.String)\n })\n})\n\nconst ResourceLinkContentBlock = Schema.Struct({\n type: Schema.Literal('resource_link'),\n uri: Schema.String,\n name: Schema.optional(Schema.String),\n mimeType: Schema.optional(Schema.String)\n})\n\nexport const ToolCallResult = Schema.Struct({\n content: Schema.optional(Schema.Array(GenericContentBlock)),\n isError: Schema.optional(Schema.Boolean),\n structuredContent: Schema.optional(Schema.Unknown)\n})\n\nexport type ToolCallResult = typeof ToolCallResult.Type\n\nexport const InitializeClientInfo = Schema.Struct({\n name: Schema.String,\n version: Schema.String\n})\n\nexport type InitializeClientInfo = typeof InitializeClientInfo.Type\n\nexport const InitializeParams = Schema.Struct({\n protocolVersion: Schema.String,\n capabilities: Schema.Record(Schema.String, Schema.Unknown),\n clientInfo: InitializeClientInfo\n})\n\nexport type InitializeParams = typeof InitializeParams.Type\n\nexport const InitializedNotification = Schema.Struct({\n jsonrpc: Schema.Literal('2.0'),\n method: Schema.Literal('notifications/initialized')\n})\n\nexport type InitializedNotification = typeof InitializedNotification.Type\n\nexport const ToolsCallParams = Schema.Struct({\n name: Schema.String,\n arguments: Schema.optional(Schema.Unknown)\n})\n\nexport type ToolsCallParams = typeof ToolsCallParams.Type\n\nexport const makeJsonRpcRequest = (input: {\n readonly id: string | number\n readonly method: string\n readonly params?: unknown\n}): JsonRpcRequest => {\n const id = input.id\n const method = input.method\n\n if (input.params !== undefined) {\n return JsonRpcRequest.make({\n jsonrpc: '2.0',\n id,\n method,\n params: input.params\n })\n }\n\n return JsonRpcRequest.make({\n jsonrpc: '2.0',\n id,\n method\n })\n}\n\nexport const makeInitializedNotification = (): JsonRpcNotification =>\n InitializedNotification.make({\n jsonrpc: '2.0',\n method: 'notifications/initialized'\n })\n\nexport const makeInitializeParams = (input: {\n readonly name: string\n readonly version: string\n}): InitializeParams =>\n InitializeParams.make({\n protocolVersion: legacyMcpProtocolVersion,\n capabilities: {},\n clientInfo: InitializeClientInfo.make({\n name: input.name,\n version: input.version\n })\n })\n\nexport const jsonRpcErrorToMcpError = (server: string, error: JsonRpcErrorObject) =>\n new McpError({\n server,\n message: `MCP JSON-RPC error ${error.code}: ${error.message}`,\n cause: 'protocol'\n })\n\n/** Tool exposure (`callableBy`/`discovery`/`loading`) for adapted MCP tools: one value for every\n * tool, or per listed tool.\n * Omitted: the agent defaults (`callableBy: 'all'`). `resolveTools` still rejects invalid\n * combinations (for example `discovery` without `callableBy: 'codemode'`).\n */\nexport type McpToolExposureResolver =\n | ToolExposure\n | ((tool: McpTool, serverName: string) => ToolExposure)\n\ntype McpToolDefFields = {\n name: string\n description: string\n parameters: ToolDef['parameters']\n outputSchema?: ToolDef['outputSchema']\n callableBy?: ToolDef['callableBy']\n discovery?: ToolDef['discovery']\n loading?: ToolDef['loading']\n}\n\n/** Adapts one listed MCP tool. A present `outputSchema` that is a plain JSON Schema object\n * passes through as declaration-only `ToolDef.outputSchema`; any other value is omitted.\n * `exposure` (host policy) sets `callableBy`/`discovery`/`loading`; without it none is set.\n */\nexport const mcpToolToToolDef = (input: {\n readonly serverName: string\n readonly tool: McpTool\n readonly exposure?: McpToolExposureResolver\n}) => {\n const fields: McpToolDefFields = {\n name: `${sanitizeMcpName(input.serverName)}_${sanitizeMcpName(input.tool.name)}`,\n description: input.tool.description ?? `MCP tool ${input.serverName}/${input.tool.name}`,\n parameters: input.tool.inputSchema ?? { type: 'object', additionalProperties: true }\n }\n\n const outputSchema = decodeToolJsonSchemaObject(input.tool.outputSchema)\n\n if (Option.isSome(outputSchema)) fields.outputSchema = outputSchema.value\n\n const exposure = Predicate.isFunction(input.exposure)\n ? input.exposure(input.tool, input.serverName)\n : input.exposure\n\n if (exposure?.callableBy !== undefined) fields.callableBy = exposure.callableBy\n\n if (exposure?.discovery !== undefined) fields.discovery = exposure.discovery\n\n if (exposure?.loading !== undefined) fields.loading = exposure.loading\n\n return ToolDef.make(fields)\n}\n\nexport const sanitizeMcpName = (name: string) => {\n const sanitized = name.replace(/[^a-zA-Z0-9_-]/g, '_')\n\n return sanitized.length === 0 ? 'mcp' : sanitized\n}\n\nconst stringProperty = (block: GenericContentBlock, key: string) =>\n Schema.decodeUnknownOption(Schema.String)(block[key])\n\nconst contentBlockText = (block: GenericContentBlock): Option.Option<string> => {\n const type = block['type']\n const text = stringProperty(block, 'text')\n\n if (type === 'text') {\n return text\n }\n\n return Option.none()\n}\n\nconst fallbackTextForContentBlock = (block: GenericContentBlock) => {\n const type = stringProperty(block, 'type').pipe(Option.getOrElse(() => 'unknown'))\n const name = stringProperty(block, 'name')\n const uri = stringProperty(block, 'uri')\n const url = stringProperty(block, 'url')\n const label = Option.getOrElse(Option.firstSomeOf([name, uri, url]), () => type)\n\n switch (type) {\n case 'resource':\n return `MCP resource: ${label}`\n case 'resource_link':\n return `MCP resource link: ${label}`\n case 'image':\n return `MCP image: ${label}`\n case 'audio':\n return `MCP audio: ${label}`\n default:\n return `Unsupported MCP ${type} content.`\n }\n}\n\nconst embeddedResourceText = (block: GenericContentBlock): Option.Option<string> =>\n Schema.decodeUnknownOption(EmbeddedResourceContentBlock)(block).pipe(\n Option.flatMap(({ resource }) => {\n if (resource.text !== undefined) {\n return Option.some(resource.text)\n }\n\n return Option.all({\n uri: Option.fromNullishOr(resource.uri),\n blob: Option.fromNullishOr(resource.blob)\n }).pipe(Option.map(({ uri, blob }) => `MCP resource: ${uri}\\n${blob}`))\n })\n )\n\nconst resourceLinkText = (block: GenericContentBlock): Option.Option<string> =>\n Schema.decodeUnknownOption(ResourceLinkContentBlock)(block).pipe(\n Option.map(({ name, uri }) => {\n const label = name ?? uri\n\n return `MCP resource link: ${label} (${uri})`\n })\n )\n\nconst imagePartFromBlock = (block: GenericContentBlock): Option.Option<ContentPart> =>\n Option.all({\n data: stringProperty(block, 'data'),\n mimeType: stringProperty(block, 'mimeType')\n }).pipe(\n Option.map(({ data, mimeType }) =>\n ImagePart.make({ source: inlineBase64Source(data), mimeType })\n )\n )\n\nconst audioPartFromBlock = (block: GenericContentBlock): Option.Option<ContentPart> =>\n Option.all({\n data: stringProperty(block, 'data'),\n mimeType: stringProperty(block, 'mimeType')\n }).pipe(\n Option.map(({ data, mimeType }) =>\n AudioPart.make({ source: inlineBase64Source(data), mimeType })\n )\n )\n\nconst contentPartFromBlock = (block: GenericContentBlock): ContentPart => {\n const type = block['type']\n\n if (type === 'text') {\n return TextPart.make({ text: Option.getOrElse(contentBlockText(block), () => '') })\n }\n\n if (type === 'image') {\n return Option.getOrElse(imagePartFromBlock(block), () =>\n TextPart.make({ text: fallbackTextForContentBlock(block) })\n )\n }\n\n if (type === 'audio') {\n return Option.getOrElse(audioPartFromBlock(block), () =>\n TextPart.make({ text: fallbackTextForContentBlock(block) })\n )\n }\n\n if (type === 'resource') {\n return TextPart.make({\n text: embeddedResourceText(block).pipe(\n Option.getOrElse(() => fallbackTextForContentBlock(block))\n )\n })\n }\n\n if (type === 'resource_link') {\n return TextPart.make({\n text: resourceLinkText(block).pipe(Option.getOrElse(() => fallbackTextForContentBlock(block)))\n })\n }\n\n return TextPart.make({ text: fallbackTextForContentBlock(block) })\n}\n\nconst contentFromBlocks = (blocks: ReadonlyArray<GenericContentBlock>): Content => {\n const textBlocks = Arr.getSomes(Arr.map(blocks, contentBlockText))\n\n if (textBlocks.length === blocks.length) {\n return textBlocks.join('\\n')\n }\n\n return Arr.map(blocks, contentPartFromBlock)\n}\n\nexport const toolCallResultToToolResult = (input: {\n readonly toolCallId: string\n readonly result: ToolCallResult\n}) => {\n const content = input.result.content ?? []\n\n const resultContent =\n content.length > 0\n ? contentFromBlocks(content)\n : input.result.structuredContent === undefined\n ? 'Unsupported MCP tool content.'\n : 'Structured MCP tool result.'\n\n return ToolResult.make({\n toolCallId: input.toolCallId,\n content: resultContent,\n isError: input.result.isError,\n structuredContent: input.result.structuredContent\n })\n}\n\nexport const decodeJsonRpcResponse = Schema.decodeUnknownEffect(JsonRpcResponse)\n\nexport const decodeToolsListResult = Schema.decodeUnknownEffect(ToolsListResult)\n\nexport const decodeToolCallResult = Schema.decodeUnknownEffect(ToolCallResult)\n\nexport const encodeJsonRpcMessage = (\n server: string,\n message: JsonRpcRequest | JsonRpcNotification\n) =>\n Schema.encodeUnknownEffect(Schema.fromJsonString(Schema.Unknown))(message).pipe(\n Effect.mapError(\n error =>\n new McpError({\n server,\n message: `Could not encode MCP JSON-RPC message: ${String(error)}`,\n cause: 'encoding'\n })\n )\n )\n\nconst decodeJsonString = (server: string, text: string) =>\n Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Unknown))(text).pipe(\n Effect.mapError(\n error =>\n new McpError({\n server,\n message: `Malformed MCP JSON: ${String(error)}`,\n cause: 'parse'\n })\n )\n )\n\nexport const decodeJsonRpcResponseFromJson = (server: string, text: string) =>\n decodeJsonString(server, text).pipe(\n Effect.flatMap(decodeJsonRpcResponse),\n Effect.mapError(error =>\n error instanceof McpError\n ? error\n : new McpError({\n server,\n message: `Invalid MCP JSON-RPC response: ${String(error)}`,\n cause: 'validation'\n })\n )\n )\n\nexport const decodeJsonRpcMessageFromJson = (server: string, text: string) =>\n decodeJsonString(server, text).pipe(\n Effect.flatMap(Schema.decodeUnknownEffect(JsonRpcMessage)),\n Effect.mapError(error =>\n error instanceof McpError\n ? error\n : new McpError({\n server,\n message: `Invalid MCP JSON-RPC message: ${String(error)}`,\n cause: 'validation'\n })\n )\n )\n"],"mappings":";;;;;AAeA,MAAa,2BAA2B;AAExC,MAAa,2BAA2B;AAExC,MAAa,qBAAqB,OAAO,OAAO;CAC9C,MAAM,OAAO;CACb,SAAS,OAAO;CAChB,MAAM,OAAO,SAAS,OAAO,OAAO;AACtC,CAAC;AAID,MAAa,yBAAyB,OAAO,OAAO;CAClD,SAAS,OAAO,QAAQ,KAAK;CAC7B,IAAI,OAAO,MAAM;EAAC,OAAO;EAAQ,OAAO;EAAQ,OAAO;CAAI,CAAC;CAC5D,QAAQ,OAAO;AACjB,CAAC;AAID,MAAa,uBAAuB,OAAO,OAAO;CAChD,SAAS,OAAO,QAAQ,KAAK;CAC7B,IAAI,OAAO,MAAM;EAAC,OAAO;EAAQ,OAAO;EAAQ,OAAO;CAAI,CAAC;CAC5D,OAAO;AACT,CAAC;AAID,MAAa,kBAAkB,OAAO,MAAM,CAAC,wBAAwB,oBAAoB,CAAC;AAI1F,MAAa,iBAAiB,OAAO,OAAO;CAC1C,SAAS,OAAO,QAAQ,KAAK;CAC7B,IAAI,OAAO,MAAM,CAAC,OAAO,QAAQ,OAAO,MAAM,CAAC;CAC/C,QAAQ,OAAO;CACf,QAAQ,OAAO,SAAS,OAAO,OAAO;AACxC,CAAC;AAID,MAAa,sBAAsB,OAAO,OAAO;CAC/C,SAAS,OAAO,QAAQ,KAAK;CAC7B,QAAQ,OAAO;CACf,QAAQ,OAAO,SAAS,OAAO,OAAO;AACxC,CAAC;AAID,MAAa,iBAAiB,OAAO,MAAM,CAAC,gBAAgB,mBAAmB,CAAC;AAIhF,MAAa,qBAAqB,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO;AAI7E,MAAa,UAAU,OAAO,OAAO;CACnC,MAAM,OAAO;CACb,OAAO,OAAO,SAAS,OAAO,MAAM;CACpC,aAAa,OAAO,SAAS,OAAO,MAAM;CAC1C,aAAa,OAAO,SAAS,oBAAoB;CACjD,cAAc,OAAO,SAAS,OAAO,OAAO;CAC5C,aAAa,OAAO,SAAS,kBAAkB;AACjD,CAAC;AAID,MAAa,kBAAkB,OAAO,OAAO,EAC3C,OAAO,OAAO,MAAM,OAAO,EAC7B,CAAC;AAID,MAAa,mBAAmB,OAAO,OAAO;CAC5C,MAAM,OAAO,QAAQ,MAAM;CAC3B,MAAM,OAAO;AACf,CAAC;AAID,MAAa,sBAAsB,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO;AAI9E,MAAM,+BAA+B,OAAO,OAAO;CACjD,MAAM,OAAO,QAAQ,UAAU;CAC/B,UAAU,OAAO,OAAO;EACtB,KAAK,OAAO,SAAS,OAAO,MAAM;EAClC,MAAM,OAAO,SAAS,OAAO,MAAM;EACnC,MAAM,OAAO,SAAS,OAAO,MAAM;EACnC,UAAU,OAAO,SAAS,OAAO,MAAM;CACzC,CAAC;AACH,CAAC;AAED,MAAM,2BAA2B,OAAO,OAAO;CAC7C,MAAM,OAAO,QAAQ,eAAe;CACpC,KAAK,OAAO;CACZ,MAAM,OAAO,SAAS,OAAO,MAAM;CACnC,UAAU,OAAO,SAAS,OAAO,MAAM;AACzC,CAAC;AAED,MAAa,iBAAiB,OAAO,OAAO;CAC1C,SAAS,OAAO,SAAS,OAAO,MAAM,mBAAmB,CAAC;CAC1D,SAAS,OAAO,SAAS,OAAO,OAAO;CACvC,mBAAmB,OAAO,SAAS,OAAO,OAAO;AACnD,CAAC;AAID,MAAa,uBAAuB,OAAO,OAAO;CAChD,MAAM,OAAO;CACb,SAAS,OAAO;AAClB,CAAC;AAID,MAAa,mBAAmB,OAAO,OAAO;CAC5C,iBAAiB,OAAO;CACxB,cAAc,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO;CACzD,YAAY;AACd,CAAC;AAID,MAAa,0BAA0B,OAAO,OAAO;CACnD,SAAS,OAAO,QAAQ,KAAK;CAC7B,QAAQ,OAAO,QAAQ,2BAA2B;AACpD,CAAC;AAID,MAAa,kBAAkB,OAAO,OAAO;CAC3C,MAAM,OAAO;CACb,WAAW,OAAO,SAAS,OAAO,OAAO;AAC3C,CAAC;AAID,MAAa,sBAAsB,UAIb;CACpB,MAAM,KAAK,MAAM;CACjB,MAAM,SAAS,MAAM;CAErB,IAAI,MAAM,WAAW,KAAA,GACnB,OAAO,eAAe,KAAK;EACzB,SAAS;EACT;EACA;EACA,QAAQ,MAAM;CAChB,CAAC;CAGH,OAAO,eAAe,KAAK;EACzB,SAAS;EACT;EACA;CACF,CAAC;AACH;AAEA,MAAa,oCACX,wBAAwB,KAAK;CAC3B,SAAS;CACT,QAAQ;AACV,CAAC;AAEH,MAAa,wBAAwB,UAInC,iBAAiB,KAAK;CACpB,iBAAiB;CACjB,cAAc,CAAC;CACf,YAAY,qBAAqB,KAAK;EACpC,MAAM,MAAM;EACZ,SAAS,MAAM;CACjB,CAAC;AACH,CAAC;AAEH,MAAa,0BAA0B,QAAgB,UACrD,IAAI,SAAS;CACX;CACA,SAAS,sBAAsB,MAAM,KAAK,IAAI,MAAM;CACpD,OAAO;AACT,CAAC;;;;;AAyBH,MAAa,oBAAoB,UAI3B;CACJ,MAAM,SAA2B;EAC/B,MAAM,GAAG,gBAAgB,MAAM,UAAU,EAAE,GAAG,gBAAgB,MAAM,KAAK,IAAI;EAC7E,aAAa,MAAM,KAAK,eAAe,YAAY,MAAM,WAAW,GAAG,MAAM,KAAK;EAClF,YAAY,MAAM,KAAK,eAAe;GAAE,MAAM;GAAU,sBAAsB;EAAK;CACrF;CAEA,MAAM,eAAe,2BAA2B,MAAM,KAAK,YAAY;CAEvE,IAAI,OAAO,OAAO,YAAY,GAAG,OAAO,eAAe,aAAa;CAEpE,MAAM,WAAW,UAAU,WAAW,MAAM,QAAQ,IAChD,MAAM,SAAS,MAAM,MAAM,MAAM,UAAU,IAC3C,MAAM;CAEV,IAAI,UAAU,eAAe,KAAA,GAAW,OAAO,aAAa,SAAS;CAErE,IAAI,UAAU,cAAc,KAAA,GAAW,OAAO,YAAY,SAAS;CAEnE,IAAI,UAAU,YAAY,KAAA,GAAW,OAAO,UAAU,SAAS;CAE/D,OAAO,QAAQ,KAAK,MAAM;AAC5B;AAEA,MAAa,mBAAmB,SAAiB;CAC/C,MAAM,YAAY,KAAK,QAAQ,mBAAmB,GAAG;CAErD,OAAO,UAAU,WAAW,IAAI,QAAQ;AAC1C;AAEA,MAAM,kBAAkB,OAA4B,QAClD,OAAO,oBAAoB,OAAO,MAAM,EAAE,MAAM,IAAI;AAEtD,MAAM,oBAAoB,UAAsD;CAC9E,MAAM,OAAO,MAAM;CACnB,MAAM,OAAO,eAAe,OAAO,MAAM;CAEzC,IAAI,SAAS,QACX,OAAO;CAGT,OAAO,OAAO,KAAK;AACrB;AAEA,MAAM,+BAA+B,UAA+B;CAClE,MAAM,OAAO,eAAe,OAAO,MAAM,EAAE,KAAK,OAAO,gBAAgB,SAAS,CAAC;CACjF,MAAM,OAAO,eAAe,OAAO,MAAM;CACzC,MAAM,MAAM,eAAe,OAAO,KAAK;CACvC,MAAM,MAAM,eAAe,OAAO,KAAK;CACvC,MAAM,QAAQ,OAAO,UAAU,OAAO,YAAY;EAAC;EAAM;EAAK;CAAG,CAAC,SAAS,IAAI;CAE/E,QAAQ,MAAR;EACE,KAAK,YACH,OAAO,iBAAiB;EAC1B,KAAK,iBACH,OAAO,sBAAsB;EAC/B,KAAK,SACH,OAAO,cAAc;EACvB,KAAK,SACH,OAAO,cAAc;EACvB,SACE,OAAO,mBAAmB,KAAK;CACnC;AACF;AAEA,MAAM,wBAAwB,UAC5B,OAAO,oBAAoB,4BAA4B,EAAE,KAAK,EAAE,KAC9D,OAAO,SAAS,EAAE,eAAe;CAC/B,IAAI,SAAS,SAAS,KAAA,GACpB,OAAO,OAAO,KAAK,SAAS,IAAI;CAGlC,OAAO,OAAO,IAAI;EAChB,KAAK,OAAO,cAAc,SAAS,GAAG;EACtC,MAAM,OAAO,cAAc,SAAS,IAAI;CAC1C,CAAC,EAAE,KAAK,OAAO,KAAK,EAAE,KAAK,WAAW,iBAAiB,IAAI,IAAI,MAAM,CAAC;AACxE,CAAC,CACH;AAEF,MAAM,oBAAoB,UACxB,OAAO,oBAAoB,wBAAwB,EAAE,KAAK,EAAE,KAC1D,OAAO,KAAK,EAAE,MAAM,UAAU;CAG5B,OAAO,sBAFO,QAAQ,IAEa,IAAI,IAAI;AAC7C,CAAC,CACH;AAEF,MAAM,sBAAsB,UAC1B,OAAO,IAAI;CACT,MAAM,eAAe,OAAO,MAAM;CAClC,UAAU,eAAe,OAAO,UAAU;AAC5C,CAAC,EAAE,KACD,OAAO,KAAK,EAAE,MAAM,eAClB,UAAU,KAAK;CAAE,QAAQ,mBAAmB,IAAI;CAAG;AAAS,CAAC,CAC/D,CACF;AAEF,MAAM,sBAAsB,UAC1B,OAAO,IAAI;CACT,MAAM,eAAe,OAAO,MAAM;CAClC,UAAU,eAAe,OAAO,UAAU;AAC5C,CAAC,EAAE,KACD,OAAO,KAAK,EAAE,MAAM,eAClB,UAAU,KAAK;CAAE,QAAQ,mBAAmB,IAAI;CAAG;AAAS,CAAC,CAC/D,CACF;AAEF,MAAM,wBAAwB,UAA4C;CACxE,MAAM,OAAO,MAAM;CAEnB,IAAI,SAAS,QACX,OAAO,SAAS,KAAK,EAAE,MAAM,OAAO,UAAU,iBAAiB,KAAK,SAAS,EAAE,EAAE,CAAC;CAGpF,IAAI,SAAS,SACX,OAAO,OAAO,UAAU,mBAAmB,KAAK,SAC9C,SAAS,KAAK,EAAE,MAAM,4BAA4B,KAAK,EAAE,CAAC,CAC5D;CAGF,IAAI,SAAS,SACX,OAAO,OAAO,UAAU,mBAAmB,KAAK,SAC9C,SAAS,KAAK,EAAE,MAAM,4BAA4B,KAAK,EAAE,CAAC,CAC5D;CAGF,IAAI,SAAS,YACX,OAAO,SAAS,KAAK,EACnB,MAAM,qBAAqB,KAAK,EAAE,KAChC,OAAO,gBAAgB,4BAA4B,KAAK,CAAC,CAC3D,EACF,CAAC;CAGH,IAAI,SAAS,iBACX,OAAO,SAAS,KAAK,EACnB,MAAM,iBAAiB,KAAK,EAAE,KAAK,OAAO,gBAAgB,4BAA4B,KAAK,CAAC,CAAC,EAC/F,CAAC;CAGH,OAAO,SAAS,KAAK,EAAE,MAAM,4BAA4B,KAAK,EAAE,CAAC;AACnE;AAEA,MAAM,qBAAqB,WAAwD;CACjF,MAAM,aAAaA,MAAI,SAASA,MAAI,IAAI,QAAQ,gBAAgB,CAAC;CAEjE,IAAI,WAAW,WAAW,OAAO,QAC/B,OAAO,WAAW,KAAK,IAAI;CAG7B,OAAOA,MAAI,IAAI,QAAQ,oBAAoB;AAC7C;AAEA,MAAa,8BAA8B,UAGrC;CACJ,MAAM,UAAU,MAAM,OAAO,WAAW,CAAC;CAEzC,MAAM,gBACJ,QAAQ,SAAS,IACb,kBAAkB,OAAO,IACzB,MAAM,OAAO,sBAAsB,KAAA,IACjC,kCACA;CAER,OAAO,WAAW,KAAK;EACrB,YAAY,MAAM;EAClB,SAAS;EACT,SAAS,MAAM,OAAO;EACtB,mBAAmB,MAAM,OAAO;CAClC,CAAC;AACH;AAEA,MAAa,wBAAwB,OAAO,oBAAoB,eAAe;AAE/E,MAAa,wBAAwB,OAAO,oBAAoB,eAAe;AAE/E,MAAa,uBAAuB,OAAO,oBAAoB,cAAc;AAE7E,MAAa,wBACX,QACA,YAEA,OAAO,oBAAoB,OAAO,eAAe,OAAO,OAAO,CAAC,EAAE,OAAO,EAAE,KACzE,OAAO,UACL,UACE,IAAI,SAAS;CACX;CACA,SAAS,0CAA0C,OAAO,KAAK;CAC/D,OAAO;AACT,CAAC,CACL,CACF;AAEF,MAAM,oBAAoB,QAAgB,SACxC,OAAO,oBAAoB,OAAO,eAAe,OAAO,OAAO,CAAC,EAAE,IAAI,EAAE,KACtE,OAAO,UACL,UACE,IAAI,SAAS;CACX;CACA,SAAS,uBAAuB,OAAO,KAAK;CAC5C,OAAO;AACT,CAAC,CACL,CACF;AAEF,MAAa,iCAAiC,QAAgB,SAC5D,iBAAiB,QAAQ,IAAI,EAAE,KAC7B,OAAO,QAAQ,qBAAqB,GACpC,OAAO,UAAS,UACd,iBAAiB,WACb,QACA,IAAI,SAAS;CACX;CACA,SAAS,kCAAkC,OAAO,KAAK;CACvD,OAAO;AACT,CAAC,CACP,CACF;AAEF,MAAa,gCAAgC,QAAgB,SAC3D,iBAAiB,QAAQ,IAAI,EAAE,KAC7B,OAAO,QAAQ,OAAO,oBAAoB,cAAc,CAAC,GACzD,OAAO,UAAS,UACd,iBAAiB,WACb,QACA,IAAI,SAAS;CACX;CACA,SAAS,iCAAiC,OAAO,KAAK;CACtD,OAAO;AACT,CAAC,CACP,CACF"}
1
+ {"version":3,"file":"protocol.mjs","names":["Arr"],"sources":["../../src/client/protocol.ts"],"sourcesContent":["import { Array as Arr, Effect, Option, Predicate } from 'effect'\nimport * as Schema from 'effect/Schema'\nimport {\n AudioPart,\n FilePart,\n ImagePart,\n TextPart,\n ToolDef,\n ToolJsonSchemaObject,\n ToolResult,\n decodeToolJsonSchemaObject,\n inlineBase64Source\n} from '@yolk-sdk/agent/protocol'\nimport type { Content, ContentPart, ToolExposure } from '@yolk-sdk/agent/protocol'\nimport { McpError } from './errors.ts'\n\nexport const latestMcpProtocolVersion = '2026-07-28'\n\nexport const legacyMcpProtocolVersion = '2024-11-05'\n\nexport const JsonRpcErrorObject = Schema.Struct({\n code: Schema.Number,\n message: Schema.String,\n data: Schema.optional(Schema.Unknown)\n})\n\nexport type JsonRpcErrorObject = typeof JsonRpcErrorObject.Type\n\nexport const JsonRpcSuccessResponse = Schema.Struct({\n jsonrpc: Schema.Literal('2.0'),\n id: Schema.Union([Schema.String, Schema.Number, Schema.Null]),\n result: Schema.Unknown\n})\n\nexport type JsonRpcSuccessResponse = typeof JsonRpcSuccessResponse.Type\n\nexport const JsonRpcErrorResponse = Schema.Struct({\n jsonrpc: Schema.Literal('2.0'),\n id: Schema.Union([Schema.String, Schema.Number, Schema.Null]),\n error: JsonRpcErrorObject\n})\n\nexport type JsonRpcErrorResponse = typeof JsonRpcErrorResponse.Type\n\nexport const JsonRpcResponse = Schema.Union([JsonRpcSuccessResponse, JsonRpcErrorResponse])\n\nexport type JsonRpcResponse = typeof JsonRpcResponse.Type\n\nexport const JsonRpcRequest = Schema.Struct({\n jsonrpc: Schema.Literal('2.0'),\n id: Schema.Union([Schema.String, Schema.Number]),\n method: Schema.String,\n params: Schema.optional(Schema.Unknown)\n})\n\nexport type JsonRpcRequest = typeof JsonRpcRequest.Type\n\nexport const JsonRpcNotification = Schema.Struct({\n jsonrpc: Schema.Literal('2.0'),\n method: Schema.String,\n params: Schema.optional(Schema.Unknown)\n})\n\nexport type JsonRpcNotification = typeof JsonRpcNotification.Type\n\nexport const JsonRpcMessage = Schema.Union([JsonRpcRequest, JsonRpcNotification])\n\nexport type JsonRpcMessage = typeof JsonRpcMessage.Type\n\nexport const McpToolAnnotations = Schema.Record(Schema.String, Schema.Unknown)\n\nexport type McpToolAnnotations = typeof McpToolAnnotations.Type\n\nexport const McpTool = Schema.Struct({\n name: Schema.String,\n title: Schema.optional(Schema.String),\n description: Schema.optional(Schema.String),\n inputSchema: Schema.optional(ToolJsonSchemaObject),\n outputSchema: Schema.optional(Schema.Unknown),\n annotations: Schema.optional(McpToolAnnotations)\n})\n\nexport type McpTool = typeof McpTool.Type\n\nexport const ToolsListResult = Schema.Struct({\n tools: Schema.Array(McpTool)\n})\n\nexport type ToolsListResult = typeof ToolsListResult.Type\n\nexport const TextContentBlock = Schema.Struct({\n type: Schema.Literal('text'),\n text: Schema.String\n})\n\nexport type TextContentBlock = typeof TextContentBlock.Type\n\nexport const GenericContentBlock = Schema.Record(Schema.String, Schema.Unknown)\n\nexport type GenericContentBlock = typeof GenericContentBlock.Type\n\nconst EmbeddedResourceContentBlock = Schema.Struct({\n type: Schema.Literal('resource'),\n resource: Schema.Struct({\n uri: Schema.optional(Schema.String),\n text: Schema.optional(Schema.String),\n blob: Schema.optional(Schema.String),\n mimeType: Schema.optional(Schema.String)\n })\n})\n\nconst ResourceLinkContentBlock = Schema.Struct({\n type: Schema.Literal('resource_link'),\n uri: Schema.String,\n name: Schema.optional(Schema.String),\n mimeType: Schema.optional(Schema.String)\n})\n\nexport const ToolCallResult = Schema.Struct({\n content: Schema.optional(Schema.Array(GenericContentBlock)),\n isError: Schema.optional(Schema.Boolean),\n structuredContent: Schema.optional(Schema.Unknown)\n})\n\nexport type ToolCallResult = typeof ToolCallResult.Type\n\nexport const InitializeClientInfo = Schema.Struct({\n name: Schema.String,\n version: Schema.String\n})\n\nexport type InitializeClientInfo = typeof InitializeClientInfo.Type\n\nexport const InitializeParams = Schema.Struct({\n protocolVersion: Schema.String,\n capabilities: Schema.Record(Schema.String, Schema.Unknown),\n clientInfo: InitializeClientInfo\n})\n\nexport type InitializeParams = typeof InitializeParams.Type\n\nexport const InitializedNotification = Schema.Struct({\n jsonrpc: Schema.Literal('2.0'),\n method: Schema.Literal('notifications/initialized')\n})\n\nexport type InitializedNotification = typeof InitializedNotification.Type\n\nexport const ToolsCallParams = Schema.Struct({\n name: Schema.String,\n arguments: Schema.optional(Schema.Unknown)\n})\n\nexport type ToolsCallParams = typeof ToolsCallParams.Type\n\nexport const makeJsonRpcRequest = (input: {\n readonly id: string | number\n readonly method: string\n readonly params?: unknown\n}): JsonRpcRequest => {\n const id = input.id\n const method = input.method\n\n if (input.params !== undefined) {\n return JsonRpcRequest.make({\n jsonrpc: '2.0',\n id,\n method,\n params: input.params\n })\n }\n\n return JsonRpcRequest.make({\n jsonrpc: '2.0',\n id,\n method\n })\n}\n\nexport const makeInitializedNotification = (): JsonRpcNotification =>\n InitializedNotification.make({\n jsonrpc: '2.0',\n method: 'notifications/initialized'\n })\n\nexport const makeInitializeParams = (input: {\n readonly name: string\n readonly version: string\n}): InitializeParams =>\n InitializeParams.make({\n protocolVersion: legacyMcpProtocolVersion,\n capabilities: {},\n clientInfo: InitializeClientInfo.make({\n name: input.name,\n version: input.version\n })\n })\n\nexport const jsonRpcErrorToMcpError = (server: string, error: JsonRpcErrorObject) =>\n new McpError({\n server,\n message: `MCP JSON-RPC error ${error.code}: ${error.message}`,\n cause: 'protocol'\n })\n\n/** Tool exposure (`callableBy`/`discovery`/`loading`) for adapted MCP tools: one value for every\n * tool, or per listed tool.\n * Omitted: the agent defaults (`callableBy: 'all'`). `resolveTools` still rejects invalid\n * combinations (for example `discovery` without `callableBy: 'codemode'`).\n */\nexport type McpToolExposureResolver =\n | ToolExposure\n | ((tool: McpTool, serverName: string) => ToolExposure)\n\ntype McpToolDefFields = {\n name: string\n description: string\n parameters: ToolDef['parameters']\n outputSchema?: ToolDef['outputSchema']\n callableBy?: ToolDef['callableBy']\n discovery?: ToolDef['discovery']\n loading?: ToolDef['loading']\n}\n\n/** Adapts one listed MCP tool. A present `outputSchema` that is a plain JSON Schema object\n * passes through as declaration-only `ToolDef.outputSchema`; any other value is omitted.\n * `exposure` (host policy) sets `callableBy`/`discovery`/`loading`; without it none is set.\n */\nexport const mcpToolToToolDef = (input: {\n readonly serverName: string\n readonly tool: McpTool\n readonly exposure?: McpToolExposureResolver\n}) => {\n const fields: McpToolDefFields = {\n name: `${sanitizeMcpName(input.serverName)}_${sanitizeMcpName(input.tool.name)}`,\n description: input.tool.description ?? `MCP tool ${input.serverName}/${input.tool.name}`,\n parameters: input.tool.inputSchema ?? { type: 'object', additionalProperties: true }\n }\n\n const outputSchema = decodeToolJsonSchemaObject(input.tool.outputSchema)\n\n if (Option.isSome(outputSchema)) fields.outputSchema = outputSchema.value\n\n const exposure = Predicate.isFunction(input.exposure)\n ? input.exposure(input.tool, input.serverName)\n : input.exposure\n\n if (exposure?.callableBy !== undefined) fields.callableBy = exposure.callableBy\n\n if (exposure?.discovery !== undefined) fields.discovery = exposure.discovery\n\n if (exposure?.loading !== undefined) fields.loading = exposure.loading\n\n return ToolDef.make(fields)\n}\n\nexport const sanitizeMcpName = (name: string) => {\n const sanitized = name.replace(/[^a-zA-Z0-9_-]/g, '_')\n\n return sanitized.length === 0 ? 'mcp' : sanitized\n}\n\nconst stringProperty = (block: GenericContentBlock, key: string) =>\n Schema.decodeUnknownOption(Schema.String)(block[key])\n\nconst contentBlockText = (block: GenericContentBlock): Option.Option<string> => {\n const type = block['type']\n const text = stringProperty(block, 'text')\n\n if (type === 'text') {\n return text\n }\n\n return Option.none()\n}\n\nconst fallbackTextForContentBlock = (block: GenericContentBlock) => {\n const type = stringProperty(block, 'type').pipe(Option.getOrElse(() => 'unknown'))\n const name = stringProperty(block, 'name')\n const uri = stringProperty(block, 'uri')\n const url = stringProperty(block, 'url')\n const label = Option.getOrElse(Option.firstSomeOf([name, uri, url]), () => type)\n\n switch (type) {\n case 'resource':\n return `MCP resource: ${label}`\n case 'resource_link':\n return `MCP resource link: ${label}`\n case 'image':\n return `MCP image: ${label}`\n case 'audio':\n return `MCP audio: ${label}`\n default:\n return `Unsupported MCP ${type} content.`\n }\n}\n\nconst resourceFilename = (uri: string) => {\n const segments = (uri.split(/[?#]/u, 1)[0] ?? '').split('/').filter(part => part.length > 0)\n const segment = segments[segments.length - 1]\n\n if (segment === undefined || segment.endsWith(':')) return undefined\n\n try {\n return decodeURIComponent(segment)\n } catch {\n return segment\n }\n}\n\n// Embedded text stays text; a blob becomes a file part that tool resolution captures (ADR 0009),\n// so its base64 never reaches the model.\nconst embeddedResourcePart = (block: GenericContentBlock): Option.Option<ContentPart> =>\n Schema.decodeUnknownOption(EmbeddedResourceContentBlock)(block).pipe(\n Option.flatMap(({ resource }): Option.Option<ContentPart> => {\n if (resource.text !== undefined) return Option.some(TextPart.make({ text: resource.text }))\n\n if (resource.blob === undefined) return Option.none()\n\n const mimeType = resource.mimeType ?? 'application/octet-stream'\n const filename = resource.uri === undefined ? undefined : resourceFilename(resource.uri)\n\n return Option.some(\n filename === undefined\n ? FilePart.make({ source: inlineBase64Source(resource.blob), mimeType })\n : FilePart.make({ source: inlineBase64Source(resource.blob), mimeType, filename })\n )\n })\n )\n\nconst resourceLinkText = (block: GenericContentBlock): Option.Option<string> =>\n Schema.decodeUnknownOption(ResourceLinkContentBlock)(block).pipe(\n Option.map(({ name, uri }) => {\n const label = name ?? uri\n\n return `MCP resource link: ${label} (${uri})`\n })\n )\n\nconst imagePartFromBlock = (block: GenericContentBlock): Option.Option<ContentPart> =>\n Option.all({\n data: stringProperty(block, 'data'),\n mimeType: stringProperty(block, 'mimeType')\n }).pipe(\n Option.map(({ data, mimeType }) =>\n ImagePart.make({ source: inlineBase64Source(data), mimeType })\n )\n )\n\nconst audioPartFromBlock = (block: GenericContentBlock): Option.Option<ContentPart> =>\n Option.all({\n data: stringProperty(block, 'data'),\n mimeType: stringProperty(block, 'mimeType')\n }).pipe(\n Option.map(({ data, mimeType }) =>\n AudioPart.make({ source: inlineBase64Source(data), mimeType })\n )\n )\n\nconst contentPartFromBlock = (block: GenericContentBlock): ContentPart => {\n const type = block['type']\n\n if (type === 'text') {\n return TextPart.make({ text: Option.getOrElse(contentBlockText(block), () => '') })\n }\n\n if (type === 'image') {\n return Option.getOrElse(imagePartFromBlock(block), () =>\n TextPart.make({ text: fallbackTextForContentBlock(block) })\n )\n }\n\n if (type === 'audio') {\n return Option.getOrElse(audioPartFromBlock(block), () =>\n TextPart.make({ text: fallbackTextForContentBlock(block) })\n )\n }\n\n if (type === 'resource') {\n return Option.getOrElse(embeddedResourcePart(block), () =>\n TextPart.make({ text: fallbackTextForContentBlock(block) })\n )\n }\n\n if (type === 'resource_link') {\n return TextPart.make({\n text: resourceLinkText(block).pipe(Option.getOrElse(() => fallbackTextForContentBlock(block)))\n })\n }\n\n return TextPart.make({ text: fallbackTextForContentBlock(block) })\n}\n\nconst contentFromBlocks = (blocks: ReadonlyArray<GenericContentBlock>): Content => {\n const textBlocks = Arr.getSomes(Arr.map(blocks, contentBlockText))\n\n if (textBlocks.length === blocks.length) {\n return textBlocks.join('\\n')\n }\n\n return Arr.map(blocks, contentPartFromBlock)\n}\n\nexport const toolCallResultToToolResult = (input: {\n readonly toolCallId: string\n readonly result: ToolCallResult\n}) => {\n const content = input.result.content ?? []\n\n const resultContent =\n content.length > 0\n ? contentFromBlocks(content)\n : input.result.structuredContent === undefined\n ? 'Unsupported MCP tool content.'\n : 'Structured MCP tool result.'\n\n return ToolResult.make({\n toolCallId: input.toolCallId,\n content: resultContent,\n isError: input.result.isError,\n structuredContent: input.result.structuredContent\n })\n}\n\nexport const decodeJsonRpcResponse = Schema.decodeUnknownEffect(JsonRpcResponse)\n\nexport const decodeToolsListResult = Schema.decodeUnknownEffect(ToolsListResult)\n\nexport const decodeToolCallResult = Schema.decodeUnknownEffect(ToolCallResult)\n\nexport const encodeJsonRpcMessage = (\n server: string,\n message: JsonRpcRequest | JsonRpcNotification\n) =>\n Schema.encodeUnknownEffect(Schema.fromJsonString(Schema.Unknown))(message).pipe(\n Effect.mapError(\n error =>\n new McpError({\n server,\n message: `Could not encode MCP JSON-RPC message: ${String(error)}`,\n cause: 'encoding'\n })\n )\n )\n\nconst decodeJsonString = (server: string, text: string) =>\n Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Unknown))(text).pipe(\n Effect.mapError(\n error =>\n new McpError({\n server,\n message: `Malformed MCP JSON: ${String(error)}`,\n cause: 'parse'\n })\n )\n )\n\nexport const decodeJsonRpcResponseFromJson = (server: string, text: string) =>\n decodeJsonString(server, text).pipe(\n Effect.flatMap(decodeJsonRpcResponse),\n Effect.mapError(error =>\n error instanceof McpError\n ? error\n : new McpError({\n server,\n message: `Invalid MCP JSON-RPC response: ${String(error)}`,\n cause: 'validation'\n })\n )\n )\n\nexport const decodeJsonRpcMessageFromJson = (server: string, text: string) =>\n decodeJsonString(server, text).pipe(\n Effect.flatMap(Schema.decodeUnknownEffect(JsonRpcMessage)),\n Effect.mapError(error =>\n error instanceof McpError\n ? error\n : new McpError({\n server,\n message: `Invalid MCP JSON-RPC message: ${String(error)}`,\n cause: 'validation'\n })\n )\n )\n"],"mappings":";;;;;AAgBA,MAAa,2BAA2B;AAExC,MAAa,2BAA2B;AAExC,MAAa,qBAAqB,OAAO,OAAO;CAC9C,MAAM,OAAO;CACb,SAAS,OAAO;CAChB,MAAM,OAAO,SAAS,OAAO,OAAO;AACtC,CAAC;AAID,MAAa,yBAAyB,OAAO,OAAO;CAClD,SAAS,OAAO,QAAQ,KAAK;CAC7B,IAAI,OAAO,MAAM;EAAC,OAAO;EAAQ,OAAO;EAAQ,OAAO;CAAI,CAAC;CAC5D,QAAQ,OAAO;AACjB,CAAC;AAID,MAAa,uBAAuB,OAAO,OAAO;CAChD,SAAS,OAAO,QAAQ,KAAK;CAC7B,IAAI,OAAO,MAAM;EAAC,OAAO;EAAQ,OAAO;EAAQ,OAAO;CAAI,CAAC;CAC5D,OAAO;AACT,CAAC;AAID,MAAa,kBAAkB,OAAO,MAAM,CAAC,wBAAwB,oBAAoB,CAAC;AAI1F,MAAa,iBAAiB,OAAO,OAAO;CAC1C,SAAS,OAAO,QAAQ,KAAK;CAC7B,IAAI,OAAO,MAAM,CAAC,OAAO,QAAQ,OAAO,MAAM,CAAC;CAC/C,QAAQ,OAAO;CACf,QAAQ,OAAO,SAAS,OAAO,OAAO;AACxC,CAAC;AAID,MAAa,sBAAsB,OAAO,OAAO;CAC/C,SAAS,OAAO,QAAQ,KAAK;CAC7B,QAAQ,OAAO;CACf,QAAQ,OAAO,SAAS,OAAO,OAAO;AACxC,CAAC;AAID,MAAa,iBAAiB,OAAO,MAAM,CAAC,gBAAgB,mBAAmB,CAAC;AAIhF,MAAa,qBAAqB,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO;AAI7E,MAAa,UAAU,OAAO,OAAO;CACnC,MAAM,OAAO;CACb,OAAO,OAAO,SAAS,OAAO,MAAM;CACpC,aAAa,OAAO,SAAS,OAAO,MAAM;CAC1C,aAAa,OAAO,SAAS,oBAAoB;CACjD,cAAc,OAAO,SAAS,OAAO,OAAO;CAC5C,aAAa,OAAO,SAAS,kBAAkB;AACjD,CAAC;AAID,MAAa,kBAAkB,OAAO,OAAO,EAC3C,OAAO,OAAO,MAAM,OAAO,EAC7B,CAAC;AAID,MAAa,mBAAmB,OAAO,OAAO;CAC5C,MAAM,OAAO,QAAQ,MAAM;CAC3B,MAAM,OAAO;AACf,CAAC;AAID,MAAa,sBAAsB,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO;AAI9E,MAAM,+BAA+B,OAAO,OAAO;CACjD,MAAM,OAAO,QAAQ,UAAU;CAC/B,UAAU,OAAO,OAAO;EACtB,KAAK,OAAO,SAAS,OAAO,MAAM;EAClC,MAAM,OAAO,SAAS,OAAO,MAAM;EACnC,MAAM,OAAO,SAAS,OAAO,MAAM;EACnC,UAAU,OAAO,SAAS,OAAO,MAAM;CACzC,CAAC;AACH,CAAC;AAED,MAAM,2BAA2B,OAAO,OAAO;CAC7C,MAAM,OAAO,QAAQ,eAAe;CACpC,KAAK,OAAO;CACZ,MAAM,OAAO,SAAS,OAAO,MAAM;CACnC,UAAU,OAAO,SAAS,OAAO,MAAM;AACzC,CAAC;AAED,MAAa,iBAAiB,OAAO,OAAO;CAC1C,SAAS,OAAO,SAAS,OAAO,MAAM,mBAAmB,CAAC;CAC1D,SAAS,OAAO,SAAS,OAAO,OAAO;CACvC,mBAAmB,OAAO,SAAS,OAAO,OAAO;AACnD,CAAC;AAID,MAAa,uBAAuB,OAAO,OAAO;CAChD,MAAM,OAAO;CACb,SAAS,OAAO;AAClB,CAAC;AAID,MAAa,mBAAmB,OAAO,OAAO;CAC5C,iBAAiB,OAAO;CACxB,cAAc,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO;CACzD,YAAY;AACd,CAAC;AAID,MAAa,0BAA0B,OAAO,OAAO;CACnD,SAAS,OAAO,QAAQ,KAAK;CAC7B,QAAQ,OAAO,QAAQ,2BAA2B;AACpD,CAAC;AAID,MAAa,kBAAkB,OAAO,OAAO;CAC3C,MAAM,OAAO;CACb,WAAW,OAAO,SAAS,OAAO,OAAO;AAC3C,CAAC;AAID,MAAa,sBAAsB,UAIb;CACpB,MAAM,KAAK,MAAM;CACjB,MAAM,SAAS,MAAM;CAErB,IAAI,MAAM,WAAW,KAAA,GACnB,OAAO,eAAe,KAAK;EACzB,SAAS;EACT;EACA;EACA,QAAQ,MAAM;CAChB,CAAC;CAGH,OAAO,eAAe,KAAK;EACzB,SAAS;EACT;EACA;CACF,CAAC;AACH;AAEA,MAAa,oCACX,wBAAwB,KAAK;CAC3B,SAAS;CACT,QAAQ;AACV,CAAC;AAEH,MAAa,wBAAwB,UAInC,iBAAiB,KAAK;CACpB,iBAAiB;CACjB,cAAc,CAAC;CACf,YAAY,qBAAqB,KAAK;EACpC,MAAM,MAAM;EACZ,SAAS,MAAM;CACjB,CAAC;AACH,CAAC;AAEH,MAAa,0BAA0B,QAAgB,UACrD,IAAI,SAAS;CACX;CACA,SAAS,sBAAsB,MAAM,KAAK,IAAI,MAAM;CACpD,OAAO;AACT,CAAC;;;;;AAyBH,MAAa,oBAAoB,UAI3B;CACJ,MAAM,SAA2B;EAC/B,MAAM,GAAG,gBAAgB,MAAM,UAAU,EAAE,GAAG,gBAAgB,MAAM,KAAK,IAAI;EAC7E,aAAa,MAAM,KAAK,eAAe,YAAY,MAAM,WAAW,GAAG,MAAM,KAAK;EAClF,YAAY,MAAM,KAAK,eAAe;GAAE,MAAM;GAAU,sBAAsB;EAAK;CACrF;CAEA,MAAM,eAAe,2BAA2B,MAAM,KAAK,YAAY;CAEvE,IAAI,OAAO,OAAO,YAAY,GAAG,OAAO,eAAe,aAAa;CAEpE,MAAM,WAAW,UAAU,WAAW,MAAM,QAAQ,IAChD,MAAM,SAAS,MAAM,MAAM,MAAM,UAAU,IAC3C,MAAM;CAEV,IAAI,UAAU,eAAe,KAAA,GAAW,OAAO,aAAa,SAAS;CAErE,IAAI,UAAU,cAAc,KAAA,GAAW,OAAO,YAAY,SAAS;CAEnE,IAAI,UAAU,YAAY,KAAA,GAAW,OAAO,UAAU,SAAS;CAE/D,OAAO,QAAQ,KAAK,MAAM;AAC5B;AAEA,MAAa,mBAAmB,SAAiB;CAC/C,MAAM,YAAY,KAAK,QAAQ,mBAAmB,GAAG;CAErD,OAAO,UAAU,WAAW,IAAI,QAAQ;AAC1C;AAEA,MAAM,kBAAkB,OAA4B,QAClD,OAAO,oBAAoB,OAAO,MAAM,EAAE,MAAM,IAAI;AAEtD,MAAM,oBAAoB,UAAsD;CAC9E,MAAM,OAAO,MAAM;CACnB,MAAM,OAAO,eAAe,OAAO,MAAM;CAEzC,IAAI,SAAS,QACX,OAAO;CAGT,OAAO,OAAO,KAAK;AACrB;AAEA,MAAM,+BAA+B,UAA+B;CAClE,MAAM,OAAO,eAAe,OAAO,MAAM,EAAE,KAAK,OAAO,gBAAgB,SAAS,CAAC;CACjF,MAAM,OAAO,eAAe,OAAO,MAAM;CACzC,MAAM,MAAM,eAAe,OAAO,KAAK;CACvC,MAAM,MAAM,eAAe,OAAO,KAAK;CACvC,MAAM,QAAQ,OAAO,UAAU,OAAO,YAAY;EAAC;EAAM;EAAK;CAAG,CAAC,SAAS,IAAI;CAE/E,QAAQ,MAAR;EACE,KAAK,YACH,OAAO,iBAAiB;EAC1B,KAAK,iBACH,OAAO,sBAAsB;EAC/B,KAAK,SACH,OAAO,cAAc;EACvB,KAAK,SACH,OAAO,cAAc;EACvB,SACE,OAAO,mBAAmB,KAAK;CACnC;AACF;AAEA,MAAM,oBAAoB,QAAgB;CACxC,MAAM,YAAY,IAAI,MAAM,SAAS,CAAC,EAAE,MAAM,IAAI,MAAM,GAAG,EAAE,QAAO,SAAQ,KAAK,SAAS,CAAC;CAC3F,MAAM,UAAU,SAAS,SAAS,SAAS;CAE3C,IAAI,YAAY,KAAA,KAAa,QAAQ,SAAS,GAAG,GAAG,OAAO,KAAA;CAE3D,IAAI;EACF,OAAO,mBAAmB,OAAO;CACnC,QAAQ;EACN,OAAO;CACT;AACF;AAIA,MAAM,wBAAwB,UAC5B,OAAO,oBAAoB,4BAA4B,EAAE,KAAK,EAAE,KAC9D,OAAO,SAAS,EAAE,eAA2C;CAC3D,IAAI,SAAS,SAAS,KAAA,GAAW,OAAO,OAAO,KAAK,SAAS,KAAK,EAAE,MAAM,SAAS,KAAK,CAAC,CAAC;CAE1F,IAAI,SAAS,SAAS,KAAA,GAAW,OAAO,OAAO,KAAK;CAEpD,MAAM,WAAW,SAAS,YAAY;CACtC,MAAM,WAAW,SAAS,QAAQ,KAAA,IAAY,KAAA,IAAY,iBAAiB,SAAS,GAAG;CAEvF,OAAO,OAAO,KACZ,aAAa,KAAA,IACT,SAAS,KAAK;EAAE,QAAQ,mBAAmB,SAAS,IAAI;EAAG;CAAS,CAAC,IACrE,SAAS,KAAK;EAAE,QAAQ,mBAAmB,SAAS,IAAI;EAAG;EAAU;CAAS,CAAC,CACrF;AACF,CAAC,CACH;AAEF,MAAM,oBAAoB,UACxB,OAAO,oBAAoB,wBAAwB,EAAE,KAAK,EAAE,KAC1D,OAAO,KAAK,EAAE,MAAM,UAAU;CAG5B,OAAO,sBAFO,QAAQ,IAEa,IAAI,IAAI;AAC7C,CAAC,CACH;AAEF,MAAM,sBAAsB,UAC1B,OAAO,IAAI;CACT,MAAM,eAAe,OAAO,MAAM;CAClC,UAAU,eAAe,OAAO,UAAU;AAC5C,CAAC,EAAE,KACD,OAAO,KAAK,EAAE,MAAM,eAClB,UAAU,KAAK;CAAE,QAAQ,mBAAmB,IAAI;CAAG;AAAS,CAAC,CAC/D,CACF;AAEF,MAAM,sBAAsB,UAC1B,OAAO,IAAI;CACT,MAAM,eAAe,OAAO,MAAM;CAClC,UAAU,eAAe,OAAO,UAAU;AAC5C,CAAC,EAAE,KACD,OAAO,KAAK,EAAE,MAAM,eAClB,UAAU,KAAK;CAAE,QAAQ,mBAAmB,IAAI;CAAG;AAAS,CAAC,CAC/D,CACF;AAEF,MAAM,wBAAwB,UAA4C;CACxE,MAAM,OAAO,MAAM;CAEnB,IAAI,SAAS,QACX,OAAO,SAAS,KAAK,EAAE,MAAM,OAAO,UAAU,iBAAiB,KAAK,SAAS,EAAE,EAAE,CAAC;CAGpF,IAAI,SAAS,SACX,OAAO,OAAO,UAAU,mBAAmB,KAAK,SAC9C,SAAS,KAAK,EAAE,MAAM,4BAA4B,KAAK,EAAE,CAAC,CAC5D;CAGF,IAAI,SAAS,SACX,OAAO,OAAO,UAAU,mBAAmB,KAAK,SAC9C,SAAS,KAAK,EAAE,MAAM,4BAA4B,KAAK,EAAE,CAAC,CAC5D;CAGF,IAAI,SAAS,YACX,OAAO,OAAO,UAAU,qBAAqB,KAAK,SAChD,SAAS,KAAK,EAAE,MAAM,4BAA4B,KAAK,EAAE,CAAC,CAC5D;CAGF,IAAI,SAAS,iBACX,OAAO,SAAS,KAAK,EACnB,MAAM,iBAAiB,KAAK,EAAE,KAAK,OAAO,gBAAgB,4BAA4B,KAAK,CAAC,CAAC,EAC/F,CAAC;CAGH,OAAO,SAAS,KAAK,EAAE,MAAM,4BAA4B,KAAK,EAAE,CAAC;AACnE;AAEA,MAAM,qBAAqB,WAAwD;CACjF,MAAM,aAAaA,MAAI,SAASA,MAAI,IAAI,QAAQ,gBAAgB,CAAC;CAEjE,IAAI,WAAW,WAAW,OAAO,QAC/B,OAAO,WAAW,KAAK,IAAI;CAG7B,OAAOA,MAAI,IAAI,QAAQ,oBAAoB;AAC7C;AAEA,MAAa,8BAA8B,UAGrC;CACJ,MAAM,UAAU,MAAM,OAAO,WAAW,CAAC;CAEzC,MAAM,gBACJ,QAAQ,SAAS,IACb,kBAAkB,OAAO,IACzB,MAAM,OAAO,sBAAsB,KAAA,IACjC,kCACA;CAER,OAAO,WAAW,KAAK;EACrB,YAAY,MAAM;EAClB,SAAS;EACT,SAAS,MAAM,OAAO;EACtB,mBAAmB,MAAM,OAAO;CAClC,CAAC;AACH;AAEA,MAAa,wBAAwB,OAAO,oBAAoB,eAAe;AAE/E,MAAa,wBAAwB,OAAO,oBAAoB,eAAe;AAE/E,MAAa,uBAAuB,OAAO,oBAAoB,cAAc;AAE7E,MAAa,wBACX,QACA,YAEA,OAAO,oBAAoB,OAAO,eAAe,OAAO,OAAO,CAAC,EAAE,OAAO,EAAE,KACzE,OAAO,UACL,UACE,IAAI,SAAS;CACX;CACA,SAAS,0CAA0C,OAAO,KAAK;CAC/D,OAAO;AACT,CAAC,CACL,CACF;AAEF,MAAM,oBAAoB,QAAgB,SACxC,OAAO,oBAAoB,OAAO,eAAe,OAAO,OAAO,CAAC,EAAE,IAAI,EAAE,KACtE,OAAO,UACL,UACE,IAAI,SAAS;CACX;CACA,SAAS,uBAAuB,OAAO,KAAK;CAC5C,OAAO;AACT,CAAC,CACL,CACF;AAEF,MAAa,iCAAiC,QAAgB,SAC5D,iBAAiB,QAAQ,IAAI,EAAE,KAC7B,OAAO,QAAQ,qBAAqB,GACpC,OAAO,UAAS,UACd,iBAAiB,WACb,QACA,IAAI,SAAS;CACX;CACA,SAAS,kCAAkC,OAAO,KAAK;CACvD,OAAO;AACT,CAAC,CACP,CACF;AAEF,MAAa,gCAAgC,QAAgB,SAC3D,iBAAiB,QAAQ,IAAI,EAAE,KAC7B,OAAO,QAAQ,OAAO,oBAAoB,cAAc,CAAC,GACzD,OAAO,UAAS,UACd,iBAAiB,WACb,QACA,IAAI,SAAS;CACX;CACA,SAAS,iCAAiC,OAAO,KAAK;CACtD,OAAO;AACT,CAAC,CACP,CACF"}
@@ -1,11 +1,11 @@
1
1
  import { latestMcpProtocolVersion } from "../client/protocol.mjs";
2
- import { callRemoteMcpServerTool, listRemoteMcpServerTools } from "../client/client.mjs";
3
2
  import { encodeMcpParamValue } from "./param-value.mjs";
4
3
  import { mcpAuthRejectedLegacyFixture, mcpAuthRejectedModernFixture } from "./auth-rejected.mjs";
5
4
  import { parseWireJson } from "./json.mjs";
6
5
  import { sseMessagePayloads } from "./sse.mjs";
7
6
  import { mcpCallReadLegacyFixture, mcpCallReadModernFixture } from "./call-read.mjs";
8
7
  import { mcpCallToolErrorLegacyFixture, mcpCallToolErrorModernFixture } from "./call-tool-error.mjs";
8
+ import { callRemoteMcpServerTool, listRemoteMcpServerTools } from "../client/client.mjs";
9
9
  import { mcpElicitationDeclarationLegacyFixture, mcpElicitationDeclarationModernFixture } from "./elicitation-declaration.mjs";
10
10
  import { mcpLegacySessionFixture } from "./legacy-session.mjs";
11
11
  import { McpConformanceConfig, McpConformanceTarget, mcpConformanceDefaultInvalidCredentialHeaders } from "./target.mjs";
@@ -17,9 +17,9 @@ import { mcpToolsListLegacyFixture, mcpToolsListModernFixture } from "./tools-li
17
17
  import { mcpUnknownToolLegacyFixture, mcpUnknownToolModernFixture } from "./unknown-tool.mjs";
18
18
  import { DiscoverResultSchema } from "@modelcontextprotocol/core";
19
19
  import { Cause, Effect, Equal, Exit, Option, Predicate } from "effect";
20
- import { SUPPORTED_PROTOCOL_VERSIONS } from "@modelcontextprotocol/client";
21
20
  import { HttpClient } from "effect/http";
22
21
  import { ConformanceMismatch, defineConformanceCase, expectConformance, expectEqual } from "@yolk-sdk/conformance/case";
22
+ import { SUPPORTED_PROTOCOL_VERSIONS } from "@modelcontextprotocol/client";
23
23
  //#region src/conformance/cases.ts
24
24
  /**
25
25
  * MCP conformance cases for `@yolk-sdk/conformance/runner`.
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.mts","names":[],"sources":["../../src/server/server.ts"],"mappings":";;;;;KAkPY,aAAA;EAAA,SACD,GAAA,EAAK,OAAA;EAAA,SACL,OAAA,GAAU,IAAA,EAAM,QAAA,KAAa,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,cAAA,EAAgB,CAAA;AAAA;AAAA,KAGtE,aAAA;EAAA,SACD,UAAA,GAAa,IAAA,aAAiB,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,MAAA,UAAgB,cAAA,EAAgB,CAAA;EAAA,SACnF,UAAA,GAAa,IAAA,aAAiB,MAAA,CAAO,MAAA,SAAe,cAAA,EAAgB,CAAA;EAAA,SACpE,iBAAA,GAAoB,OAAA,EAAS,OAAA,KAAY,MAAA,CAAO,MAAA,CAAO,QAAA,SAAiB,CAAA;AAAA;AAAA,cA0BtE,iBAAA,MAAwB,KAAA;EAAA,SAC1B,IAAA;EAAA,SACA,OAAA;EAAA,SACA,KAAA,EAAO,aAAA,CAAc,aAAA,CAAc,CAAA;EAAA,SACnC,sBAAA,GAAyB,aAAA;AAAA,MAChC,aAAA,CAAc,CAAA"}
1
+ {"version":3,"file":"server.d.mts","names":[],"sources":["../../src/server/server.ts"],"mappings":";;;;;KAiQY,aAAA;EAAA,SACD,GAAA,EAAK,OAAA;EAAA,SACL,OAAA,GAAU,IAAA,EAAM,QAAA,KAAa,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,cAAA,EAAgB,CAAA;AAAA;AAAA,KAGtE,aAAA;EAAA,SACD,UAAA,GAAa,IAAA,aAAiB,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,MAAA,UAAgB,cAAA,EAAgB,CAAA;EAAA,SACnF,UAAA,GAAa,IAAA,aAAiB,MAAA,CAAO,MAAA,SAAe,cAAA,EAAgB,CAAA;EAAA,SACpE,iBAAA,GAAoB,OAAA,EAAS,OAAA,KAAY,MAAA,CAAO,MAAA,CAAO,QAAA,SAAiB,CAAA;AAAA;AAAA,cA0BtE,iBAAA,MAAwB,KAAA;EAAA,SAC1B,IAAA;EAAA,SACA,OAAA;EAAA,SACA,KAAA,EAAO,aAAA,CAAc,aAAA,CAAc,CAAA;EAAA,SACnC,sBAAA,GAAyB,aAAA;AAAA,MAChC,aAAA,CAAc,CAAA"}
@@ -1,7 +1,7 @@
1
1
  import { McpServerError } from "./errors.mjs";
2
2
  import { Array as Array$1, Effect, Match, Option, Predicate, Result } from "effect";
3
3
  import * as Schema from "effect/Schema";
4
- import { ToolCall, ToolResult, attachmentSourceBase64, attachmentSourcePreview, contentParts } from "@yolk-sdk/agent/protocol";
4
+ import { ToolCall, ToolResult, attachmentSourceBase64, attachmentSourcePreview, contentParts, filePartText } from "@yolk-sdk/agent/protocol";
5
5
  import { McpServer, createMcpHandler, fromJsonSchema, originValidationResponse } from "@modelcontextprotocol/server";
6
6
  import { legacyMcpProtocolVersion } from "@yolk-sdk/mcp/client";
7
7
  //#region src/server/server.ts
@@ -108,6 +108,19 @@ const mcpContentBlockFromPart = (part) => Match.value(part).pipe(Match.withRetur
108
108
  data,
109
109
  mimeType: current.mimeType
110
110
  })
111
+ })), Match.tag("File", (current) => Option.match(attachmentSourceBase64(current.source), {
112
+ onNone: () => ({
113
+ type: "text",
114
+ text: filePartText(current)
115
+ }),
116
+ onSome: (data) => ({
117
+ type: "resource",
118
+ resource: {
119
+ uri: documentResourceUri(current.filename ?? "file"),
120
+ mimeType: current.mimeType,
121
+ blob: data
122
+ }
123
+ })
111
124
  })), Match.exhaustive);
112
125
  const mcpResultFromToolResult = (result) => {
113
126
  const content = Array$1.map(contentParts(result.content), mcpContentBlockFromPart);
@@ -1 +1 @@
1
- {"version":3,"file":"server.mjs","names":["Arr","SdkMcpServer"],"sources":["../../src/server/server.ts"],"sourcesContent":["import { Array as Arr, Effect, Match, Option, Predicate, Result } from 'effect'\nimport type { Context } from 'effect'\nimport * as Schema from 'effect/Schema'\nimport {\n McpServer as SdkMcpServer,\n createMcpHandler,\n fromJsonSchema,\n originValidationResponse,\n type CallToolResult as SdkCallToolResult,\n type ContentBlock as SdkContentBlock\n} from '@modelcontextprotocol/server'\nimport {\n ToolCall,\n ToolResult,\n attachmentSourceBase64,\n attachmentSourcePreview,\n contentParts,\n type ContentPart,\n type ToolDef\n} from '@yolk-sdk/agent/protocol'\nimport { legacyMcpProtocolVersion } from '@yolk-sdk/mcp/client'\nimport { McpServerError } from './errors.ts'\n\ntype JsonRpcRequest = {\n readonly jsonrpc: '2.0'\n readonly id: string | number\n readonly method: string\n readonly params?: unknown\n}\n\ntype JsonRpcNotification = {\n readonly jsonrpc: '2.0'\n readonly method: string\n readonly params?: unknown\n}\n\ntype JsonRpcResponse = {\n readonly jsonrpc: '2.0'\n readonly id: string | number | null\n readonly result?: unknown\n readonly error?: {\n readonly code: number\n readonly message: string\n }\n}\n\nconst JsonRpcRequestSchema = Schema.Struct({\n jsonrpc: Schema.Literal('2.0'),\n id: Schema.Union([Schema.String, Schema.Number]),\n method: Schema.String,\n params: Schema.optional(Schema.Unknown)\n})\n\nconst JsonRpcNotificationSchema = Schema.Struct({\n jsonrpc: Schema.Literal('2.0'),\n method: Schema.String,\n params: Schema.optional(Schema.Unknown)\n})\n\nconst CallToolParamsSchema = Schema.Struct({\n name: Schema.String,\n arguments: Schema.optional(Schema.Unknown)\n})\n\nconst JsonRpcMessageSchema = Schema.Union([JsonRpcRequestSchema, JsonRpcNotificationSchema])\n\ntype JsonRpcMessage = typeof JsonRpcMessageSchema.Type\n\nconst DecodedMessageLine = Schema.TaggedStruct('Message', {\n message: Schema.Unknown\n})\n\nconst DecodedResponseLine = Schema.TaggedStruct('Response', {\n response: Schema.Unknown\n})\n\ntype DecodedLine =\n | {\n readonly _tag: 'Message'\n readonly message: JsonRpcMessage\n }\n | {\n readonly _tag: 'Response'\n readonly response: Option.Option<string>\n }\n\nconst decodedMessage = (message: JsonRpcMessage): DecodedLine => ({\n ...DecodedMessageLine.make({ message }),\n message\n})\n\nconst decodedResponse = (response: Option.Option<string>): DecodedLine => ({\n ...DecodedResponseLine.make({ response }),\n response\n})\n\nconst decodeJson = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Unknown))\n\nconst decodeJsonRpcMessage = Schema.decodeUnknownEffect(JsonRpcMessageSchema)\n\nconst decodeCallToolParams = Schema.decodeUnknownEffect(CallToolParamsSchema)\n\nconst encodeJson = (value: JsonRpcResponse) =>\n Schema.encodeUnknownEffect(Schema.fromJsonString(Schema.Unknown))(value).pipe(\n Effect.mapError(\n error =>\n new McpServerError({\n message: `Could not encode MCP response: ${String(error)}`,\n cause: 'encoding'\n })\n )\n )\n\nconst decodeMessage = (line: string) =>\n decodeJson(line).pipe(\n Effect.mapError(\n error =>\n new McpServerError({\n message: `Malformed MCP JSON: ${String(error)}`,\n cause: 'parse'\n })\n ),\n Effect.flatMap(value =>\n decodeJsonRpcMessage(value).pipe(\n Effect.mapError(\n error =>\n new McpServerError({\n message: `Invalid MCP JSON-RPC message: ${String(error)}`,\n cause: 'validation'\n })\n )\n )\n )\n )\n\nconst successResponse = (id: string | number, result: unknown): JsonRpcResponse => ({\n jsonrpc: '2.0',\n id,\n result\n})\n\nconst errorResponse = (\n id: string | number | null,\n code: number,\n message: string\n): JsonRpcResponse => ({\n jsonrpc: '2.0',\n id,\n error: { code, message }\n})\n\nconst unknownToMessage = (error: unknown) =>\n error instanceof Error ? error.message : String(error)\n\nconst isRequest = (message: JsonRpcRequest | JsonRpcNotification): message is JsonRpcRequest =>\n 'id' in message\n\nconst protocolErrorCode = (error: McpServerError) => {\n switch (error.cause) {\n case 'parse':\n return -32_700\n case 'validation':\n return -32_600\n case 'protocol':\n return -32_603\n case 'tool_error':\n case 'encoding':\n return -32_000\n }\n}\n\nconst protocolErrorResponse = (id: string | number | null, error: McpServerError) =>\n errorResponse(id, protocolErrorCode(error), error.message)\n\nconst documentResourceUri = (filename: string) => `file:///${encodeURIComponent(filename)}`\n\nconst mcpContentBlockFromPart = (part: ContentPart): SdkContentBlock =>\n Match.value(part).pipe(\n Match.withReturnType<SdkContentBlock>(),\n Match.tag('Text', current => ({ type: 'text', text: current.text })),\n Match.tag('Image', current =>\n Option.match(attachmentSourceBase64(current.source), {\n onNone: () => ({\n type: 'text',\n text: `Image attachment: ${attachmentSourcePreview(current.source)}`\n }),\n onSome: data => ({ type: 'image', data, mimeType: current.mimeType })\n })\n ),\n Match.tag('Document', current =>\n Option.match(attachmentSourceBase64(current.source), {\n onNone: () => ({\n type: 'text',\n text: `Document attachment: ${attachmentSourcePreview(current.source)}`\n }),\n onSome: data => ({\n type: 'resource',\n resource: {\n uri: documentResourceUri(current.filename),\n name: current.title ?? current.filename,\n mimeType: current.mimeType,\n blob: data\n }\n })\n })\n ),\n Match.tag('Audio', current =>\n Option.match(attachmentSourceBase64(current.source), {\n onNone: () => ({\n type: 'text',\n text: `Audio attachment: ${attachmentSourcePreview(current.source)}`\n }),\n onSome: data => ({ type: 'audio', data, mimeType: current.mimeType })\n })\n ),\n Match.exhaustive\n )\n\nconst mcpResultFromToolResult = (result: ToolResult): SdkCallToolResult => {\n const content = Arr.map(contentParts(result.content), mcpContentBlockFromPart)\n const base = result.isError === undefined ? { content } : { content, isError: result.isError }\n\n return result.structuredContent === undefined\n ? base\n : { ...base, structuredContent: result.structuredContent }\n}\n\nconst mcpErrorResult = (message: string): SdkCallToolResult => ({\n content: [{ type: 'text', text: message }],\n isError: true\n})\n\nconst mcpResultFromExecutionResult = (\n result: ToolResult | ReturnType<typeof mcpErrorResult>\n): SdkCallToolResult => (result instanceof ToolResult ? mcpResultFromToolResult(result) : result)\n\nconst toolListItem = (tool: ToolDef) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.parameters\n})\n\nexport type McpServerTool<R = never> = {\n readonly def: ToolDef\n readonly execute: (call: ToolCall) => Effect.Effect<ToolResult, McpServerError, R>\n}\n\nexport type McpToolServer<R = never> = {\n readonly handleLine: (line: string) => Effect.Effect<Option.Option<string>, McpServerError, R>\n readonly handleJson: (body: string) => Effect.Effect<string, McpServerError, R>\n readonly handleHttpRequest: (request: Request) => Effect.Effect<Response, never, R>\n}\n\nconst jsonResponse = (body: string, init?: ResponseInit) =>\n new Response(body, {\n ...init,\n headers: {\n 'content-type': 'application/json',\n ...(init?.headers ?? {})\n }\n })\n\nconst methodNotAllowedBody = () =>\n encodeJson(errorResponse(null, -32_600, 'Method not allowed')).pipe(\n Effect.orElseSucceed(\n () => '{\"jsonrpc\":\"2.0\",\"id\":null,\"error\":{\"code\":-32600,\"message\":\"Method not allowed\"}}'\n )\n )\n\nconst badRequestBody = (message: string) =>\n encodeJson(errorResponse(null, -32_600, message)).pipe(\n Effect.orElseSucceed(\n () => '{\"jsonrpc\":\"2.0\",\"id\":null,\"error\":{\"code\":-32600,\"message\":\"Bad request\"}}'\n )\n )\n\nexport const makeMcpToolServer = <R>(input: {\n readonly name: string\n readonly version: string\n readonly tools: ReadonlyArray<McpServerTool<R>>\n readonly allowedOriginHostnames?: ReadonlyArray<string>\n}): McpToolServer<R> => {\n const findTool = (name: string) => Arr.findFirst(input.tools, tool => tool.def.name === name)\n\n const toolInputSchemas = input.tools.map(tool => ({\n tool,\n schema: Schema.decodeUnknownOption(Schema.Record(Schema.String, Schema.Unknown))(\n tool.def.parameters\n ).pipe(Option.getOrElse(() => ({ type: 'object', additionalProperties: true })))\n }))\n\n const makeSdkServer = (context: Context.Context<R>) => {\n const server = new SdkMcpServer(\n { name: input.name, version: input.version },\n {\n cacheHints: {\n 'server/discover': { ttlMs: 0, cacheScope: 'private' },\n 'tools/list': { ttlMs: 0, cacheScope: 'private' }\n }\n }\n )\n\n for (const { schema, tool } of toolInputSchemas) {\n server.registerTool(\n tool.def.name,\n {\n description: tool.def.description,\n inputSchema: fromJsonSchema(schema)\n },\n async (args, sdkContext) => {\n const result = await Effect.runPromiseWith(context)(\n tool\n .execute(\n ToolCall.make({\n id: String(sdkContext.mcpReq.id),\n name: tool.def.name,\n params: args\n })\n )\n .pipe(\n Effect.catch(error =>\n Effect.succeed(mcpErrorResult(`MCP tool failed: ${error.message}`))\n )\n )\n )\n\n return mcpResultFromExecutionResult(result)\n }\n )\n }\n\n return server\n }\n\n const handleRequest = (request: JsonRpcRequest) =>\n Effect.gen(function* () {\n switch (request.method) {\n case 'initialize':\n return successResponse(request.id, {\n protocolVersion: legacyMcpProtocolVersion,\n capabilities: { tools: {} },\n serverInfo: { name: input.name, version: input.version }\n })\n case 'tools/list':\n return successResponse(request.id, {\n tools: input.tools.map(tool => toolListItem(tool.def))\n })\n case 'tools/call': {\n const params = yield* decodeCallToolParams(request.params).pipe(\n Effect.mapError(\n error =>\n new McpServerError({\n message: `Invalid tools/call params: ${String(error)}`,\n cause: 'validation'\n })\n )\n )\n\n const tool = findTool(params.name)\n\n if (Option.isNone(tool)) {\n return errorResponse(request.id, -32_602, `Unknown tool: ${params.name}`)\n }\n\n const result = yield* tool.value\n .execute(\n ToolCall.make({\n id: String(request.id),\n name: params.name,\n params: params.arguments ?? {}\n })\n )\n .pipe(\n Effect.catch(error =>\n Effect.succeed(mcpErrorResult(`MCP tool failed: ${error.message}`))\n )\n )\n\n return successResponse(request.id, mcpResultFromExecutionResult(result))\n }\n\n default:\n return errorResponse(request.id, -32_601, `Method not found: ${request.method}`)\n }\n }).pipe(Effect.catch(error => Effect.succeed(protocolErrorResponse(request.id, error))))\n\n const handleLine = (line: string) =>\n Effect.gen(function* () {\n const decoded: DecodedLine = yield* decodeMessage(line).pipe(\n Effect.map(decodedMessage),\n Effect.catch(error =>\n encodeJson(protocolErrorResponse(null, error)).pipe(\n Effect.map(response => decodedResponse(Option.some(response)))\n )\n )\n )\n\n if (Predicate.isTagged(decoded, 'Response')) {\n return decoded.response\n }\n\n const { message } = decoded\n\n if (!isRequest(message)) {\n return Option.none<string>()\n }\n\n const response = yield* handleRequest(message)\n const encoded = yield* encodeJson(response)\n\n return Option.some(encoded)\n })\n\n const handleJson = (body: string) =>\n Effect.gen(function* () {\n const response = yield* handleLine(body)\n\n if (Option.isNone(response)) {\n return yield* encodeJson(errorResponse(null, -32_600, 'Notifications have no response'))\n }\n\n return response.value\n })\n\n const handleHttpRequest = (request: Request) =>\n Effect.gen(function* () {\n const targetHostname = new URL(request.url).hostname\n\n const rejected = originValidationResponse(\n request,\n Array.from(input.allowedOriginHostnames ?? [targetHostname])\n )\n\n if (rejected !== undefined) {\n return rejected\n }\n\n if (!request.headers.has('mcp-protocol-version')) {\n if (request.method !== 'POST') {\n const body = yield* methodNotAllowedBody()\n\n return jsonResponse(body, { status: 405, headers: { allow: 'POST' } })\n }\n\n const body = yield* Effect.tryPromise({\n try: () => request.text(),\n catch: error => `Could not read request body: ${unknownToMessage(error)}`\n }).pipe(Effect.result)\n\n if (Result.isFailure(body)) {\n return jsonResponse(yield* badRequestBody(body.failure))\n }\n\n const responseBody = yield* handleJson(body.success).pipe(\n Effect.catch(error => badRequestBody(error.message))\n )\n\n return jsonResponse(responseBody)\n }\n\n const context = yield* Effect.context<R>()\n const handler = createMcpHandler(() => makeSdkServer(context))\n\n return yield* Effect.acquireUseRelease(\n Effect.succeed(handler),\n current =>\n Effect.tryPromise(() => current.fetch(request)).pipe(\n Effect.catch(error =>\n badRequestBody(unknownToMessage(error)).pipe(\n Effect.map(body => jsonResponse(body, { status: 400 }))\n )\n )\n ),\n current => Effect.promise(() => current.close()).pipe(Effect.catch(() => Effect.void))\n )\n })\n\n return { handleLine, handleJson, handleHttpRequest }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"server.mjs","names":["Arr","SdkMcpServer"],"sources":["../../src/server/server.ts"],"sourcesContent":["import { Array as Arr, Effect, Match, Option, Predicate, Result } from 'effect'\nimport type { Context } from 'effect'\nimport * as Schema from 'effect/Schema'\nimport {\n McpServer as SdkMcpServer,\n createMcpHandler,\n fromJsonSchema,\n originValidationResponse,\n type CallToolResult as SdkCallToolResult,\n type ContentBlock as SdkContentBlock\n} from '@modelcontextprotocol/server'\nimport {\n ToolCall,\n ToolResult,\n attachmentSourceBase64,\n attachmentSourcePreview,\n filePartText,\n contentParts,\n type ContentPart,\n type ToolDef\n} from '@yolk-sdk/agent/protocol'\nimport { legacyMcpProtocolVersion } from '@yolk-sdk/mcp/client'\nimport { McpServerError } from './errors.ts'\n\ntype JsonRpcRequest = {\n readonly jsonrpc: '2.0'\n readonly id: string | number\n readonly method: string\n readonly params?: unknown\n}\n\ntype JsonRpcNotification = {\n readonly jsonrpc: '2.0'\n readonly method: string\n readonly params?: unknown\n}\n\ntype JsonRpcResponse = {\n readonly jsonrpc: '2.0'\n readonly id: string | number | null\n readonly result?: unknown\n readonly error?: {\n readonly code: number\n readonly message: string\n }\n}\n\nconst JsonRpcRequestSchema = Schema.Struct({\n jsonrpc: Schema.Literal('2.0'),\n id: Schema.Union([Schema.String, Schema.Number]),\n method: Schema.String,\n params: Schema.optional(Schema.Unknown)\n})\n\nconst JsonRpcNotificationSchema = Schema.Struct({\n jsonrpc: Schema.Literal('2.0'),\n method: Schema.String,\n params: Schema.optional(Schema.Unknown)\n})\n\nconst CallToolParamsSchema = Schema.Struct({\n name: Schema.String,\n arguments: Schema.optional(Schema.Unknown)\n})\n\nconst JsonRpcMessageSchema = Schema.Union([JsonRpcRequestSchema, JsonRpcNotificationSchema])\n\ntype JsonRpcMessage = typeof JsonRpcMessageSchema.Type\n\nconst DecodedMessageLine = Schema.TaggedStruct('Message', {\n message: Schema.Unknown\n})\n\nconst DecodedResponseLine = Schema.TaggedStruct('Response', {\n response: Schema.Unknown\n})\n\ntype DecodedLine =\n | {\n readonly _tag: 'Message'\n readonly message: JsonRpcMessage\n }\n | {\n readonly _tag: 'Response'\n readonly response: Option.Option<string>\n }\n\nconst decodedMessage = (message: JsonRpcMessage): DecodedLine => ({\n ...DecodedMessageLine.make({ message }),\n message\n})\n\nconst decodedResponse = (response: Option.Option<string>): DecodedLine => ({\n ...DecodedResponseLine.make({ response }),\n response\n})\n\nconst decodeJson = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Unknown))\n\nconst decodeJsonRpcMessage = Schema.decodeUnknownEffect(JsonRpcMessageSchema)\n\nconst decodeCallToolParams = Schema.decodeUnknownEffect(CallToolParamsSchema)\n\nconst encodeJson = (value: JsonRpcResponse) =>\n Schema.encodeUnknownEffect(Schema.fromJsonString(Schema.Unknown))(value).pipe(\n Effect.mapError(\n error =>\n new McpServerError({\n message: `Could not encode MCP response: ${String(error)}`,\n cause: 'encoding'\n })\n )\n )\n\nconst decodeMessage = (line: string) =>\n decodeJson(line).pipe(\n Effect.mapError(\n error =>\n new McpServerError({\n message: `Malformed MCP JSON: ${String(error)}`,\n cause: 'parse'\n })\n ),\n Effect.flatMap(value =>\n decodeJsonRpcMessage(value).pipe(\n Effect.mapError(\n error =>\n new McpServerError({\n message: `Invalid MCP JSON-RPC message: ${String(error)}`,\n cause: 'validation'\n })\n )\n )\n )\n )\n\nconst successResponse = (id: string | number, result: unknown): JsonRpcResponse => ({\n jsonrpc: '2.0',\n id,\n result\n})\n\nconst errorResponse = (\n id: string | number | null,\n code: number,\n message: string\n): JsonRpcResponse => ({\n jsonrpc: '2.0',\n id,\n error: { code, message }\n})\n\nconst unknownToMessage = (error: unknown) =>\n error instanceof Error ? error.message : String(error)\n\nconst isRequest = (message: JsonRpcRequest | JsonRpcNotification): message is JsonRpcRequest =>\n 'id' in message\n\nconst protocolErrorCode = (error: McpServerError) => {\n switch (error.cause) {\n case 'parse':\n return -32_700\n case 'validation':\n return -32_600\n case 'protocol':\n return -32_603\n case 'tool_error':\n case 'encoding':\n return -32_000\n }\n}\n\nconst protocolErrorResponse = (id: string | number | null, error: McpServerError) =>\n errorResponse(id, protocolErrorCode(error), error.message)\n\nconst documentResourceUri = (filename: string) => `file:///${encodeURIComponent(filename)}`\n\nconst mcpContentBlockFromPart = (part: ContentPart): SdkContentBlock =>\n Match.value(part).pipe(\n Match.withReturnType<SdkContentBlock>(),\n Match.tag('Text', current => ({ type: 'text', text: current.text })),\n Match.tag('Image', current =>\n Option.match(attachmentSourceBase64(current.source), {\n onNone: () => ({\n type: 'text',\n text: `Image attachment: ${attachmentSourcePreview(current.source)}`\n }),\n onSome: data => ({ type: 'image', data, mimeType: current.mimeType })\n })\n ),\n Match.tag('Document', current =>\n Option.match(attachmentSourceBase64(current.source), {\n onNone: () => ({\n type: 'text',\n text: `Document attachment: ${attachmentSourcePreview(current.source)}`\n }),\n onSome: data => ({\n type: 'resource',\n resource: {\n uri: documentResourceUri(current.filename),\n name: current.title ?? current.filename,\n mimeType: current.mimeType,\n blob: data\n }\n })\n })\n ),\n Match.tag('Audio', current =>\n Option.match(attachmentSourceBase64(current.source), {\n onNone: () => ({\n type: 'text',\n text: `Audio attachment: ${attachmentSourcePreview(current.source)}`\n }),\n onSome: data => ({ type: 'audio', data, mimeType: current.mimeType })\n })\n ),\n // Inline file bytes leave as an embedded resource; a captured file only as its label.\n Match.tag('File', current =>\n Option.match(attachmentSourceBase64(current.source), {\n onNone: () => ({ type: 'text', text: filePartText(current) }),\n onSome: data => ({\n type: 'resource',\n resource: {\n uri: documentResourceUri(current.filename ?? 'file'),\n mimeType: current.mimeType,\n blob: data\n }\n })\n })\n ),\n Match.exhaustive\n )\n\nconst mcpResultFromToolResult = (result: ToolResult): SdkCallToolResult => {\n const content = Arr.map(contentParts(result.content), mcpContentBlockFromPart)\n const base = result.isError === undefined ? { content } : { content, isError: result.isError }\n\n return result.structuredContent === undefined\n ? base\n : { ...base, structuredContent: result.structuredContent }\n}\n\nconst mcpErrorResult = (message: string): SdkCallToolResult => ({\n content: [{ type: 'text', text: message }],\n isError: true\n})\n\nconst mcpResultFromExecutionResult = (\n result: ToolResult | ReturnType<typeof mcpErrorResult>\n): SdkCallToolResult => (result instanceof ToolResult ? mcpResultFromToolResult(result) : result)\n\nconst toolListItem = (tool: ToolDef) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.parameters\n})\n\nexport type McpServerTool<R = never> = {\n readonly def: ToolDef\n readonly execute: (call: ToolCall) => Effect.Effect<ToolResult, McpServerError, R>\n}\n\nexport type McpToolServer<R = never> = {\n readonly handleLine: (line: string) => Effect.Effect<Option.Option<string>, McpServerError, R>\n readonly handleJson: (body: string) => Effect.Effect<string, McpServerError, R>\n readonly handleHttpRequest: (request: Request) => Effect.Effect<Response, never, R>\n}\n\nconst jsonResponse = (body: string, init?: ResponseInit) =>\n new Response(body, {\n ...init,\n headers: {\n 'content-type': 'application/json',\n ...(init?.headers ?? {})\n }\n })\n\nconst methodNotAllowedBody = () =>\n encodeJson(errorResponse(null, -32_600, 'Method not allowed')).pipe(\n Effect.orElseSucceed(\n () => '{\"jsonrpc\":\"2.0\",\"id\":null,\"error\":{\"code\":-32600,\"message\":\"Method not allowed\"}}'\n )\n )\n\nconst badRequestBody = (message: string) =>\n encodeJson(errorResponse(null, -32_600, message)).pipe(\n Effect.orElseSucceed(\n () => '{\"jsonrpc\":\"2.0\",\"id\":null,\"error\":{\"code\":-32600,\"message\":\"Bad request\"}}'\n )\n )\n\nexport const makeMcpToolServer = <R>(input: {\n readonly name: string\n readonly version: string\n readonly tools: ReadonlyArray<McpServerTool<R>>\n readonly allowedOriginHostnames?: ReadonlyArray<string>\n}): McpToolServer<R> => {\n const findTool = (name: string) => Arr.findFirst(input.tools, tool => tool.def.name === name)\n\n const toolInputSchemas = input.tools.map(tool => ({\n tool,\n schema: Schema.decodeUnknownOption(Schema.Record(Schema.String, Schema.Unknown))(\n tool.def.parameters\n ).pipe(Option.getOrElse(() => ({ type: 'object', additionalProperties: true })))\n }))\n\n const makeSdkServer = (context: Context.Context<R>) => {\n const server = new SdkMcpServer(\n { name: input.name, version: input.version },\n {\n cacheHints: {\n 'server/discover': { ttlMs: 0, cacheScope: 'private' },\n 'tools/list': { ttlMs: 0, cacheScope: 'private' }\n }\n }\n )\n\n for (const { schema, tool } of toolInputSchemas) {\n server.registerTool(\n tool.def.name,\n {\n description: tool.def.description,\n inputSchema: fromJsonSchema(schema)\n },\n async (args, sdkContext) => {\n const result = await Effect.runPromiseWith(context)(\n tool\n .execute(\n ToolCall.make({\n id: String(sdkContext.mcpReq.id),\n name: tool.def.name,\n params: args\n })\n )\n .pipe(\n Effect.catch(error =>\n Effect.succeed(mcpErrorResult(`MCP tool failed: ${error.message}`))\n )\n )\n )\n\n return mcpResultFromExecutionResult(result)\n }\n )\n }\n\n return server\n }\n\n const handleRequest = (request: JsonRpcRequest) =>\n Effect.gen(function* () {\n switch (request.method) {\n case 'initialize':\n return successResponse(request.id, {\n protocolVersion: legacyMcpProtocolVersion,\n capabilities: { tools: {} },\n serverInfo: { name: input.name, version: input.version }\n })\n case 'tools/list':\n return successResponse(request.id, {\n tools: input.tools.map(tool => toolListItem(tool.def))\n })\n case 'tools/call': {\n const params = yield* decodeCallToolParams(request.params).pipe(\n Effect.mapError(\n error =>\n new McpServerError({\n message: `Invalid tools/call params: ${String(error)}`,\n cause: 'validation'\n })\n )\n )\n\n const tool = findTool(params.name)\n\n if (Option.isNone(tool)) {\n return errorResponse(request.id, -32_602, `Unknown tool: ${params.name}`)\n }\n\n const result = yield* tool.value\n .execute(\n ToolCall.make({\n id: String(request.id),\n name: params.name,\n params: params.arguments ?? {}\n })\n )\n .pipe(\n Effect.catch(error =>\n Effect.succeed(mcpErrorResult(`MCP tool failed: ${error.message}`))\n )\n )\n\n return successResponse(request.id, mcpResultFromExecutionResult(result))\n }\n\n default:\n return errorResponse(request.id, -32_601, `Method not found: ${request.method}`)\n }\n }).pipe(Effect.catch(error => Effect.succeed(protocolErrorResponse(request.id, error))))\n\n const handleLine = (line: string) =>\n Effect.gen(function* () {\n const decoded: DecodedLine = yield* decodeMessage(line).pipe(\n Effect.map(decodedMessage),\n Effect.catch(error =>\n encodeJson(protocolErrorResponse(null, error)).pipe(\n Effect.map(response => decodedResponse(Option.some(response)))\n )\n )\n )\n\n if (Predicate.isTagged(decoded, 'Response')) {\n return decoded.response\n }\n\n const { message } = decoded\n\n if (!isRequest(message)) {\n return Option.none<string>()\n }\n\n const response = yield* handleRequest(message)\n const encoded = yield* encodeJson(response)\n\n return Option.some(encoded)\n })\n\n const handleJson = (body: string) =>\n Effect.gen(function* () {\n const response = yield* handleLine(body)\n\n if (Option.isNone(response)) {\n return yield* encodeJson(errorResponse(null, -32_600, 'Notifications have no response'))\n }\n\n return response.value\n })\n\n const handleHttpRequest = (request: Request) =>\n Effect.gen(function* () {\n const targetHostname = new URL(request.url).hostname\n\n const rejected = originValidationResponse(\n request,\n Array.from(input.allowedOriginHostnames ?? [targetHostname])\n )\n\n if (rejected !== undefined) {\n return rejected\n }\n\n if (!request.headers.has('mcp-protocol-version')) {\n if (request.method !== 'POST') {\n const body = yield* methodNotAllowedBody()\n\n return jsonResponse(body, { status: 405, headers: { allow: 'POST' } })\n }\n\n const body = yield* Effect.tryPromise({\n try: () => request.text(),\n catch: error => `Could not read request body: ${unknownToMessage(error)}`\n }).pipe(Effect.result)\n\n if (Result.isFailure(body)) {\n return jsonResponse(yield* badRequestBody(body.failure))\n }\n\n const responseBody = yield* handleJson(body.success).pipe(\n Effect.catch(error => badRequestBody(error.message))\n )\n\n return jsonResponse(responseBody)\n }\n\n const context = yield* Effect.context<R>()\n const handler = createMcpHandler(() => makeSdkServer(context))\n\n return yield* Effect.acquireUseRelease(\n Effect.succeed(handler),\n current =>\n Effect.tryPromise(() => current.fetch(request)).pipe(\n Effect.catch(error =>\n badRequestBody(unknownToMessage(error)).pipe(\n Effect.map(body => jsonResponse(body, { status: 400 }))\n )\n )\n ),\n current => Effect.promise(() => current.close()).pipe(Effect.catch(() => Effect.void))\n )\n })\n\n return { handleLine, handleJson, handleHttpRequest }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yolk-sdk/mcp",
3
- "version": "0.1.0-canary.113",
3
+ "version": "0.1.0-canary.114",
4
4
  "description": "MCP v2 client/server/protocol APIs, Effect/Yolk adapters, legacy compatibility, and experimental conformance cases.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -85,8 +85,8 @@
85
85
  "@modelcontextprotocol/server": "2.0.0",
86
86
  "effect": "4.0.0",
87
87
  "eventsource-parser": "^3.0.0",
88
- "@yolk-sdk/agent": "^0.1.0-canary.113",
89
- "@yolk-sdk/conformance": "^0.1.0-canary.113"
88
+ "@yolk-sdk/agent": "^0.1.0-canary.114",
89
+ "@yolk-sdk/conformance": "^0.1.0-canary.114"
90
90
  },
91
91
  "scripts": {
92
92
  "build": "tsdown",
@@ -2,6 +2,7 @@ import { Array as Arr, Effect, Option, Predicate } from 'effect'
2
2
  import * as Schema from 'effect/Schema'
3
3
  import {
4
4
  AudioPart,
5
+ FilePart,
5
6
  ImagePart,
6
7
  TextPart,
7
8
  ToolDef,
@@ -294,17 +295,36 @@ const fallbackTextForContentBlock = (block: GenericContentBlock) => {
294
295
  }
295
296
  }
296
297
 
297
- const embeddedResourceText = (block: GenericContentBlock): Option.Option<string> =>
298
+ const resourceFilename = (uri: string) => {
299
+ const segments = (uri.split(/[?#]/u, 1)[0] ?? '').split('/').filter(part => part.length > 0)
300
+ const segment = segments[segments.length - 1]
301
+
302
+ if (segment === undefined || segment.endsWith(':')) return undefined
303
+
304
+ try {
305
+ return decodeURIComponent(segment)
306
+ } catch {
307
+ return segment
308
+ }
309
+ }
310
+
311
+ // Embedded text stays text; a blob becomes a file part that tool resolution captures (ADR 0009),
312
+ // so its base64 never reaches the model.
313
+ const embeddedResourcePart = (block: GenericContentBlock): Option.Option<ContentPart> =>
298
314
  Schema.decodeUnknownOption(EmbeddedResourceContentBlock)(block).pipe(
299
- Option.flatMap(({ resource }) => {
300
- if (resource.text !== undefined) {
301
- return Option.some(resource.text)
302
- }
303
-
304
- return Option.all({
305
- uri: Option.fromNullishOr(resource.uri),
306
- blob: Option.fromNullishOr(resource.blob)
307
- }).pipe(Option.map(({ uri, blob }) => `MCP resource: ${uri}\n${blob}`))
315
+ Option.flatMap(({ resource }): Option.Option<ContentPart> => {
316
+ if (resource.text !== undefined) return Option.some(TextPart.make({ text: resource.text }))
317
+
318
+ if (resource.blob === undefined) return Option.none()
319
+
320
+ const mimeType = resource.mimeType ?? 'application/octet-stream'
321
+ const filename = resource.uri === undefined ? undefined : resourceFilename(resource.uri)
322
+
323
+ return Option.some(
324
+ filename === undefined
325
+ ? FilePart.make({ source: inlineBase64Source(resource.blob), mimeType })
326
+ : FilePart.make({ source: inlineBase64Source(resource.blob), mimeType, filename })
327
+ )
308
328
  })
309
329
  )
310
330
 
@@ -357,11 +377,9 @@ const contentPartFromBlock = (block: GenericContentBlock): ContentPart => {
357
377
  }
358
378
 
359
379
  if (type === 'resource') {
360
- return TextPart.make({
361
- text: embeddedResourceText(block).pipe(
362
- Option.getOrElse(() => fallbackTextForContentBlock(block))
363
- )
364
- })
380
+ return Option.getOrElse(embeddedResourcePart(block), () =>
381
+ TextPart.make({ text: fallbackTextForContentBlock(block) })
382
+ )
365
383
  }
366
384
 
367
385
  if (type === 'resource_link') {
@@ -14,6 +14,7 @@ import {
14
14
  ToolResult,
15
15
  attachmentSourceBase64,
16
16
  attachmentSourcePreview,
17
+ filePartText,
17
18
  contentParts,
18
19
  type ContentPart,
19
20
  type ToolDef
@@ -213,6 +214,20 @@ const mcpContentBlockFromPart = (part: ContentPart): SdkContentBlock =>
213
214
  onSome: data => ({ type: 'audio', data, mimeType: current.mimeType })
214
215
  })
215
216
  ),
217
+ // Inline file bytes leave as an embedded resource; a captured file only as its label.
218
+ Match.tag('File', current =>
219
+ Option.match(attachmentSourceBase64(current.source), {
220
+ onNone: () => ({ type: 'text', text: filePartText(current) }),
221
+ onSome: data => ({
222
+ type: 'resource',
223
+ resource: {
224
+ uri: documentResourceUri(current.filename ?? 'file'),
225
+ mimeType: current.mimeType,
226
+ blob: data
227
+ }
228
+ })
229
+ })
230
+ ),
216
231
  Match.exhaustive
217
232
  )
218
233