@decocms/bindings 0.2.4-beta.4 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +3 -3
  2. package/package.json +9 -35
  3. package/src/core/binder.ts +241 -0
  4. package/src/core/client/README.md +3 -0
  5. package/{dist/core/client/http-client-transport.js → src/core/client/http-client-transport.ts} +24 -12
  6. package/src/core/client/index.ts +1 -0
  7. package/src/core/client/mcp-client.ts +149 -0
  8. package/src/core/client/mcp.ts +93 -0
  9. package/src/core/client/proxy.ts +151 -0
  10. package/src/core/connection.ts +38 -0
  11. package/src/core/subset.ts +514 -0
  12. package/src/index.ts +15 -0
  13. package/src/well-known/agent.ts +60 -0
  14. package/src/well-known/collections.ts +416 -0
  15. package/src/well-known/language-model.ts +383 -0
  16. package/test/index.test.ts +942 -0
  17. package/tsconfig.json +11 -0
  18. package/vitest.config.ts +8 -0
  19. package/dist/core/binder.d.ts +0 -3
  20. package/dist/core/binder.js +0 -81
  21. package/dist/core/binder.js.map +0 -1
  22. package/dist/core/client/http-client-transport.d.ts +0 -12
  23. package/dist/core/client/http-client-transport.js.map +0 -1
  24. package/dist/core/client/index.d.ts +0 -3
  25. package/dist/core/client/index.js +0 -5
  26. package/dist/core/client/index.js.map +0 -1
  27. package/dist/core/client/mcp-client.d.ts +0 -233
  28. package/dist/core/client/mcp-client.js +0 -99
  29. package/dist/core/client/mcp-client.js.map +0 -1
  30. package/dist/core/client/mcp.d.ts +0 -3
  31. package/dist/core/client/mcp.js +0 -29
  32. package/dist/core/client/mcp.js.map +0 -1
  33. package/dist/core/client/proxy.d.ts +0 -10
  34. package/dist/core/client/proxy.js +0 -104
  35. package/dist/core/client/proxy.js.map +0 -1
  36. package/dist/core/connection.d.ts +0 -30
  37. package/dist/core/connection.js +0 -1
  38. package/dist/core/connection.js.map +0 -1
  39. package/dist/core/subset.d.ts +0 -17
  40. package/dist/core/subset.js +0 -321
  41. package/dist/core/subset.js.map +0 -1
  42. package/dist/index-D0aUdNls.d.ts +0 -153
  43. package/dist/index.d.ts +0 -3
  44. package/dist/index.js +0 -7
  45. package/dist/index.js.map +0 -1
  46. package/dist/well-known/agent.d.ts +0 -903
  47. package/dist/well-known/agent.js +0 -27
  48. package/dist/well-known/agent.js.map +0 -1
  49. package/dist/well-known/collections.d.ts +0 -537
  50. package/dist/well-known/collections.js +0 -134
  51. package/dist/well-known/collections.js.map +0 -1
  52. package/dist/well-known/language-model.d.ts +0 -2836
  53. package/dist/well-known/language-model.js +0 -209
  54. package/dist/well-known/language-model.js.map +0 -1
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Agents Well-Known Binding
3
+ *
4
+ * Defines the interface for AI agent providers.
5
+ * Any MCP that implements this binding can provide configurable AI agents
6
+ * with custom instructions and tool access controls.
7
+ *
8
+ * This binding uses collection bindings for LIST and GET operations (read-only).
9
+ */
10
+
11
+ import { z } from "zod";
12
+ import type { Binder } from "../core/binder";
13
+ import {
14
+ BaseCollectionEntitySchema,
15
+ createCollectionBindings,
16
+ } from "./collections";
17
+
18
+ /**
19
+ * Agent entity schema for AI agents
20
+ * Extends BaseCollectionEntitySchema with agent-specific fields
21
+ * Base schema already includes: id, title, created_at, updated_at, created_by, updated_by
22
+ */
23
+ export const AgentSchema = BaseCollectionEntitySchema.extend({
24
+ // Agent-specific fields
25
+ description: z.string().describe("Brief description of the agent's purpose"),
26
+ instructions: z
27
+ .string()
28
+ .describe("System instructions that define the agent's behavior"),
29
+ tool_set: z
30
+ .record(z.string(), z.array(z.string()))
31
+ .describe(
32
+ "Map of connection IDs to arrays of allowed tool names for this agent",
33
+ ),
34
+ avatar: z.string().url().describe("URL to the agent's avatar image"),
35
+ });
36
+
37
+ /**
38
+ * AGENT Collection Binding
39
+ *
40
+ * Collection bindings for agents (read-only).
41
+ * Provides LIST and GET operations for AI agents.
42
+ */
43
+ export const AGENTS_COLLECTION_BINDING = createCollectionBindings(
44
+ "agent",
45
+ AgentSchema,
46
+ );
47
+
48
+ /**
49
+ * AGENTS Binding
50
+ *
51
+ * Defines the interface for AI agent providers.
52
+ * Any MCP that implements this binding can provide configurable AI agents.
53
+ *
54
+ * Required tools:
55
+ * - COLLECTION_AGENT_LIST: List available AI agents with their configurations
56
+ * - COLLECTION_AGENT_GET: Get a single agent by ID (includes instructions and tool_set)
57
+ */
58
+ export const AGENTS_BINDING = [
59
+ ...AGENTS_COLLECTION_BINDING,
60
+ ] as const satisfies Binder;
@@ -0,0 +1,416 @@
1
+ import { z } from "zod";
2
+ import type { ToolBinder } from "../core/binder";
3
+
4
+ /**
5
+ * Collection Bindings
6
+ *
7
+ * This module provides standardized tool bindings for Collections, representing
8
+ * SQL table-like structures with CRUD + Search operations compatible with TanStack DB.
9
+ *
10
+ * Key Features:
11
+ * - Generic collection bindings that work with any entity type
12
+ * - Standardized tool naming: `COLLECTION_{COLLECTION}_*`
13
+ * - Compatible with TanStack DB query-collection
14
+ * - Full TypeScript support with proper type constraints
15
+ * - Support for filtering, sorting, and pagination
16
+ * - Simple id and title fields for human-readable identification
17
+ */
18
+
19
+ /**
20
+ * Base schema for collection entities
21
+ * All collection entities must have an id, title, and audit trail fields
22
+ */
23
+ export const BaseCollectionEntitySchema = z.object({
24
+ id: z.string().describe("Unique identifier for the entity"),
25
+ title: z.string().describe("Human-readable title for the entity"),
26
+ created_at: z.string().datetime(),
27
+ updated_at: z.string().datetime(),
28
+ created_by: z.string().optional(),
29
+ updated_by: z.string().optional(),
30
+ });
31
+
32
+ /**
33
+ * Type helper for BaseCollectionEntitySchema
34
+ */
35
+ export type BaseCollectionEntitySchemaType = typeof BaseCollectionEntitySchema;
36
+
37
+ /**
38
+ * Comparison expression schema for filtering
39
+ */
40
+ const ComparisonExpressionSchema = z.object({
41
+ field: z.array(z.string()),
42
+ operator: z.enum(["eq", "gt", "gte", "lt", "lte", "in", "like", "contains"]),
43
+ value: z.unknown(),
44
+ });
45
+
46
+ /**
47
+ * Where expression schema for filtering
48
+ * Supports TanStack DB predicate push-down patterns
49
+ */
50
+ export const WhereExpressionSchema = z.union([
51
+ ComparisonExpressionSchema,
52
+ z.object({
53
+ operator: z.enum(["and", "or", "not"]),
54
+ conditions: z.array(ComparisonExpressionSchema),
55
+ }),
56
+ ]);
57
+
58
+ /**
59
+ * Where expression type for filtering
60
+ * Derived from WhereExpressionSchema
61
+ */
62
+ export type WhereExpression = z.infer<typeof WhereExpressionSchema>;
63
+
64
+ /**
65
+ * Order by expression for sorting
66
+ */
67
+ export const OrderByExpressionSchema = z.object({
68
+ field: z.array(z.string()),
69
+ direction: z.enum(["asc", "desc"]),
70
+ nulls: z.enum(["first", "last"]).optional(),
71
+ });
72
+
73
+ /**
74
+ * List/Query input schema for collections
75
+ * Compatible with TanStack DB LoadSubsetOptions
76
+ */
77
+ export const CollectionListInputSchema = z.object({
78
+ where: WhereExpressionSchema.optional().describe("Filter expression"),
79
+ orderBy: z
80
+ .array(OrderByExpressionSchema)
81
+ .optional()
82
+ .describe("Sort expressions"),
83
+ limit: z
84
+ .number()
85
+ .int()
86
+ .min(1)
87
+ .max(1000)
88
+ .optional()
89
+ .describe("Maximum number of items to return"),
90
+ offset: z
91
+ .number()
92
+ .int()
93
+ .min(0)
94
+ .optional()
95
+ .describe("Number of items to skip"),
96
+ });
97
+
98
+ /**
99
+ * Factory function to create list output schema for a specific collection type
100
+ */
101
+ export function createCollectionListOutputSchema<T extends z.ZodTypeAny>(
102
+ entitySchema: T,
103
+ ) {
104
+ return z.object({
105
+ items: z.array(entitySchema).describe("Array of collection items"),
106
+ totalCount: z
107
+ .number()
108
+ .int()
109
+ .min(0)
110
+ .optional()
111
+ .describe("Total number of matching items (if available)"),
112
+ hasMore: z
113
+ .boolean()
114
+ .optional()
115
+ .describe("Whether there are more items available"),
116
+ });
117
+ }
118
+
119
+ /**
120
+ * Get by ID input schema
121
+ */
122
+ export const CollectionGetInputSchema = z.object({
123
+ id: z.string().describe("ID of the entity to retrieve"),
124
+ });
125
+
126
+ /**
127
+ * Factory function to create get output schema
128
+ */
129
+ export function createCollectionGetOutputSchema<T extends z.ZodTypeAny>(
130
+ entitySchema: T,
131
+ ) {
132
+ return z.object({
133
+ item: entitySchema
134
+ .nullable()
135
+ .describe("The retrieved item, or null if not found"),
136
+ });
137
+ }
138
+
139
+ /**
140
+ * Factory function to create insert input schema
141
+ */
142
+ export function createCollectionInsertInputSchema<T extends z.ZodTypeAny>(
143
+ entitySchema: T,
144
+ ) {
145
+ // Remove id field since it may be auto-generated by the server
146
+ return z.object({
147
+ data: entitySchema.describe(
148
+ "Data for the new entity (id may be auto-generated)",
149
+ ),
150
+ });
151
+ }
152
+
153
+ /**
154
+ * Factory function to create insert output schema
155
+ */
156
+ export function createCollectionInsertOutputSchema<T extends z.ZodTypeAny>(
157
+ entitySchema: T,
158
+ ) {
159
+ return z.object({
160
+ item: entitySchema.describe("The created entity with generated id"),
161
+ });
162
+ }
163
+
164
+ /**
165
+ * Factory function to create update input schema
166
+ */
167
+ export function createCollectionUpdateInputSchema<T extends z.ZodTypeAny>(
168
+ entitySchema: T,
169
+ ) {
170
+ return z.object({
171
+ id: z.string().describe("ID of the entity to update"),
172
+ data: (entitySchema as unknown as z.AnyZodObject)
173
+ .partial()
174
+ .describe("Partial entity data to update"),
175
+ });
176
+ }
177
+
178
+ /**
179
+ * Factory function to create update output schema
180
+ */
181
+ export function createCollectionUpdateOutputSchema<T extends z.ZodTypeAny>(
182
+ entitySchema: T,
183
+ ) {
184
+ return z.object({
185
+ item: entitySchema.describe("The updated entity"),
186
+ });
187
+ }
188
+
189
+ /**
190
+ * Delete input schema
191
+ */
192
+ export const CollectionDeleteInputSchema = z.object({
193
+ id: z.string().describe("ID of the entity to delete"),
194
+ });
195
+
196
+ /**
197
+ * Factory function to create delete output schema
198
+ */
199
+ export function createCollectionDeleteOutputSchema<T extends z.ZodTypeAny>(
200
+ entitySchema: T,
201
+ ) {
202
+ return z.object({
203
+ item: entitySchema.describe("The deleted entity"),
204
+ });
205
+ }
206
+
207
+ /**
208
+ * Options for creating collection bindings
209
+ */
210
+ export interface CollectionBindingOptions {
211
+ /**
212
+ * If true, only LIST and GET operations will be included (read-only collection)
213
+ * @default false
214
+ */
215
+ readOnly?: boolean;
216
+ }
217
+
218
+ /**
219
+ * Creates generic collection bindings for a specific entity type
220
+ *
221
+ * This function generates standardized tool bindings that work with any collection/table
222
+ * by accepting a custom entity schema and collection name. The bindings provide:
223
+ * - COLLECTION_{NAME}_LIST - Query/search entities with filtering and sorting (required)
224
+ * - COLLECTION_{NAME}_GET - Get a single entity by ID (required)
225
+ * - COLLECTION_{NAME}_CREATE - Create a new entity (optional, excluded if readOnly=true)
226
+ * - COLLECTION_{NAME}_UPDATE - Update an existing entity (optional, excluded if readOnly=true)
227
+ * - COLLECTION_{NAME}_DELETE - Delete an entity (optional, excluded if readOnly=true)
228
+ *
229
+ * @param collectionName - The name of the collection/table (e.g., "users", "products", "orders")
230
+ * @param entitySchema - The Zod schema for the entity type (must extend BaseCollectionEntitySchema)
231
+ * @param options - Optional configuration for the collection bindings
232
+ * @returns Array of tool bindings for Collection CRUD + Query operations
233
+ *
234
+ * @example
235
+ * ```typescript
236
+ * const UserSchema = z.object({
237
+ * id: z.string(),
238
+ * title: z.string(),
239
+ * created_at: z.string().datetime(),
240
+ * updated_at: z.string().datetime(),
241
+ * created_by: z.string().optional(),
242
+ * updated_by: z.string().optional(),
243
+ * email: z.string().email(),
244
+ * });
245
+ *
246
+ * // Full CRUD collection
247
+ * const USER_COLLECTION_BINDING = createCollectionBindings("users", UserSchema);
248
+ *
249
+ * // Read-only collection (only LIST and GET)
250
+ * const READONLY_COLLECTION_BINDING = createCollectionBindings("products", ProductSchema, { readOnly: true });
251
+ * ```
252
+ */
253
+ export function createCollectionBindings<
254
+ TEntitySchema extends BaseCollectionEntitySchemaType,
255
+ TName extends string,
256
+ >(
257
+ collectionName: TName,
258
+ entitySchema: TEntitySchema,
259
+ options?: CollectionBindingOptions,
260
+ ) {
261
+ const upperName = collectionName.toUpperCase() as Uppercase<TName>;
262
+ const readOnly = options?.readOnly ?? false;
263
+
264
+ const bindings: CollectionBinding<TEntitySchema, Uppercase<TName>>[number][] =
265
+ [
266
+ {
267
+ name: `COLLECTION_${upperName}_LIST` as const,
268
+ inputSchema: CollectionListInputSchema,
269
+ outputSchema: createCollectionListOutputSchema(entitySchema),
270
+ },
271
+ {
272
+ name: `COLLECTION_${upperName}_GET` as const,
273
+ inputSchema: CollectionGetInputSchema,
274
+ outputSchema: createCollectionGetOutputSchema(entitySchema),
275
+ },
276
+ ];
277
+
278
+ // Only include mutation operations if not read-only
279
+ if (!readOnly) {
280
+ bindings.push(
281
+ {
282
+ name: `COLLECTION_${upperName}_CREATE` as const,
283
+ inputSchema: createCollectionInsertInputSchema(entitySchema),
284
+ outputSchema: createCollectionInsertOutputSchema(entitySchema),
285
+ opt: true,
286
+ },
287
+ {
288
+ name: `COLLECTION_${upperName}_UPDATE` as const,
289
+ inputSchema: createCollectionUpdateInputSchema(entitySchema),
290
+ outputSchema: createCollectionUpdateOutputSchema(entitySchema),
291
+ opt: true,
292
+ },
293
+ {
294
+ name: `COLLECTION_${upperName}_DELETE` as const,
295
+ inputSchema: CollectionDeleteInputSchema,
296
+ outputSchema: createCollectionDeleteOutputSchema(entitySchema),
297
+ opt: true,
298
+ },
299
+ );
300
+ }
301
+
302
+ return bindings satisfies readonly ToolBinder[];
303
+ }
304
+
305
+ export type ReadOnlyCollectionBinding<
306
+ TEntitySchema extends BaseCollectionEntitySchemaType,
307
+ TUpperName extends Uppercase<string> = Uppercase<string>,
308
+ > = [
309
+ {
310
+ name: `COLLECTION_${TUpperName}_LIST`;
311
+ inputSchema: typeof CollectionListInputSchema;
312
+ outputSchema: ReturnType<
313
+ typeof createCollectionListOutputSchema<TEntitySchema>
314
+ >;
315
+ },
316
+ {
317
+ name: `COLLECTION_${TUpperName}_GET`;
318
+ inputSchema: typeof CollectionGetInputSchema;
319
+ outputSchema: ReturnType<
320
+ typeof createCollectionGetOutputSchema<TEntitySchema>
321
+ >;
322
+ },
323
+ ];
324
+ /**
325
+ * Type helper to extract the collection binding type
326
+ */
327
+ export type CollectionBinding<
328
+ TEntitySchema extends BaseCollectionEntitySchemaType,
329
+ TUpperName extends Uppercase<string> = Uppercase<string>,
330
+ > = [
331
+ ...ReadOnlyCollectionBinding<TEntitySchema, TUpperName>,
332
+ {
333
+ name: `COLLECTION_${TUpperName}_CREATE`;
334
+ inputSchema: ReturnType<
335
+ typeof createCollectionInsertInputSchema<TEntitySchema>
336
+ >;
337
+ outputSchema: ReturnType<
338
+ typeof createCollectionInsertOutputSchema<TEntitySchema>
339
+ >;
340
+ opt: true;
341
+ },
342
+ {
343
+ name: `COLLECTION_${TUpperName}_UPDATE`;
344
+ inputSchema: ReturnType<
345
+ typeof createCollectionUpdateInputSchema<TEntitySchema>
346
+ >;
347
+ outputSchema: ReturnType<
348
+ typeof createCollectionUpdateOutputSchema<TEntitySchema>
349
+ >;
350
+ opt: true;
351
+ },
352
+ {
353
+ name: `COLLECTION_${TUpperName}_DELETE`;
354
+ inputSchema: typeof CollectionDeleteInputSchema;
355
+ outputSchema: ReturnType<
356
+ typeof createCollectionDeleteOutputSchema<TEntitySchema>
357
+ >;
358
+ opt: true;
359
+ },
360
+ ];
361
+
362
+ /**
363
+ * Type helper to extract tool names from a collection binding
364
+ */
365
+ export type CollectionTools<
366
+ TEntitySchema extends BaseCollectionEntitySchemaType,
367
+ TUpperName extends Uppercase<string> = Uppercase<string>,
368
+ > = CollectionBinding<TEntitySchema, TUpperName>[number]["name"];
369
+
370
+ // Export types for TypeScript usage
371
+ export type CollectionListInput = z.infer<typeof CollectionListInputSchema>;
372
+ export type CollectionGetInput = z.infer<typeof CollectionGetInputSchema>;
373
+ export type CollectionDeleteInput = z.infer<typeof CollectionDeleteInputSchema>;
374
+ export type OrderByExpression = z.infer<typeof OrderByExpressionSchema>;
375
+
376
+ /**
377
+ * Type helper for list output with generic item type
378
+ */
379
+ export type CollectionListOutput<T> = {
380
+ items: T[];
381
+ totalCount?: number;
382
+ hasMore?: boolean;
383
+ };
384
+
385
+ /**
386
+ * Type helper for get output with generic item type
387
+ */
388
+ export type CollectionGetOutput<T> = {
389
+ item: T | null;
390
+ };
391
+
392
+ /**
393
+ * Type helper for insert output with generic item type
394
+ */
395
+ export type CollectionInsertOutput<T> = {
396
+ item: T;
397
+ };
398
+
399
+ /**
400
+ * Type helper for update output with generic item type
401
+ */
402
+ export type CollectionUpdateOutput<T> = {
403
+ item: T;
404
+ };
405
+
406
+ /**
407
+ * Type helper for delete output with generic item type
408
+ */
409
+ export type CollectionDeleteOutput<T> = {
410
+ item: T;
411
+ };
412
+
413
+ /**
414
+ * Base collection entity type - inferred from BaseCollectionEntitySchema
415
+ */
416
+ export type BaseCollectionEntity = z.infer<typeof BaseCollectionEntitySchema>;