@decocms/bindings 0.2.4-beta.2 → 0.2.4-beta.3

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 (92) hide show
  1. package/README.md +5 -5
  2. package/dist/core/binder.d.ts +3 -0
  3. package/dist/core/binder.js +81 -0
  4. package/dist/core/binder.js.map +1 -0
  5. package/dist/{client.js → core/client/http-client-transport.js} +9 -9
  6. package/dist/core/client/http-client-transport.js.map +1 -0
  7. package/dist/core/client/index.d.ts +3 -0
  8. package/dist/core/client/index.js +5 -0
  9. package/dist/core/client/index.js.map +1 -0
  10. package/dist/core/client/mcp-client.d.ts +233 -0
  11. package/dist/core/client/mcp-client.js +99 -0
  12. package/dist/core/client/mcp-client.js.map +1 -0
  13. package/dist/core/client/mcp.d.ts +3 -0
  14. package/dist/core/client/mcp.js +29 -0
  15. package/dist/core/client/mcp.js.map +1 -0
  16. package/dist/core/client/proxy.d.ts +10 -0
  17. package/dist/core/client/proxy.js +104 -0
  18. package/dist/core/client/proxy.js.map +1 -0
  19. package/dist/core/connection.js +1 -0
  20. package/dist/core/connection.js.map +1 -0
  21. package/dist/core/subset.d.ts +17 -0
  22. package/dist/core/subset.js +321 -0
  23. package/dist/core/subset.js.map +1 -0
  24. package/dist/index-D0aUdNls.d.ts +153 -0
  25. package/dist/index.d.ts +3 -94
  26. package/dist/index.js +5 -340
  27. package/dist/index.js.map +1 -1
  28. package/dist/{node → well-known}/agents.d.ts +64 -64
  29. package/dist/well-known/agents.js +28 -0
  30. package/dist/well-known/agents.js.map +1 -0
  31. package/dist/{node → well-known}/collections.d.ts +1 -1
  32. package/dist/{collections.js → well-known/collections.js} +24 -13
  33. package/dist/well-known/collections.js.map +1 -0
  34. package/dist/{node → well-known}/language-model.d.ts +353 -357
  35. package/dist/{node → well-known}/language-model.js +27 -21
  36. package/dist/well-known/language-model.js.map +1 -0
  37. package/package.json +17 -37
  38. package/dist/browser/agents.js +0 -29
  39. package/dist/browser/agents.js.map +0 -1
  40. package/dist/browser/chunk-6QEXJ7XW.js +0 -48564
  41. package/dist/browser/chunk-6QEXJ7XW.js.map +0 -1
  42. package/dist/browser/chunk-WKNVAFKE.js +0 -2176
  43. package/dist/browser/chunk-WKNVAFKE.js.map +0 -1
  44. package/dist/browser/chunk-XWLBKKHZ.js +0 -127
  45. package/dist/browser/chunk-XWLBKKHZ.js.map +0 -1
  46. package/dist/browser/chunk-ZX4ZDU2T.js +0 -58
  47. package/dist/browser/chunk-ZX4ZDU2T.js.map +0 -1
  48. package/dist/browser/client.js +0 -9
  49. package/dist/browser/client.js.map +0 -1
  50. package/dist/browser/collections.js +0 -4
  51. package/dist/browser/collections.js.map +0 -1
  52. package/dist/browser/connection.js +0 -8
  53. package/dist/browser/connection.js.map +0 -1
  54. package/dist/browser/index.js +0 -10
  55. package/dist/browser/index.js.map +0 -1
  56. package/dist/browser/language-model.js +0 -205
  57. package/dist/browser/language-model.js.map +0 -1
  58. package/dist/client.js.map +0 -1
  59. package/dist/collections.d.ts +0 -537
  60. package/dist/collections.js.map +0 -1
  61. package/dist/connection.js +0 -3
  62. package/dist/connection.js.map +0 -1
  63. package/dist/language-model.d.ts +0 -3228
  64. package/dist/language-model.js +0 -628
  65. package/dist/language-model.js.map +0 -1
  66. package/dist/models.d.ts +0 -2071
  67. package/dist/models.js +0 -111
  68. package/dist/models.js.map +0 -1
  69. package/dist/node/agents.js +0 -27
  70. package/dist/node/agents.js.map +0 -1
  71. package/dist/node/chunk-BLCFITZG.js +0 -56
  72. package/dist/node/chunk-BLCFITZG.js.map +0 -1
  73. package/dist/node/chunk-QMQMPK7Q.js +0 -50
  74. package/dist/node/chunk-QMQMPK7Q.js.map +0 -1
  75. package/dist/node/chunk-QP7AQCEP.js +0 -23478
  76. package/dist/node/chunk-QP7AQCEP.js.map +0 -1
  77. package/dist/node/chunk-T2DG7334.js +0 -125
  78. package/dist/node/chunk-T2DG7334.js.map +0 -1
  79. package/dist/node/client.d.ts +0 -12
  80. package/dist/node/client.js +0 -7
  81. package/dist/node/client.js.map +0 -1
  82. package/dist/node/collections.js +0 -4
  83. package/dist/node/collections.js.map +0 -1
  84. package/dist/node/connection.d.ts +0 -30
  85. package/dist/node/connection.js +0 -6
  86. package/dist/node/connection.js.map +0 -1
  87. package/dist/node/index.d.ts +0 -94
  88. package/dist/node/index.js +0 -8
  89. package/dist/node/index.js.map +0 -1
  90. package/dist/node/language-model.js.map +0 -1
  91. /package/dist/{client.d.ts → core/client/http-client-transport.d.ts} +0 -0
  92. /package/dist/{connection.d.ts → core/connection.d.ts} +0 -0
package/dist/index.d.ts CHANGED
@@ -1,94 +1,3 @@
1
- import { ZodType } from 'zod';
2
-
3
- /**
4
- * Core Binder Types and Utilities
5
- *
6
- * This module provides the core types and utilities for the bindings system.
7
- * Bindings define standardized interfaces that integrations (MCPs) can implement.
8
- */
9
-
10
- /**
11
- * ToolBinder defines a single tool within a binding.
12
- * It specifies the tool name, input/output schemas, and whether it's optional.
13
- *
14
- * @template TName - The tool name (can be a string or RegExp for pattern matching)
15
- * @template TInput - The input type (inferred from inputSchema)
16
- * @template TReturn - The return type (inferred from outputSchema)
17
- */
18
- interface ToolBinder<TName extends string | RegExp = string, TInput = any, TReturn extends object | null | boolean = object, TStreamable extends boolean = boolean> {
19
- /** The name of the tool (e.g., "DECO_CHAT_CHANNELS_JOIN") */
20
- name: TName;
21
- /** Zod schema for validating tool input */
22
- inputSchema: ZodType<TInput>;
23
- /** Optional Zod schema for validating tool output */
24
- outputSchema?: TStreamable extends true ? never : ZodType<TReturn>;
25
- /**
26
- * Whether this tool is streamable.
27
- */
28
- streamable?: TStreamable;
29
- /**
30
- * Whether this tool is optional in the binding.
31
- * If true, an implementation doesn't need to provide this tool.
32
- */
33
- opt?: true;
34
- }
35
- /**
36
- * Binder represents a collection of tool definitions that form a binding.
37
- * A binding is like a TypeScript interface - it defines what tools must be implemented.
38
- *
39
- * @template TDefinition - Array of ToolBinder definitions
40
- *
41
- * @example
42
- * ```ts
43
- * const MY_BINDING = [{
44
- * name: "MY_TOOL" as const,
45
- * inputSchema: z.object({ id: z.string() }),
46
- * outputSchema: z.object({ success: z.boolean() }),
47
- * }] as const satisfies Binder;
48
- * ```
49
- */
50
- type Binder<TDefinition extends readonly ToolBinder[] = readonly ToolBinder[]> = TDefinition;
51
- /**
52
- * Tool with schemas for validation
53
- */
54
- interface ToolWithSchemas {
55
- name: string;
56
- inputSchema?: ZodType<any> | Record<string, unknown>;
57
- outputSchema?: ZodType<any> | Record<string, unknown>;
58
- }
59
- /**
60
- * Binding checker interface
61
- */
62
- interface BindingChecker {
63
- /**
64
- * Check if a set of tools implements the binding with full schema validation.
65
- *
66
- * Validates:
67
- * - Tool name matches (exact or regex)
68
- * - Input schema: Tool accepts what binder requires (no removals from binder to tool)
69
- * - Output schema: Tool provides what binder expects (no removals from tool to binder)
70
- *
71
- * @param tools - Array of tools with names and schemas
72
- * @returns Promise<boolean> - true if all tools implement the binding correctly
73
- */
74
- isImplementedBy: (tools: ToolWithSchemas[]) => Promise<boolean>;
75
- }
76
- /**
77
- * Creates a binding checker with full schema validation using json-schema-diff.
78
- *
79
- * This performs strict compatibility checking:
80
- * - For input schemas: Validates that the tool can accept what the binder requires
81
- * - For output schemas: Validates that the tool provides what the binder expects
82
- *
83
- * @param binderTools - The binding definition to check against
84
- * @returns A binding checker with an async isImplementedBy method
85
- *
86
- * @example
87
- * ```ts
88
- * const checker = createBindingChecker(MY_BINDING);
89
- * const isCompatible = await checker.isImplementedBy(availableTools);
90
- * ```
91
- */
92
- declare function createBindingChecker<TDefinition extends readonly ToolBinder[]>(binderTools: TDefinition): BindingChecker;
93
-
94
- export { type Binder, type BindingChecker, type ToolBinder, type ToolWithSchemas, createBindingChecker };
1
+ export { B as Binder, f as BindingChecker, a as ToolBinder, T as ToolWithSchemas, j as createBindingChecker } from './index-D0aUdNls.js';
2
+ import 'zod/v3';
3
+ import './core/connection.js';
package/dist/index.js CHANGED
@@ -1,342 +1,7 @@
1
- import { diffSchemas } from 'json-schema-diff';
2
- import { zodToJsonSchema } from 'zod-to-json-schema';
3
- import { convertJsonSchemaToZod } from 'zod-from-json-schema';
4
- import { Client as Client$1 } from '@modelcontextprotocol/sdk/client/index.js';
5
- import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
6
- import { WebSocketClientTransport } from '@modelcontextprotocol/sdk/client/websocket.js';
7
- import { ListToolsResultSchema } from '@modelcontextprotocol/sdk/types.js';
8
- import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
9
-
10
- // src/core/binder.ts
11
- var HTTPClientTransport = class extends StreamableHTTPClientTransport {
12
- constructor(url, opts) {
13
- super(url, opts);
14
- }
15
- send(message, options) {
16
- const mockAction = getMockActionFor(message);
17
- if (mockAction?.type === "emit") {
18
- this.onmessage?.(mockAction.message);
19
- return Promise.resolve();
20
- }
21
- if (mockAction?.type === "suppress") {
22
- return Promise.resolve();
23
- }
24
- return super.send(message, options);
25
- }
1
+ import {
2
+ createBindingChecker
3
+ } from "./core/binder";
4
+ export {
5
+ createBindingChecker
26
6
  };
27
- function getMockActionFor(message) {
28
- const m = message;
29
- if (!m || typeof m !== "object" || !("method" in m)) return null;
30
- switch (m.method) {
31
- case "initialize": {
32
- const protocolVersion = m?.params?.protocolVersion;
33
- if (!protocolVersion) return null;
34
- return {
35
- type: "emit",
36
- message: {
37
- result: {
38
- protocolVersion,
39
- capabilities: { tools: {} },
40
- serverInfo: { name: "deco-chat-server", version: "1.0.0" }
41
- },
42
- jsonrpc: m.jsonrpc ?? "2.0",
43
- // @ts-expect-error - id is not typed
44
- id: m.id
45
- }
46
- };
47
- }
48
- case "notifications/roots/list_changed":
49
- case "notifications/initialized":
50
- case "notifications/cancelled":
51
- case "notifications/progress": {
52
- return { type: "suppress" };
53
- }
54
- default:
55
- return null;
56
- }
57
- }
58
-
59
- // src/core/client/mcp-client.ts
60
- var Client = class extends Client$1 {
61
- constructor(_clientInfo, options) {
62
- super(_clientInfo, options);
63
- }
64
- async listTools(params, options) {
65
- const result = await this.request(
66
- { method: "tools/list", params },
67
- ListToolsResultSchema,
68
- options
69
- );
70
- return result;
71
- }
72
- };
73
- var createServerClient = async (mcpServer, signal, extraHeaders) => {
74
- const transport = createTransport(mcpServer.connection, signal, extraHeaders);
75
- if (!transport) {
76
- throw new Error("Unknown MCP connection type");
77
- }
78
- const client = new Client({
79
- name: mcpServer?.name ?? "MCP Client",
80
- version: "1.0.0"
81
- });
82
- await client.connect(transport);
83
- return {
84
- client,
85
- callStreamableTool: (tool, args) => {
86
- if (mcpServer.connection.type !== "HTTP") {
87
- throw new Error("HTTP connection required");
88
- }
89
- return fetch(mcpServer.connection.url + `/call-tool/${tool}`, {
90
- method: "POST",
91
- redirect: "manual",
92
- body: JSON.stringify(args),
93
- headers: {
94
- ...extraHeaders,
95
- Authorization: `Bearer ${mcpServer.connection.token}`
96
- }
97
- });
98
- }
99
- };
100
- };
101
- var createTransport = (connection, signal, extraHeaders) => {
102
- if (connection.type === "Websocket") {
103
- return new WebSocketClientTransport(new URL(connection.url));
104
- }
105
- if (connection.type !== "SSE" && connection.type !== "HTTP") {
106
- return null;
107
- }
108
- const authHeaders = connection.token ? { authorization: `Bearer ${connection.token}` } : {};
109
- const headers = {
110
- ...authHeaders,
111
- ...extraHeaders ?? {},
112
- ..."headers" in connection ? connection.headers || {} : {}
113
- };
114
- if (connection.type === "SSE") {
115
- const config = {
116
- requestInit: { headers, signal }
117
- };
118
- if (connection.token) {
119
- config.eventSourceInit = {
120
- fetch: (req, init) => {
121
- return fetch(req, {
122
- ...init,
123
- headers: {
124
- ...headers,
125
- Accept: "text/event-stream"
126
- },
127
- signal
128
- });
129
- }
130
- };
131
- }
132
- return new SSEClientTransport(new URL(connection.url), config);
133
- }
134
- return new HTTPClientTransport(new URL(connection.url), {
135
- requestInit: {
136
- headers,
137
- signal,
138
- // @ts-ignore - this is a valid option for fetch
139
- credentials: "include"
140
- }
141
- });
142
- };
143
-
144
- // src/core/client/proxy.ts
145
- var safeParse = (content) => {
146
- try {
147
- return JSON.parse(content);
148
- } catch {
149
- return content;
150
- }
151
- };
152
- var toolsMap = /* @__PURE__ */ new Map();
153
- function createMCPClientProxy(options) {
154
- return new Proxy({}, {
155
- get(_, name) {
156
- if (name === "toJSON") {
157
- return null;
158
- }
159
- if (typeof name !== "string") {
160
- throw new Error("Name must be a string");
161
- }
162
- async function callToolFn(args) {
163
- const debugId = options?.debugId?.();
164
- const extraHeaders = debugId ? { "x-trace-debug-id": debugId } : void 0;
165
- const { client, callStreamableTool } = await createServerClient(
166
- { connection: options.connection },
167
- void 0,
168
- extraHeaders
169
- );
170
- if (options?.streamable?.[String(name)]) {
171
- return callStreamableTool(String(name), args);
172
- }
173
- const { structuredContent, isError, content } = await client.callTool(
174
- {
175
- name: String(name),
176
- arguments: args
177
- },
178
- void 0,
179
- {
180
- timeout: 3e6
181
- }
182
- );
183
- if (isError) {
184
- const maybeErrorMessage = content?.[0]?.text;
185
- const error = typeof maybeErrorMessage === "string" ? safeParse(maybeErrorMessage) : null;
186
- const throwableError = error?.code && typeof options?.getErrorByStatusCode === "function" ? options.getErrorByStatusCode(
187
- error.code,
188
- error.message,
189
- error.traceId
190
- ) : null;
191
- if (throwableError) {
192
- throw throwableError;
193
- }
194
- throw new Error(
195
- `Tool ${String(name)} returned an error: ${JSON.stringify(
196
- structuredContent ?? content
197
- )}`
198
- );
199
- }
200
- return structuredContent;
201
- }
202
- const listToolsFn = async () => {
203
- const { client } = await createServerClient({
204
- connection: options.connection
205
- });
206
- const { tools } = await client.listTools();
207
- return tools;
208
- };
209
- async function listToolsOnce() {
210
- const conn = options.connection;
211
- const key = JSON.stringify(conn);
212
- try {
213
- if (!toolsMap.has(key)) {
214
- toolsMap.set(key, listToolsFn());
215
- }
216
- return await toolsMap.get(key);
217
- } catch (error) {
218
- console.error("Failed to list tools", error);
219
- toolsMap.delete(key);
220
- return;
221
- }
222
- }
223
- callToolFn.asTool = async () => {
224
- const tools = await listToolsOnce() ?? [];
225
- const tool = tools.find((t) => t.name === name);
226
- if (!tool) {
227
- throw new Error(`Tool ${name} not found`);
228
- }
229
- return {
230
- ...tool,
231
- id: tool.name,
232
- inputSchema: tool.inputSchema ? convertJsonSchemaToZod(tool.inputSchema) : void 0,
233
- outputSchema: tool.outputSchema ? convertJsonSchemaToZod(tool.outputSchema) : void 0,
234
- execute: (input) => {
235
- return callToolFn(input.context);
236
- }
237
- };
238
- };
239
- return callToolFn;
240
- }
241
- });
242
- }
243
-
244
- // src/core/client/mcp.ts
245
- new Proxy(
246
- {},
247
- {
248
- get(_, name) {
249
- if (name === "toJSON") {
250
- return null;
251
- }
252
- if (name === "forConnection") {
253
- return (connection) => createMCPFetchStub({
254
- connection
255
- });
256
- }
257
- return global[name];
258
- }
259
- }
260
- );
261
- function createMCPFetchStub(options) {
262
- return createMCPClientProxy(options);
263
- }
264
-
265
- // src/core/binder.ts
266
- function normalizeSchema(schema) {
267
- if (!schema) return void 0;
268
- if (schema._def) {
269
- const jsonSchema2 = zodToJsonSchema(schema, {
270
- // Don't add additionalProperties: false to allow structural compatibility
271
- $refStrategy: "none"
272
- });
273
- if (jsonSchema2.type === "object") {
274
- delete jsonSchema2.additionalProperties;
275
- }
276
- return jsonSchema2;
277
- }
278
- const jsonSchema = schema;
279
- if (jsonSchema.type === "object" && "additionalProperties" in jsonSchema) {
280
- const copy = { ...jsonSchema };
281
- delete copy.additionalProperties;
282
- return copy;
283
- }
284
- return jsonSchema;
285
- }
286
- function createBindingChecker(binderTools) {
287
- return {
288
- isImplementedBy: async (tools) => {
289
- for (const binderTool of binderTools) {
290
- const pattern = typeof binderTool.name === "string" ? new RegExp(`^${binderTool.name}$`) : binderTool.name;
291
- const matchedTool = tools.find((t) => pattern.test(t.name));
292
- if (!matchedTool && binderTool.opt) {
293
- continue;
294
- }
295
- if (!matchedTool) {
296
- return false;
297
- }
298
- const binderInputSchema = normalizeSchema(binderTool.inputSchema);
299
- const toolInputSchema = normalizeSchema(matchedTool.inputSchema);
300
- if (binderInputSchema && toolInputSchema) {
301
- try {
302
- const inputDiff = await diffSchemas({
303
- sourceSchema: binderInputSchema,
304
- destinationSchema: toolInputSchema
305
- });
306
- if (inputDiff.removalsFound) {
307
- return false;
308
- }
309
- } catch (error) {
310
- console.error("Schema diff failed", error);
311
- return false;
312
- }
313
- } else if (binderInputSchema && !toolInputSchema) {
314
- return false;
315
- }
316
- const binderOutputSchema = normalizeSchema(binderTool.outputSchema);
317
- const toolOutputSchema = normalizeSchema(matchedTool.outputSchema);
318
- if (binderOutputSchema && toolOutputSchema) {
319
- try {
320
- const outputDiff = await diffSchemas({
321
- sourceSchema: binderOutputSchema,
322
- destinationSchema: toolOutputSchema
323
- });
324
- if (outputDiff.removalsFound) {
325
- return false;
326
- }
327
- } catch (error) {
328
- console.error("Schema diff failed", error);
329
- return false;
330
- }
331
- } else if (binderOutputSchema && !toolOutputSchema) {
332
- return false;
333
- }
334
- }
335
- return true;
336
- }
337
- };
338
- }
339
-
340
- export { createBindingChecker };
341
- //# sourceMappingURL=index.js.map
342
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/client/http-client-transport.ts","../src/core/client/mcp-client.ts","../src/core/client/proxy.ts","../src/core/client/mcp.ts","../src/core/binder.ts"],"names":["BaseClient","jsonSchema"],"mappings":"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","file":"index.js","sourcesContent":["import type { JSONRPCMessage } from \"@modelcontextprotocol/sdk/types.js\";\nimport {\n StreamableHTTPClientTransport,\n type StreamableHTTPClientTransportOptions,\n} from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\n\nexport class HTTPClientTransport extends StreamableHTTPClientTransport {\n constructor(url: URL, opts?: StreamableHTTPClientTransportOptions) {\n super(url, opts);\n }\n\n override send(\n message: JSONRPCMessage,\n options?: {\n resumptionToken?: string;\n onresumptiontoken?: (token: string) => void;\n },\n ): Promise<void> {\n const mockAction = getMockActionFor(message);\n if (mockAction?.type === \"emit\") {\n this.onmessage?.(mockAction.message);\n return Promise.resolve();\n }\n if (mockAction?.type === \"suppress\") {\n return Promise.resolve();\n }\n return super.send(message, options);\n }\n}\n\ntype MockAction =\n | { type: \"emit\"; message: JSONRPCMessage }\n | { type: \"suppress\" };\n\nfunction getMockActionFor(message: JSONRPCMessage): MockAction | null {\n const m = message;\n if (!m || typeof m !== \"object\" || !(\"method\" in m)) return null;\n\n switch (m.method) {\n case \"initialize\": {\n const protocolVersion = m?.params?.protocolVersion;\n if (!protocolVersion) return null;\n return {\n type: \"emit\",\n message: {\n result: {\n protocolVersion,\n capabilities: { tools: {} },\n serverInfo: { name: \"deco-chat-server\", version: \"1.0.0\" },\n },\n jsonrpc: m.jsonrpc ?? \"2.0\",\n // @ts-expect-error - id is not typed\n id: m.id,\n } as JSONRPCMessage,\n };\n }\n case \"notifications/roots/list_changed\":\n case \"notifications/initialized\":\n case \"notifications/cancelled\":\n case \"notifications/progress\": {\n return { type: \"suppress\" };\n }\n default:\n return null;\n }\n}\n","import {\n Client as BaseClient,\n ClientOptions,\n} from \"@modelcontextprotocol/sdk/client/index.js\";\nimport {\n SSEClientTransport,\n SSEClientTransportOptions,\n} from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { WebSocketClientTransport } from \"@modelcontextprotocol/sdk/client/websocket.js\";\nimport { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport {\n Implementation,\n ListToolsRequest,\n ListToolsResultSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { MCPConnection } from \"../connection\";\nimport { HTTPClientTransport } from \"./http-client-transport\";\n\n/**\n * WARNNING: This is a hack to prevent schema compilation errors.\n * More info at: https://github.com/modelcontextprotocol/typescript-sdk/issues/923\n *\n * Make sure to keep this updated with the right version of the SDK.\n * https://github.com/modelcontextprotocol/typescript-sdk/blob/bf817939917277a4c59f2e19e7b44b8dd7ff140c/src/client/index.ts#L480\n */\nclass Client extends BaseClient {\n constructor(_clientInfo: Implementation, options?: ClientOptions) {\n super(_clientInfo, options);\n }\n\n override async listTools(\n params?: ListToolsRequest[\"params\"],\n options?: RequestOptions,\n ) {\n const result = await this.request(\n { method: \"tools/list\", params },\n ListToolsResultSchema,\n options,\n );\n\n return result;\n }\n}\n\nexport interface ServerClient {\n client: Client;\n callStreamableTool: (tool: string, args: unknown) => Promise<Response>;\n}\nexport const createServerClient = async (\n mcpServer: { connection: MCPConnection; name?: string },\n signal?: AbortSignal,\n extraHeaders?: Record<string, string>,\n): Promise<ServerClient> => {\n const transport = createTransport(mcpServer.connection, signal, extraHeaders);\n\n if (!transport) {\n throw new Error(\"Unknown MCP connection type\");\n }\n\n const client = new Client({\n name: mcpServer?.name ?? \"MCP Client\",\n version: \"1.0.0\",\n });\n\n await client.connect(transport);\n\n return {\n client,\n callStreamableTool: (tool, args) => {\n if (mcpServer.connection.type !== \"HTTP\") {\n throw new Error(\"HTTP connection required\");\n }\n return fetch(mcpServer.connection.url + `/call-tool/${tool}`, {\n method: \"POST\",\n redirect: \"manual\",\n body: JSON.stringify(args),\n headers: {\n ...extraHeaders,\n Authorization: `Bearer ${mcpServer.connection.token}`,\n },\n });\n },\n };\n};\n\nexport const createTransport = (\n connection: MCPConnection,\n signal?: AbortSignal,\n extraHeaders?: Record<string, string>,\n) => {\n if (connection.type === \"Websocket\") {\n return new WebSocketClientTransport(new URL(connection.url));\n }\n\n if (connection.type !== \"SSE\" && connection.type !== \"HTTP\") {\n return null;\n }\n\n const authHeaders: Record<string, string> = connection.token\n ? { authorization: `Bearer ${connection.token}` }\n : {};\n\n const headers: Record<string, string> = {\n ...authHeaders,\n ...(extraHeaders ?? {}),\n ...(\"headers\" in connection ? connection.headers || {} : {}),\n };\n\n if (connection.type === \"SSE\") {\n const config: SSEClientTransportOptions = {\n requestInit: { headers, signal },\n };\n\n if (connection.token) {\n config.eventSourceInit = {\n fetch: (req, init) => {\n return fetch(req, {\n ...init,\n headers: {\n ...headers,\n Accept: \"text/event-stream\",\n },\n signal,\n });\n },\n };\n }\n\n return new SSEClientTransport(new URL(connection.url), config);\n }\n return new HTTPClientTransport(new URL(connection.url), {\n requestInit: {\n headers,\n signal,\n // @ts-ignore - this is a valid option for fetch\n credentials: \"include\",\n },\n });\n};\n","/* oxlint-disable no-explicit-any */\nimport { convertJsonSchemaToZod } from \"zod-from-json-schema\";\nimport type { CreateStubAPIOptions } from \"./mcp\";\nimport { createServerClient } from \"./mcp-client\";\n\nconst safeParse = (content: string) => {\n try {\n return JSON.parse(content as string);\n } catch {\n return content;\n }\n};\n\nconst toolsMap = new Map<\n string,\n Promise<\n Array<{\n name: string;\n inputSchema: any;\n outputSchema?: any;\n description: string;\n }>\n >\n>();\n\n/**\n * The base fetcher used to fetch the MCP from API.\n */\nexport function createMCPClientProxy<T extends Record<string, unknown>>(\n options: CreateStubAPIOptions,\n): T {\n return new Proxy<T>({} as T, {\n get(_, name) {\n if (name === \"toJSON\") {\n return null;\n }\n if (typeof name !== \"string\") {\n throw new Error(\"Name must be a string\");\n }\n async function callToolFn(args: unknown) {\n const debugId = options?.debugId?.();\n const extraHeaders = debugId\n ? { \"x-trace-debug-id\": debugId }\n : undefined;\n\n const { client, callStreamableTool } = await createServerClient(\n { connection: options.connection },\n undefined,\n extraHeaders,\n );\n\n if (options?.streamable?.[String(name)]) {\n return callStreamableTool(String(name), args);\n }\n\n const { structuredContent, isError, content } = await client.callTool(\n {\n name: String(name),\n arguments: args as Record<string, unknown>,\n },\n undefined,\n {\n timeout: 3000000,\n },\n );\n\n if (isError) {\n const maybeErrorMessage = (content as { text: string }[])?.[0]?.text;\n const error =\n typeof maybeErrorMessage === \"string\"\n ? safeParse(maybeErrorMessage)\n : null;\n\n const throwableError =\n error?.code && typeof options?.getErrorByStatusCode === \"function\"\n ? options.getErrorByStatusCode(\n error.code,\n error.message,\n error.traceId,\n )\n : null;\n\n if (throwableError) {\n throw throwableError;\n }\n\n throw new Error(\n `Tool ${String(name)} returned an error: ${JSON.stringify(\n structuredContent ?? content,\n )}`,\n );\n }\n return structuredContent;\n }\n\n const listToolsFn = async () => {\n const { client } = await createServerClient({\n connection: options.connection,\n });\n const { tools } = await client.listTools();\n\n return tools as {\n name: string;\n inputSchema: any;\n outputSchema?: any;\n description: string;\n }[];\n };\n\n async function listToolsOnce() {\n const conn = options.connection;\n const key = JSON.stringify(conn);\n\n try {\n if (!toolsMap.has(key)) {\n toolsMap.set(key, listToolsFn());\n }\n\n return await toolsMap.get(key)!;\n } catch (error) {\n console.error(\"Failed to list tools\", error);\n\n toolsMap.delete(key);\n return;\n }\n }\n callToolFn.asTool = async () => {\n const tools = (await listToolsOnce()) ?? [];\n const tool = tools.find((t) => t.name === name);\n if (!tool) {\n throw new Error(`Tool ${name} not found`);\n }\n\n return {\n ...tool,\n id: tool.name,\n inputSchema: tool.inputSchema\n ? convertJsonSchemaToZod(tool.inputSchema)\n : undefined,\n outputSchema: tool.outputSchema\n ? convertJsonSchemaToZod(tool.outputSchema)\n : undefined,\n execute: (input: any) => {\n return callToolFn(input.context);\n },\n };\n };\n return callToolFn;\n },\n });\n}\n","/* oxlint-disable no-explicit-any */\nimport { z } from \"zod\";\nimport type { MCPConnection } from \"../connection\";\nimport { createMCPClientProxy } from \"./proxy\";\n\nexport interface FetchOptions extends RequestInit {\n path?: string;\n segments?: string[];\n}\n\n// Default fetcher instance with API_SERVER_URL and API_HEADERS\nexport const MCPClient = new Proxy(\n {} as {\n forConnection: <TDefinition extends readonly ToolBinder[]>(\n connection: MCPConnection,\n ) => MCPClientFetchStub<TDefinition>;\n },\n {\n get(_, name) {\n if (name === \"toJSON\") {\n return null;\n }\n\n if (name === \"forConnection\") {\n return <TDefinition extends readonly ToolBinder[]>(\n connection: MCPConnection,\n ) =>\n createMCPFetchStub<TDefinition>({\n connection,\n });\n }\n return global[name as keyof typeof global];\n },\n },\n);\n\nimport type { ToolBinder } from \"../binder\";\nexport type { ToolBinder };\n\nexport const isStreamableToolBinder = (\n toolBinder: ToolBinder,\n): toolBinder is ToolBinder<string, any, any, true> => {\n return toolBinder.streamable === true;\n};\nexport type MCPClientStub<TDefinition extends readonly ToolBinder[]> = {\n [K in TDefinition[number] as K[\"name\"]]: K extends ToolBinder<\n string,\n infer TInput,\n infer TReturn\n >\n ? (params: TInput, init?: RequestInit) => Promise<TReturn>\n : never;\n};\n\nexport type MCPClientFetchStub<TDefinition extends readonly ToolBinder[]> = {\n [K in TDefinition[number] as K[\"name\"]]: K[\"streamable\"] extends true\n ? K extends ToolBinder<string, infer TInput, any, true>\n ? (params: TInput, init?: RequestInit) => Promise<Response>\n : never\n : K extends ToolBinder<string, infer TInput, infer TReturn, any>\n ? (params: TInput, init?: RequestInit) => Promise<Awaited<TReturn>>\n : never;\n};\n\nexport interface MCPClientRaw {\n callTool: (tool: string, args: unknown) => Promise<unknown>;\n listTools: () => Promise<\n {\n name: string;\n inputSchema: any;\n outputSchema?: any;\n description: string;\n }[]\n >;\n}\nexport type JSONSchemaToZodConverter = (jsonSchema: any) => z.ZodTypeAny;\nexport interface CreateStubAPIOptions {\n connection: MCPConnection;\n streamable?: Record<string, boolean>;\n debugId?: () => string;\n getErrorByStatusCode?: (\n statusCode: number,\n message?: string,\n traceId?: string,\n errorObject?: unknown,\n ) => Error;\n}\n\nexport function createMCPFetchStub<TDefinition extends readonly ToolBinder[]>(\n options: CreateStubAPIOptions,\n): MCPClientFetchStub<TDefinition> {\n return createMCPClientProxy<MCPClientFetchStub<TDefinition>>(options);\n}\n","/**\n * Core Binder Types and Utilities\n *\n * This module provides the core types and utilities for the bindings system.\n * Bindings define standardized interfaces that integrations (MCPs) can implement.\n */\n\nimport { diffSchemas } from \"json-schema-diff\";\nimport type { ZodType } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\nimport { createMCPFetchStub, MCPClientFetchStub } from \"./client/mcp\";\nimport { MCPConnection } from \"./connection\";\n\n/**\n * ToolBinder defines a single tool within a binding.\n * It specifies the tool name, input/output schemas, and whether it's optional.\n *\n * @template TName - The tool name (can be a string or RegExp for pattern matching)\n * @template TInput - The input type (inferred from inputSchema)\n * @template TReturn - The return type (inferred from outputSchema)\n */\nexport interface ToolBinder<\n TName extends string | RegExp = string,\n // biome-ignore lint/suspicious/noExplicitAny: Generic type parameter\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TInput = any,\n TReturn extends object | null | boolean = object,\n TStreamable extends boolean = boolean,\n> {\n /** The name of the tool (e.g., \"DECO_CHAT_CHANNELS_JOIN\") */\n name: TName;\n\n /** Zod schema for validating tool input */\n inputSchema: ZodType<TInput>;\n\n /** Optional Zod schema for validating tool output */\n outputSchema?: TStreamable extends true ? never : ZodType<TReturn>;\n\n /**\n * Whether this tool is streamable.\n */\n streamable?: TStreamable;\n\n /**\n * Whether this tool is optional in the binding.\n * If true, an implementation doesn't need to provide this tool.\n */\n opt?: true;\n}\n\n/**\n * Binder represents a collection of tool definitions that form a binding.\n * A binding is like a TypeScript interface - it defines what tools must be implemented.\n *\n * @template TDefinition - Array of ToolBinder definitions\n *\n * @example\n * ```ts\n * const MY_BINDING = [{\n * name: \"MY_TOOL\" as const,\n * inputSchema: z.object({ id: z.string() }),\n * outputSchema: z.object({ success: z.boolean() }),\n * }] as const satisfies Binder;\n * ```\n */\nexport type Binder<\n TDefinition extends readonly ToolBinder[] = readonly ToolBinder[],\n> = TDefinition;\n\n/**\n * Tool with schemas for validation\n */\nexport interface ToolWithSchemas {\n name: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n inputSchema?: ZodType<any> | Record<string, unknown>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n outputSchema?: ZodType<any> | Record<string, unknown>;\n}\n\n/**\n * Converts a schema to JSON Schema format if it's a Zod schema\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction normalizeSchema(schema: any): Record<string, unknown> | undefined {\n if (!schema) return undefined;\n\n // If it's a Zod schema (has _def property), convert it\n if (schema._def) {\n const jsonSchema = zodToJsonSchema(schema, {\n // Don't add additionalProperties: false to allow structural compatibility\n $refStrategy: \"none\",\n }) as Record<string, unknown>;\n\n // Remove additionalProperties constraint to allow subtyping\n if (jsonSchema.type === \"object\") {\n delete jsonSchema.additionalProperties;\n }\n\n return jsonSchema;\n }\n\n // Otherwise assume it's already a JSON Schema\n const jsonSchema = schema as Record<string, unknown>;\n\n // Remove additionalProperties constraint if present\n if (jsonSchema.type === \"object\" && \"additionalProperties\" in jsonSchema) {\n const copy = { ...jsonSchema };\n delete copy.additionalProperties;\n return copy;\n }\n\n return jsonSchema;\n}\n\n/**\n * Binding checker interface\n */\nexport interface BindingChecker {\n /**\n * Check if a set of tools implements the binding with full schema validation.\n *\n * Validates:\n * - Tool name matches (exact or regex)\n * - Input schema: Tool accepts what binder requires (no removals from binder to tool)\n * - Output schema: Tool provides what binder expects (no removals from tool to binder)\n *\n * @param tools - Array of tools with names and schemas\n * @returns Promise<boolean> - true if all tools implement the binding correctly\n */\n isImplementedBy: (tools: ToolWithSchemas[]) => Promise<boolean>;\n}\n\nexport const bindingClient = <TDefinition extends readonly ToolBinder[]>(\n binder: TDefinition,\n) => {\n return {\n ...createBindingChecker(binder),\n forConnection: (\n mcpConnection: MCPConnection,\n ): MCPClientFetchStub<TDefinition> => {\n return createMCPFetchStub<TDefinition>({\n connection: mcpConnection,\n streamable: binder.reduce(\n (acc, tool) => {\n acc[tool.name] = tool.streamable === true;\n return acc;\n },\n {} as Record<string, boolean>,\n ),\n });\n },\n };\n};\n\nexport type MCPBindingClient<T extends ReturnType<typeof bindingClient>> =\n ReturnType<T[\"forConnection\"]>;\n\n/**\n * Creates a binding checker with full schema validation using json-schema-diff.\n *\n * This performs strict compatibility checking:\n * - For input schemas: Validates that the tool can accept what the binder requires\n * - For output schemas: Validates that the tool provides what the binder expects\n *\n * @param binderTools - The binding definition to check against\n * @returns A binding checker with an async isImplementedBy method\n *\n * @example\n * ```ts\n * const checker = createBindingChecker(MY_BINDING);\n * const isCompatible = await checker.isImplementedBy(availableTools);\n * ```\n */\nexport function createBindingChecker<TDefinition extends readonly ToolBinder[]>(\n binderTools: TDefinition,\n): BindingChecker {\n return {\n isImplementedBy: async (tools: ToolWithSchemas[]) => {\n for (const binderTool of binderTools) {\n // Find matching tool by name (exact or regex)\n const pattern =\n typeof binderTool.name === \"string\"\n ? new RegExp(`^${binderTool.name}$`)\n : binderTool.name;\n\n const matchedTool = tools.find((t) => pattern.test(t.name));\n\n // Skip optional tools that aren't present\n if (!matchedTool && binderTool.opt) {\n continue;\n }\n\n // Required tool not found\n if (!matchedTool) {\n return false;\n }\n\n // === INPUT SCHEMA VALIDATION ===\n // Tool must accept what binder requires\n // Check: binder (source) -> tool (destination)\n // If removals found, tool doesn't accept something binder requires\n const binderInputSchema = normalizeSchema(binderTool.inputSchema);\n const toolInputSchema = normalizeSchema(matchedTool.inputSchema);\n\n if (binderInputSchema && toolInputSchema) {\n try {\n const inputDiff = await diffSchemas({\n sourceSchema: binderInputSchema,\n destinationSchema: toolInputSchema,\n });\n\n // If something was removed from binder to tool, tool can't accept it\n if (inputDiff.removalsFound) {\n return false;\n }\n } catch (error) {\n console.error(\"Schema diff failed\", error);\n // Schema diff failed - consider incompatible\n return false;\n }\n } else if (binderInputSchema && !toolInputSchema) {\n // Binder requires input schema but tool doesn't have one\n return false;\n }\n\n // === OUTPUT SCHEMA VALIDATION ===\n // Tool must provide what binder expects (but can provide more)\n // Check: binder (source) -> tool (destination)\n // If removals found, tool doesn't provide something binder expects\n const binderOutputSchema = normalizeSchema(binderTool.outputSchema);\n const toolOutputSchema = normalizeSchema(matchedTool.outputSchema);\n\n if (binderOutputSchema && toolOutputSchema) {\n try {\n const outputDiff = await diffSchemas({\n sourceSchema: binderOutputSchema,\n destinationSchema: toolOutputSchema,\n });\n\n // If something was removed from binder to tool, tool doesn't provide it\n if (outputDiff.removalsFound) {\n return false;\n }\n } catch (error) {\n console.error(\"Schema diff failed\", error);\n // Schema diff failed - consider incompatible\n return false;\n }\n } else if (binderOutputSchema && !toolOutputSchema) {\n // Binder expects output schema but tool doesn't have one\n return false;\n }\n }\n\n return true;\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @decocms/bindings\n *\n * Core type definitions for the bindings system.\n * Bindings define standardized interfaces that integrations (MCPs) can implement.\n */\n\n// Re-export core binder types and utilities\nexport {\n createBindingChecker,\n type Binder,\n type BindingChecker,\n type ToolBinder,\n type ToolWithSchemas,\n} from \"./core/binder\";\n"],"mappings":"AAQA;AAAA,EACE;AAAA,OAKK;","names":[]}