@centrali-io/centrali-mcp 4.2.2 → 4.2.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.
@@ -184,28 +184,30 @@ function registerDescribeTools(server) {
184
184
  },
185
185
  property_shape: {
186
186
  name: "string — field name (e.g., 'email', 'totalAmount')",
187
- type: "string — the field data type (see field_types below)",
187
+ type: "string — one of: string, number, boolean, datetime, array, object, reference",
188
+ description: "string | null — optional human-readable description",
188
189
  required: "boolean — whether the field is mandatory",
189
- unique: "boolean — whether values must be unique across records",
190
- defaultValue: "any | null default value for new records",
191
- description: "string | null — field description",
192
- config: "object | null — type-specific configuration (e.g., min/max for numbers, options for select)",
190
+ nullable: "boolean — whether the field accepts null values",
191
+ isUnique: "boolean whether values must be unique across records",
192
+ immutable: "boolean — field cannot be changed after creation",
193
+ default: "any | null — default value for new records",
194
+ enum: "any[] | null — restrict to specific allowed values",
193
195
  },
194
196
  field_types: {
195
- text: "Short text string",
196
- long_text: "Multi-line text / rich text",
197
- number: "Numeric value (integer or decimal). Config: { min, max, precision }",
198
- boolean: "True/false toggle",
199
- date: "Date value (ISO 8601)",
200
- datetime: "Date and time value (ISO 8601 with time)",
201
- email: "Email address (validated format)",
202
- url: "URL (validated format)",
203
- select: "Single choice from predefined options. Config: { options: [{ label, value }] }",
204
- multi_select: "Multiple choices from predefined options. Config: { options: [{ label, value }] }",
205
- reference: "Foreign key to another collection. Config: { referenceSlug: 'other-collection-slug' }",
206
- file: "File attachment (stored in Azure Blob Storage)",
207
- json: "Arbitrary JSON object",
208
- auto_increment: "Auto-incrementing integer (read-only)",
197
+ string: "Text field. Options: minLength, maxLength, pattern (regex), renderAs ('textarea'|'secret'|'color'|'code'|'html'|'markdown'), enum (string[]), not (disallowed values), isSecret (boolean). Use enum for select-like behavior.",
198
+ number: "Numeric field (integer or decimal). Options: minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, enum (number[]), autoIncrement ({ startAt, incrementBy? }).",
199
+ boolean: "True/false toggle. Options: default (boolean), enum ([true]|[false]).",
200
+ datetime: "ISO 8601 date/time field. Options: earliestDate, latestDate, exclusiveEarliest, exclusiveLatest, default (ISO string), enum (ISO string[]).",
201
+ array: "Array of typed items. Required: items: { type: 'string'|'number'|'boolean'|'datetime'|'object' }. Options: minItems, maxItems, uniqueItems, itemSchema (PropertyDefinition[] when items.type='object').",
202
+ object: "Nested object. Options: properties (PropertyDefinition[]), requiredProperties (string[]), strictProperties (boolean — reject unknown fields).",
203
+ reference: "Foreign key to another collection. Required: target (collection recordSlug), relationship ('many-to-one'|'one-to-one'|'many-to-many'), onDelete ('restrict'|'cascade'|'set_null'). Options: targetField (default: 'id'), displayField, nullable (required if onDelete='set_null').",
204
+ },
205
+ examples: {
206
+ string_with_enum: '{ "name": "status", "type": "string", "required": true, "enum": ["active", "inactive", "archived"] }',
207
+ number_with_range: '{ "name": "price", "type": "number", "minimum": 0, "maximum": 10000 }',
208
+ reference: '{ "name": "categoryId", "type": "reference", "target": "categories", "relationship": "many-to-one", "onDelete": "restrict" }',
209
+ array_of_strings: '{ "name": "tags", "type": "array", "items": { "type": "string" } }',
210
+ nested_object: '{ "name": "address", "type": "object", "properties": [{ "name": "street", "type": "string" }, { "name": "city", "type": "string" }] }',
209
211
  },
210
212
  crud_tools: {
211
213
  create_collection: {
@@ -231,6 +233,10 @@ function registerDescribeTools(server) {
231
233
  "Use create_collection to define new data schemas with typed properties",
232
234
  "Properties array defines the fields — each needs at minimum a name and type",
233
235
  "Use schemaDiscoveryMode: 'flexible' to auto-add new fields when records are created",
236
+ "For enum/select behavior, use type 'string' with an 'enum' array — there is no 'select' type",
237
+ "For multi-line text, use type 'string' with renderAs: 'textarea'",
238
+ "For JSON blobs, use type 'object' with strictProperties: false",
239
+ "Property options go at the top level of the property object, NOT nested inside a 'config' key",
234
240
  ],
235
241
  }, null, 2),
236
242
  },
@@ -142,7 +142,7 @@ function registerCollectionTools(server, sdk) {
142
142
  properties: zod_1.z
143
143
  .array(zod_1.z.record(zod_1.z.string(), zod_1.z.any()))
144
144
  .optional()
145
- .describe("Array of property definitions. Each property has name, type, and optional config (required, unique, defaultValue, description, config)"),
145
+ .describe("Array of property definitions. Each property needs 'name' and 'type' (string|number|boolean|datetime|array|object|reference). Type-specific options go at the top level, NOT inside a 'config' key. Use describe_collections for full schema reference."),
146
146
  enableVersioning: zod_1.z.boolean().optional().describe("Enable record versioning (default: false)"),
147
147
  schemaDiscoveryMode: zod_1.z
148
148
  .enum(["strict", "flexible"])
@@ -191,7 +191,11 @@ function registerCollectionTools(server, sdk) {
191
191
  .describe("Updated array of property definitions (replaces existing properties)"),
192
192
  enableVersioning: zod_1.z.boolean().optional().describe("Enable or disable record versioning"),
193
193
  tags: zod_1.z.array(zod_1.z.string()).optional().describe("Updated tags"),
194
- defaultTtlSeconds: zod_1.z.number().nullable().optional().describe("Default TTL in seconds for new records. Set to null to clear."),
194
+ defaultTtlSeconds: zod_1.z
195
+ .number()
196
+ .nullable()
197
+ .optional()
198
+ .describe("Default TTL in seconds for new records. Set to null to clear."),
195
199
  }, (_a) => __awaiter(this, [_a], void 0, function* ({ collectionId, name, description, properties, enableVersioning, tags, defaultTtlSeconds }) {
196
200
  try {
197
201
  const input = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centrali-io/centrali-mcp",
3
- "version": "4.2.2",
3
+ "version": "4.2.3",
4
4
  "description": "Centrali MCP Server - AI assistant integration for Centrali workspaces",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",
@@ -201,32 +201,41 @@ export function registerDescribeTools(server: McpServer) {
201
201
  },
202
202
  property_shape: {
203
203
  name: "string — field name (e.g., 'email', 'totalAmount')",
204
- type: "string — the field data type (see field_types below)",
204
+ type: "string — one of: string, number, boolean, datetime, array, object, reference",
205
+ description: "string | null — optional human-readable description",
205
206
  required: "boolean — whether the field is mandatory",
206
- unique: "boolean — whether values must be unique across records",
207
- defaultValue: "any | null default value for new records",
208
- description: "string | null — field description",
209
- config:
210
- "object | null — type-specific configuration (e.g., min/max for numbers, options for select)",
207
+ nullable: "boolean — whether the field accepts null values",
208
+ isUnique: "boolean whether values must be unique across records",
209
+ immutable: "boolean — field cannot be changed after creation",
210
+ default: "any | null — default value for new records",
211
+ enum: "any[] | null — restrict to specific allowed values",
211
212
  },
212
213
  field_types: {
213
- text: "Short text string",
214
- long_text: "Multi-line text / rich text",
215
- number: "Numeric value (integer or decimal). Config: { min, max, precision }",
216
- boolean: "True/false toggle",
217
- date: "Date value (ISO 8601)",
218
- datetime: "Date and time value (ISO 8601 with time)",
219
- email: "Email address (validated format)",
220
- url: "URL (validated format)",
221
- select:
222
- "Single choice from predefined options. Config: { options: [{ label, value }] }",
223
- multi_select:
224
- "Multiple choices from predefined options. Config: { options: [{ label, value }] }",
214
+ string:
215
+ "Text field. Options: minLength, maxLength, pattern (regex), renderAs ('textarea'|'secret'|'color'|'code'|'html'|'markdown'), enum (string[]), not (disallowed values), isSecret (boolean). Use enum for select-like behavior.",
216
+ number:
217
+ "Numeric field (integer or decimal). Options: minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, enum (number[]), autoIncrement ({ startAt, incrementBy? }).",
218
+ boolean: "True/false toggle. Options: default (boolean), enum ([true]|[false]).",
219
+ datetime:
220
+ "ISO 8601 date/time field. Options: earliestDate, latestDate, exclusiveEarliest, exclusiveLatest, default (ISO string), enum (ISO string[]).",
221
+ array:
222
+ "Array of typed items. Required: items: { type: 'string'|'number'|'boolean'|'datetime'|'object' }. Options: minItems, maxItems, uniqueItems, itemSchema (PropertyDefinition[] when items.type='object').",
223
+ object:
224
+ "Nested object. Options: properties (PropertyDefinition[]), requiredProperties (string[]), strictProperties (boolean — reject unknown fields).",
225
225
  reference:
226
- "Foreign key to another collection. Config: { referenceSlug: 'other-collection-slug' }",
227
- file: "File attachment (stored in Azure Blob Storage)",
228
- json: "Arbitrary JSON object",
229
- auto_increment: "Auto-incrementing integer (read-only)",
226
+ "Foreign key to another collection. Required: target (collection recordSlug), relationship ('many-to-one'|'one-to-one'|'many-to-many'), onDelete ('restrict'|'cascade'|'set_null'). Options: targetField (default: 'id'), displayField, nullable (required if onDelete='set_null').",
227
+ },
228
+ examples: {
229
+ string_with_enum:
230
+ '{ "name": "status", "type": "string", "required": true, "enum": ["active", "inactive", "archived"] }',
231
+ number_with_range:
232
+ '{ "name": "price", "type": "number", "minimum": 0, "maximum": 10000 }',
233
+ reference:
234
+ '{ "name": "categoryId", "type": "reference", "target": "categories", "relationship": "many-to-one", "onDelete": "restrict" }',
235
+ array_of_strings:
236
+ '{ "name": "tags", "type": "array", "items": { "type": "string" } }',
237
+ nested_object:
238
+ '{ "name": "address", "type": "object", "properties": [{ "name": "street", "type": "string" }, { "name": "city", "type": "string" }] }',
230
239
  },
231
240
  crud_tools: {
232
241
  create_collection: {
@@ -252,6 +261,10 @@ export function registerDescribeTools(server: McpServer) {
252
261
  "Use create_collection to define new data schemas with typed properties",
253
262
  "Properties array defines the fields — each needs at minimum a name and type",
254
263
  "Use schemaDiscoveryMode: 'flexible' to auto-add new fields when records are created",
264
+ "For enum/select behavior, use type 'string' with an 'enum' array — there is no 'select' type",
265
+ "For multi-line text, use type 'string' with renderAs: 'textarea'",
266
+ "For JSON blobs, use type 'object' with strictProperties: false",
267
+ "Property options go at the top level of the property object, NOT nested inside a 'config' key",
255
268
  ],
256
269
  },
257
270
  null,
@@ -154,7 +154,9 @@ export function registerCollectionTools(server: McpServer, sdk: CentraliSDK) {
154
154
  properties: z
155
155
  .array(z.record(z.string(), z.any()))
156
156
  .optional()
157
- .describe("Array of property definitions. Each property has name, type, and optional config (required, unique, defaultValue, description, config)"),
157
+ .describe(
158
+ "Array of property definitions. Each property needs 'name' and 'type' (string|number|boolean|datetime|array|object|reference). Type-specific options go at the top level, NOT inside a 'config' key. Use describe_collections for full schema reference."
159
+ ),
158
160
  enableVersioning: z.boolean().optional().describe("Enable record versioning (default: false)"),
159
161
  schemaDiscoveryMode: z
160
162
  .enum(["strict", "flexible"])
@@ -170,7 +172,6 @@ export function registerCollectionTools(server: McpServer, sdk: CentraliSDK) {
170
172
  if (enableVersioning !== undefined) input.enableVersioning = enableVersioning;
171
173
  if (schemaDiscoveryMode !== undefined) input.schemaDiscoveryMode = schemaDiscoveryMode;
172
174
  if (tags !== undefined) input.tags = tags;
173
-
174
175
  const result = await sdk.collections.create(input as any);
175
176
  return {
176
177
  content: [
@@ -204,7 +205,11 @@ export function registerCollectionTools(server: McpServer, sdk: CentraliSDK) {
204
205
  .describe("Updated array of property definitions (replaces existing properties)"),
205
206
  enableVersioning: z.boolean().optional().describe("Enable or disable record versioning"),
206
207
  tags: z.array(z.string()).optional().describe("Updated tags"),
207
- defaultTtlSeconds: z.number().nullable().optional().describe("Default TTL in seconds for new records. Set to null to clear."),
208
+ defaultTtlSeconds: z
209
+ .number()
210
+ .nullable()
211
+ .optional()
212
+ .describe("Default TTL in seconds for new records. Set to null to clear."),
208
213
  },
209
214
  async ({ collectionId, name, description, properties, enableVersioning, tags, defaultTtlSeconds }) => {
210
215
  try {
@@ -215,7 +220,6 @@ export function registerCollectionTools(server: McpServer, sdk: CentraliSDK) {
215
220
  if (enableVersioning !== undefined) input.enableVersioning = enableVersioning;
216
221
  if (tags !== undefined) input.tags = tags;
217
222
  if (defaultTtlSeconds !== undefined) input.defaultTtlSeconds = defaultTtlSeconds;
218
-
219
223
  const result = await sdk.collections.update(collectionId, input as any);
220
224
  return {
221
225
  content: [