@famgia/omnify-mcp 0.0.2
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 +157 -0
- package/dist/index.cjs +693 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +675 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,693 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
25
|
+
|
|
26
|
+
// src/index.ts
|
|
27
|
+
var import_server = require("@modelcontextprotocol/sdk/server/index.js");
|
|
28
|
+
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
29
|
+
var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
30
|
+
var import_zod = require("zod");
|
|
31
|
+
var yaml = __toESM(require("yaml"), 1);
|
|
32
|
+
var PropertyTypeEnum = import_zod.z.enum([
|
|
33
|
+
"String",
|
|
34
|
+
"Int",
|
|
35
|
+
"BigInt",
|
|
36
|
+
"Float",
|
|
37
|
+
"Decimal",
|
|
38
|
+
"Boolean",
|
|
39
|
+
"Text",
|
|
40
|
+
"LongText",
|
|
41
|
+
"Date",
|
|
42
|
+
"Time",
|
|
43
|
+
"Timestamp",
|
|
44
|
+
"Json",
|
|
45
|
+
"Email",
|
|
46
|
+
"Password",
|
|
47
|
+
"File",
|
|
48
|
+
"Point",
|
|
49
|
+
"Coordinates",
|
|
50
|
+
"Enum",
|
|
51
|
+
"EnumRef",
|
|
52
|
+
"Association"
|
|
53
|
+
]);
|
|
54
|
+
var RelationTypeEnum = import_zod.z.enum([
|
|
55
|
+
"OneToOne",
|
|
56
|
+
"OneToMany",
|
|
57
|
+
"ManyToOne",
|
|
58
|
+
"ManyToMany",
|
|
59
|
+
"MorphTo",
|
|
60
|
+
"MorphOne",
|
|
61
|
+
"MorphMany",
|
|
62
|
+
"MorphToMany",
|
|
63
|
+
"MorphedByMany"
|
|
64
|
+
]);
|
|
65
|
+
var ReferentialActionEnum = import_zod.z.enum([
|
|
66
|
+
"CASCADE",
|
|
67
|
+
"SET NULL",
|
|
68
|
+
"SET DEFAULT",
|
|
69
|
+
"RESTRICT",
|
|
70
|
+
"NO ACTION"
|
|
71
|
+
]);
|
|
72
|
+
var LocalizedStringSchema = import_zod.z.union([
|
|
73
|
+
import_zod.z.string(),
|
|
74
|
+
import_zod.z.record(import_zod.z.string())
|
|
75
|
+
]);
|
|
76
|
+
var CreateSchemaInputSchema = import_zod.z.object({
|
|
77
|
+
name: import_zod.z.string().describe("Schema name in PascalCase (e.g., User, BlogPost)"),
|
|
78
|
+
kind: import_zod.z.enum(["object", "enum"]).default("object").describe("Schema kind"),
|
|
79
|
+
displayName: LocalizedStringSchema.optional().describe("Human-readable name (string or locale map)"),
|
|
80
|
+
group: import_zod.z.string().optional().describe("Schema group for organization"),
|
|
81
|
+
properties: import_zod.z.record(import_zod.z.object({
|
|
82
|
+
type: PropertyTypeEnum,
|
|
83
|
+
displayName: LocalizedStringSchema.optional(),
|
|
84
|
+
nullable: import_zod.z.boolean().optional(),
|
|
85
|
+
unique: import_zod.z.boolean().optional(),
|
|
86
|
+
default: import_zod.z.unknown().optional(),
|
|
87
|
+
length: import_zod.z.number().optional(),
|
|
88
|
+
unsigned: import_zod.z.boolean().optional(),
|
|
89
|
+
precision: import_zod.z.number().optional(),
|
|
90
|
+
scale: import_zod.z.number().optional(),
|
|
91
|
+
enum: import_zod.z.union([import_zod.z.string(), import_zod.z.array(import_zod.z.unknown())]).optional(),
|
|
92
|
+
relation: RelationTypeEnum.optional(),
|
|
93
|
+
target: import_zod.z.string().optional(),
|
|
94
|
+
onDelete: ReferentialActionEnum.optional(),
|
|
95
|
+
joinTable: import_zod.z.string().optional(),
|
|
96
|
+
multiple: import_zod.z.boolean().optional()
|
|
97
|
+
})).optional(),
|
|
98
|
+
values: import_zod.z.array(import_zod.z.union([
|
|
99
|
+
import_zod.z.string(),
|
|
100
|
+
import_zod.z.object({
|
|
101
|
+
value: import_zod.z.string(),
|
|
102
|
+
label: LocalizedStringSchema.optional()
|
|
103
|
+
})
|
|
104
|
+
])).optional().describe("Enum values (only for kind: enum)"),
|
|
105
|
+
options: import_zod.z.object({
|
|
106
|
+
softDelete: import_zod.z.boolean().optional(),
|
|
107
|
+
timestamps: import_zod.z.boolean().optional(),
|
|
108
|
+
authenticatable: import_zod.z.boolean().optional(),
|
|
109
|
+
tableName: import_zod.z.string().optional(),
|
|
110
|
+
idType: import_zod.z.enum(["BigInt", "Int", "Uuid", "String"]).optional()
|
|
111
|
+
}).optional()
|
|
112
|
+
});
|
|
113
|
+
function getPropertyTypes() {
|
|
114
|
+
return `# Omnify Property Types
|
|
115
|
+
|
|
116
|
+
## Primitive Types
|
|
117
|
+
- **String**: VARCHAR(255) - short text, use \`length\` for custom size
|
|
118
|
+
- **Int**: INTEGER - 32-bit integer
|
|
119
|
+
- **BigInt**: BIGINT - 64-bit integer (default for IDs)
|
|
120
|
+
- **Float**: FLOAT - floating point number
|
|
121
|
+
- **Decimal**: DECIMAL(precision, scale) - exact decimal, use for money
|
|
122
|
+
- **Boolean**: BOOLEAN - true/false
|
|
123
|
+
|
|
124
|
+
## Text Types
|
|
125
|
+
- **Text**: TEXT (~65KB) - medium text content
|
|
126
|
+
- **LongText**: LONGTEXT (~4GB) - large text content
|
|
127
|
+
|
|
128
|
+
## Date/Time Types
|
|
129
|
+
- **Date**: DATE - date only (YYYY-MM-DD)
|
|
130
|
+
- **Time**: TIME - time only (HH:MM:SS)
|
|
131
|
+
- **Timestamp**: TIMESTAMP - date and time
|
|
132
|
+
|
|
133
|
+
## Special Types
|
|
134
|
+
- **Email**: VARCHAR(255) - validated email format
|
|
135
|
+
- **Password**: VARCHAR(255) - hashed password (auto-hidden)
|
|
136
|
+
- **Json**: JSON - structured data
|
|
137
|
+
- **File**: Polymorphic file attachment
|
|
138
|
+
|
|
139
|
+
## Enum Types
|
|
140
|
+
- **Enum**: Inline enum values
|
|
141
|
+
- **EnumRef**: Reference to shared enum schema
|
|
142
|
+
|
|
143
|
+
## Association Types (Relations)
|
|
144
|
+
- **Association**: Relationship to another schema
|
|
145
|
+
- relation: OneToOne, OneToMany, ManyToOne, ManyToMany
|
|
146
|
+
- relation: MorphTo, MorphOne, MorphMany (polymorphic)
|
|
147
|
+
- target: Target schema name
|
|
148
|
+
- onDelete: CASCADE, SET NULL, RESTRICT
|
|
149
|
+
`;
|
|
150
|
+
}
|
|
151
|
+
function getRelationshipGuide() {
|
|
152
|
+
return `# Omnify Relationship Guide
|
|
153
|
+
|
|
154
|
+
## Standard Relations
|
|
155
|
+
|
|
156
|
+
### ManyToOne (belongs to)
|
|
157
|
+
Most common - creates foreign key column.
|
|
158
|
+
\`\`\`yaml
|
|
159
|
+
author:
|
|
160
|
+
type: Association
|
|
161
|
+
relation: ManyToOne
|
|
162
|
+
target: User
|
|
163
|
+
onDelete: CASCADE
|
|
164
|
+
\`\`\`
|
|
165
|
+
|
|
166
|
+
### OneToMany (has many)
|
|
167
|
+
Inverse of ManyToOne - no column created.
|
|
168
|
+
\`\`\`yaml
|
|
169
|
+
posts:
|
|
170
|
+
type: Association
|
|
171
|
+
relation: OneToMany
|
|
172
|
+
target: Post
|
|
173
|
+
\`\`\`
|
|
174
|
+
|
|
175
|
+
### ManyToMany
|
|
176
|
+
Creates pivot table automatically.
|
|
177
|
+
\`\`\`yaml
|
|
178
|
+
tags:
|
|
179
|
+
type: Association
|
|
180
|
+
relation: ManyToMany
|
|
181
|
+
target: Tag
|
|
182
|
+
joinTable: post_tags # optional custom name
|
|
183
|
+
\`\`\`
|
|
184
|
+
|
|
185
|
+
### OneToOne
|
|
186
|
+
Unique foreign key relationship.
|
|
187
|
+
\`\`\`yaml
|
|
188
|
+
profile:
|
|
189
|
+
type: Association
|
|
190
|
+
relation: OneToOne
|
|
191
|
+
target: UserProfile
|
|
192
|
+
\`\`\`
|
|
193
|
+
|
|
194
|
+
## Polymorphic Relations
|
|
195
|
+
|
|
196
|
+
### MorphTo (owning side)
|
|
197
|
+
Creates {name}_type and {name}_id columns.
|
|
198
|
+
\`\`\`yaml
|
|
199
|
+
commentable:
|
|
200
|
+
type: Association
|
|
201
|
+
relation: MorphTo
|
|
202
|
+
\`\`\`
|
|
203
|
+
|
|
204
|
+
### MorphMany (inverse side)
|
|
205
|
+
No columns - defines inverse relationship.
|
|
206
|
+
\`\`\`yaml
|
|
207
|
+
comments:
|
|
208
|
+
type: Association
|
|
209
|
+
relation: MorphMany
|
|
210
|
+
target: Comment
|
|
211
|
+
\`\`\`
|
|
212
|
+
`;
|
|
213
|
+
}
|
|
214
|
+
function getExampleSchemas() {
|
|
215
|
+
return `# Omnify Schema Examples
|
|
216
|
+
|
|
217
|
+
## User Schema (with authentication)
|
|
218
|
+
\`\`\`yaml
|
|
219
|
+
name: User
|
|
220
|
+
displayName:
|
|
221
|
+
ja: \u30E6\u30FC\u30B6\u30FC
|
|
222
|
+
en: User
|
|
223
|
+
options:
|
|
224
|
+
softDelete: true
|
|
225
|
+
authenticatable: true
|
|
226
|
+
properties:
|
|
227
|
+
name:
|
|
228
|
+
type: String
|
|
229
|
+
displayName:
|
|
230
|
+
ja: \u6C0F\u540D
|
|
231
|
+
en: Full Name
|
|
232
|
+
email:
|
|
233
|
+
type: Email
|
|
234
|
+
unique: true
|
|
235
|
+
displayName:
|
|
236
|
+
ja: \u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9
|
|
237
|
+
en: Email Address
|
|
238
|
+
password:
|
|
239
|
+
type: Password
|
|
240
|
+
posts:
|
|
241
|
+
type: Association
|
|
242
|
+
relation: OneToMany
|
|
243
|
+
target: Post
|
|
244
|
+
\`\`\`
|
|
245
|
+
|
|
246
|
+
## Post Schema (with relations)
|
|
247
|
+
\`\`\`yaml
|
|
248
|
+
name: Post
|
|
249
|
+
displayName:
|
|
250
|
+
ja: \u6295\u7A3F
|
|
251
|
+
en: Post
|
|
252
|
+
options:
|
|
253
|
+
softDelete: true
|
|
254
|
+
indexes:
|
|
255
|
+
- columns: [published_at]
|
|
256
|
+
- columns: [status, published_at]
|
|
257
|
+
properties:
|
|
258
|
+
title:
|
|
259
|
+
type: String
|
|
260
|
+
displayName:
|
|
261
|
+
ja: \u30BF\u30A4\u30C8\u30EB
|
|
262
|
+
en: Title
|
|
263
|
+
slug:
|
|
264
|
+
type: String
|
|
265
|
+
unique: true
|
|
266
|
+
content:
|
|
267
|
+
type: LongText
|
|
268
|
+
displayName:
|
|
269
|
+
ja: \u672C\u6587
|
|
270
|
+
en: Content
|
|
271
|
+
status:
|
|
272
|
+
type: EnumRef
|
|
273
|
+
enum: PostStatus
|
|
274
|
+
default: draft
|
|
275
|
+
published_at:
|
|
276
|
+
type: Timestamp
|
|
277
|
+
nullable: true
|
|
278
|
+
author:
|
|
279
|
+
type: Association
|
|
280
|
+
relation: ManyToOne
|
|
281
|
+
target: User
|
|
282
|
+
onDelete: CASCADE
|
|
283
|
+
category:
|
|
284
|
+
type: Association
|
|
285
|
+
relation: ManyToOne
|
|
286
|
+
target: Category
|
|
287
|
+
tags:
|
|
288
|
+
type: Association
|
|
289
|
+
relation: ManyToMany
|
|
290
|
+
target: Tag
|
|
291
|
+
joinTable: post_tags
|
|
292
|
+
comments:
|
|
293
|
+
type: Association
|
|
294
|
+
relation: MorphMany
|
|
295
|
+
target: Comment
|
|
296
|
+
\`\`\`
|
|
297
|
+
|
|
298
|
+
## Enum Schema
|
|
299
|
+
\`\`\`yaml
|
|
300
|
+
name: PostStatus
|
|
301
|
+
kind: enum
|
|
302
|
+
displayName:
|
|
303
|
+
ja: \u6295\u7A3F\u30B9\u30C6\u30FC\u30BF\u30B9
|
|
304
|
+
en: Post Status
|
|
305
|
+
values:
|
|
306
|
+
- value: draft
|
|
307
|
+
label:
|
|
308
|
+
ja: \u4E0B\u66F8\u304D
|
|
309
|
+
en: Draft
|
|
310
|
+
- value: pending
|
|
311
|
+
label:
|
|
312
|
+
ja: \u5BE9\u67FB\u4E2D
|
|
313
|
+
en: Pending Review
|
|
314
|
+
- value: published
|
|
315
|
+
label:
|
|
316
|
+
ja: \u516C\u958B\u6E08\u307F
|
|
317
|
+
en: Published
|
|
318
|
+
- value: archived
|
|
319
|
+
label:
|
|
320
|
+
ja: \u30A2\u30FC\u30AB\u30A4\u30D6
|
|
321
|
+
en: Archived
|
|
322
|
+
\`\`\`
|
|
323
|
+
|
|
324
|
+
## Category Schema (self-referencing)
|
|
325
|
+
\`\`\`yaml
|
|
326
|
+
name: Category
|
|
327
|
+
displayName:
|
|
328
|
+
ja: \u30AB\u30C6\u30B4\u30EA
|
|
329
|
+
en: Category
|
|
330
|
+
properties:
|
|
331
|
+
name:
|
|
332
|
+
type: String
|
|
333
|
+
length: 100
|
|
334
|
+
slug:
|
|
335
|
+
type: String
|
|
336
|
+
unique: true
|
|
337
|
+
description:
|
|
338
|
+
type: Text
|
|
339
|
+
nullable: true
|
|
340
|
+
parent:
|
|
341
|
+
type: Association
|
|
342
|
+
relation: ManyToOne
|
|
343
|
+
target: Category
|
|
344
|
+
nullable: true
|
|
345
|
+
children:
|
|
346
|
+
type: Association
|
|
347
|
+
relation: OneToMany
|
|
348
|
+
target: Category
|
|
349
|
+
posts:
|
|
350
|
+
type: Association
|
|
351
|
+
relation: OneToMany
|
|
352
|
+
target: Post
|
|
353
|
+
\`\`\`
|
|
354
|
+
`;
|
|
355
|
+
}
|
|
356
|
+
function createSchema(input) {
|
|
357
|
+
const schema = {
|
|
358
|
+
name: input.name
|
|
359
|
+
};
|
|
360
|
+
if (input.kind && input.kind !== "object") {
|
|
361
|
+
schema.kind = input.kind;
|
|
362
|
+
}
|
|
363
|
+
if (input.displayName) {
|
|
364
|
+
schema.displayName = input.displayName;
|
|
365
|
+
}
|
|
366
|
+
if (input.group) {
|
|
367
|
+
schema.group = input.group;
|
|
368
|
+
}
|
|
369
|
+
if (input.options && Object.keys(input.options).length > 0) {
|
|
370
|
+
schema.options = input.options;
|
|
371
|
+
}
|
|
372
|
+
if (input.properties && Object.keys(input.properties).length > 0) {
|
|
373
|
+
schema.properties = input.properties;
|
|
374
|
+
}
|
|
375
|
+
if (input.values && input.values.length > 0) {
|
|
376
|
+
schema.values = input.values;
|
|
377
|
+
}
|
|
378
|
+
return yaml.stringify(schema);
|
|
379
|
+
}
|
|
380
|
+
function validateSchemaYaml(yamlContent) {
|
|
381
|
+
const errors = [];
|
|
382
|
+
const warnings = [];
|
|
383
|
+
try {
|
|
384
|
+
const schema = yaml.parse(yamlContent);
|
|
385
|
+
if (!schema.name) {
|
|
386
|
+
errors.push("Missing required field: name");
|
|
387
|
+
}
|
|
388
|
+
if (schema.kind && !["object", "enum"].includes(schema.kind)) {
|
|
389
|
+
errors.push(`Invalid kind: ${schema.kind}. Must be 'object' or 'enum'`);
|
|
390
|
+
}
|
|
391
|
+
if (schema.kind === "enum") {
|
|
392
|
+
if (!schema.values || schema.values.length === 0) {
|
|
393
|
+
errors.push("Enum schema must have values array");
|
|
394
|
+
}
|
|
395
|
+
if (schema.properties && Object.keys(schema.properties).length > 0) {
|
|
396
|
+
warnings.push("Enum schemas should not have properties");
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (schema.kind !== "enum") {
|
|
400
|
+
if (schema.values && schema.values.length > 0) {
|
|
401
|
+
warnings.push("Object schemas should not have values (use kind: enum for enums)");
|
|
402
|
+
}
|
|
403
|
+
if (schema.properties) {
|
|
404
|
+
for (const [propName, propDef] of Object.entries(schema.properties)) {
|
|
405
|
+
const prop = propDef;
|
|
406
|
+
if (!prop.type) {
|
|
407
|
+
errors.push(`Property '${propName}' missing required field: type`);
|
|
408
|
+
}
|
|
409
|
+
if (prop.type === "Association") {
|
|
410
|
+
if (!prop.relation) {
|
|
411
|
+
errors.push(`Property '${propName}' (Association) missing required field: relation`);
|
|
412
|
+
}
|
|
413
|
+
if (prop.relation !== "MorphTo" && !prop.target) {
|
|
414
|
+
errors.push(`Property '${propName}' (Association) missing required field: target`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
if (prop.type === "EnumRef" && !prop.enum) {
|
|
418
|
+
errors.push(`Property '${propName}' (EnumRef) missing required field: enum`);
|
|
419
|
+
}
|
|
420
|
+
if (prop.type === "Enum" && !prop.enum) {
|
|
421
|
+
errors.push(`Property '${propName}' (Enum) missing required field: enum`);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return { valid: errors.length === 0, errors, warnings };
|
|
427
|
+
} catch (e) {
|
|
428
|
+
return {
|
|
429
|
+
valid: false,
|
|
430
|
+
errors: [`Invalid YAML: ${e instanceof Error ? e.message : "Unknown error"}`],
|
|
431
|
+
warnings: []
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
var server = new import_server.Server(
|
|
436
|
+
{
|
|
437
|
+
name: "omnify-mcp",
|
|
438
|
+
version: "0.0.1"
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
capabilities: {
|
|
442
|
+
tools: {},
|
|
443
|
+
resources: {}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
);
|
|
447
|
+
server.setRequestHandler(import_types.ListToolsRequestSchema, async () => {
|
|
448
|
+
return {
|
|
449
|
+
tools: [
|
|
450
|
+
{
|
|
451
|
+
name: "omnify_create_schema",
|
|
452
|
+
description: "Create an Omnify schema YAML file. Use this to generate database models with Laravel and TypeScript support.",
|
|
453
|
+
inputSchema: {
|
|
454
|
+
type: "object",
|
|
455
|
+
properties: {
|
|
456
|
+
name: {
|
|
457
|
+
type: "string",
|
|
458
|
+
description: "Schema name in PascalCase (e.g., User, BlogPost)"
|
|
459
|
+
},
|
|
460
|
+
kind: {
|
|
461
|
+
type: "string",
|
|
462
|
+
enum: ["object", "enum"],
|
|
463
|
+
default: "object",
|
|
464
|
+
description: "Schema kind - object for tables, enum for enumeration types"
|
|
465
|
+
},
|
|
466
|
+
displayName: {
|
|
467
|
+
oneOf: [
|
|
468
|
+
{ type: "string" },
|
|
469
|
+
{ type: "object", additionalProperties: { type: "string" } }
|
|
470
|
+
],
|
|
471
|
+
description: 'Human-readable name. Can be string or locale map like { ja: "\u65E5\u672C\u8A9E", en: "English" }'
|
|
472
|
+
},
|
|
473
|
+
group: {
|
|
474
|
+
type: "string",
|
|
475
|
+
description: "Schema group for organization (e.g., auth, blog, shop)"
|
|
476
|
+
},
|
|
477
|
+
properties: {
|
|
478
|
+
type: "object",
|
|
479
|
+
description: "Property definitions. Each property has type and optional modifiers.",
|
|
480
|
+
additionalProperties: {
|
|
481
|
+
type: "object",
|
|
482
|
+
properties: {
|
|
483
|
+
type: {
|
|
484
|
+
type: "string",
|
|
485
|
+
enum: ["String", "Int", "BigInt", "Float", "Decimal", "Boolean", "Text", "LongText", "Date", "Time", "Timestamp", "Json", "Email", "Password", "File", "Enum", "EnumRef", "Association"]
|
|
486
|
+
},
|
|
487
|
+
displayName: {
|
|
488
|
+
oneOf: [
|
|
489
|
+
{ type: "string" },
|
|
490
|
+
{ type: "object", additionalProperties: { type: "string" } }
|
|
491
|
+
]
|
|
492
|
+
},
|
|
493
|
+
nullable: { type: "boolean" },
|
|
494
|
+
unique: { type: "boolean" },
|
|
495
|
+
default: {},
|
|
496
|
+
length: { type: "number" },
|
|
497
|
+
enum: { oneOf: [{ type: "string" }, { type: "array" }] },
|
|
498
|
+
relation: { type: "string", enum: ["OneToOne", "OneToMany", "ManyToOne", "ManyToMany", "MorphTo", "MorphOne", "MorphMany"] },
|
|
499
|
+
target: { type: "string" },
|
|
500
|
+
onDelete: { type: "string", enum: ["CASCADE", "SET NULL", "RESTRICT"] },
|
|
501
|
+
joinTable: { type: "string" }
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
},
|
|
505
|
+
values: {
|
|
506
|
+
type: "array",
|
|
507
|
+
description: "Enum values (only for kind: enum)",
|
|
508
|
+
items: {
|
|
509
|
+
oneOf: [
|
|
510
|
+
{ type: "string" },
|
|
511
|
+
{ type: "object", properties: { value: { type: "string" }, label: {} } }
|
|
512
|
+
]
|
|
513
|
+
}
|
|
514
|
+
},
|
|
515
|
+
options: {
|
|
516
|
+
type: "object",
|
|
517
|
+
properties: {
|
|
518
|
+
softDelete: { type: "boolean", description: "Enable soft deletes" },
|
|
519
|
+
timestamps: { type: "boolean", description: "Add created_at/updated_at" },
|
|
520
|
+
authenticatable: { type: "boolean", description: "Enable for User model" },
|
|
521
|
+
tableName: { type: "string", description: "Custom table name" },
|
|
522
|
+
idType: { type: "string", enum: ["BigInt", "Int", "Uuid", "String"] }
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
},
|
|
526
|
+
required: ["name"]
|
|
527
|
+
}
|
|
528
|
+
},
|
|
529
|
+
{
|
|
530
|
+
name: "omnify_validate_schema",
|
|
531
|
+
description: "Validate an Omnify schema YAML content. Returns validation errors and warnings.",
|
|
532
|
+
inputSchema: {
|
|
533
|
+
type: "object",
|
|
534
|
+
properties: {
|
|
535
|
+
yaml_content: {
|
|
536
|
+
type: "string",
|
|
537
|
+
description: "YAML content to validate"
|
|
538
|
+
}
|
|
539
|
+
},
|
|
540
|
+
required: ["yaml_content"]
|
|
541
|
+
}
|
|
542
|
+
},
|
|
543
|
+
{
|
|
544
|
+
name: "omnify_get_types",
|
|
545
|
+
description: "Get documentation for all Omnify property types and their options.",
|
|
546
|
+
inputSchema: {
|
|
547
|
+
type: "object",
|
|
548
|
+
properties: {}
|
|
549
|
+
}
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
name: "omnify_get_relationships",
|
|
553
|
+
description: "Get documentation for Omnify relationship types (OneToMany, ManyToOne, ManyToMany, polymorphic, etc.)",
|
|
554
|
+
inputSchema: {
|
|
555
|
+
type: "object",
|
|
556
|
+
properties: {}
|
|
557
|
+
}
|
|
558
|
+
},
|
|
559
|
+
{
|
|
560
|
+
name: "omnify_get_examples",
|
|
561
|
+
description: "Get example Omnify schemas for common use cases (User, Post, Category, Enum)",
|
|
562
|
+
inputSchema: {
|
|
563
|
+
type: "object",
|
|
564
|
+
properties: {}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
]
|
|
568
|
+
};
|
|
569
|
+
});
|
|
570
|
+
server.setRequestHandler(import_types.CallToolRequestSchema, async (request) => {
|
|
571
|
+
const { name, arguments: args } = request.params;
|
|
572
|
+
switch (name) {
|
|
573
|
+
case "omnify_create_schema": {
|
|
574
|
+
try {
|
|
575
|
+
const input = CreateSchemaInputSchema.parse(args);
|
|
576
|
+
const yamlContent = createSchema(input);
|
|
577
|
+
return {
|
|
578
|
+
content: [
|
|
579
|
+
{
|
|
580
|
+
type: "text",
|
|
581
|
+
text: `# Generated Schema: ${input.name}
|
|
582
|
+
|
|
583
|
+
\`\`\`yaml
|
|
584
|
+
${yamlContent}\`\`\`
|
|
585
|
+
|
|
586
|
+
Save this to: schemas/${input.group || "default"}/${input.name}.yaml`
|
|
587
|
+
}
|
|
588
|
+
]
|
|
589
|
+
};
|
|
590
|
+
} catch (e) {
|
|
591
|
+
return {
|
|
592
|
+
content: [
|
|
593
|
+
{
|
|
594
|
+
type: "text",
|
|
595
|
+
text: `Error creating schema: ${e instanceof Error ? e.message : "Unknown error"}`
|
|
596
|
+
}
|
|
597
|
+
],
|
|
598
|
+
isError: true
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
case "omnify_validate_schema": {
|
|
603
|
+
const yamlContent = args.yaml_content;
|
|
604
|
+
const result = validateSchemaYaml(yamlContent);
|
|
605
|
+
let response = result.valid ? "\u2705 Schema is valid!\n\n" : "\u274C Schema has errors:\n\n";
|
|
606
|
+
if (result.errors.length > 0) {
|
|
607
|
+
response += "**Errors:**\n" + result.errors.map((e) => `- ${e}`).join("\n") + "\n\n";
|
|
608
|
+
}
|
|
609
|
+
if (result.warnings.length > 0) {
|
|
610
|
+
response += "**Warnings:**\n" + result.warnings.map((w) => `- ${w}`).join("\n");
|
|
611
|
+
}
|
|
612
|
+
return {
|
|
613
|
+
content: [{ type: "text", text: response }]
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
case "omnify_get_types": {
|
|
617
|
+
return {
|
|
618
|
+
content: [{ type: "text", text: getPropertyTypes() }]
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
case "omnify_get_relationships": {
|
|
622
|
+
return {
|
|
623
|
+
content: [{ type: "text", text: getRelationshipGuide() }]
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
case "omnify_get_examples": {
|
|
627
|
+
return {
|
|
628
|
+
content: [{ type: "text", text: getExampleSchemas() }]
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
default:
|
|
632
|
+
return {
|
|
633
|
+
content: [{ type: "text", text: `Unknown tool: ${name}` }],
|
|
634
|
+
isError: true
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
});
|
|
638
|
+
server.setRequestHandler(import_types.ListResourcesRequestSchema, async () => {
|
|
639
|
+
return {
|
|
640
|
+
resources: [
|
|
641
|
+
{
|
|
642
|
+
uri: "omnify://schema/json-schema",
|
|
643
|
+
name: "Omnify JSON Schema",
|
|
644
|
+
description: "JSON Schema for validating Omnify schema files",
|
|
645
|
+
mimeType: "application/json"
|
|
646
|
+
},
|
|
647
|
+
{
|
|
648
|
+
uri: "omnify://docs/types",
|
|
649
|
+
name: "Property Types Documentation",
|
|
650
|
+
description: "Documentation for all Omnify property types",
|
|
651
|
+
mimeType: "text/markdown"
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
uri: "omnify://docs/relationships",
|
|
655
|
+
name: "Relationships Documentation",
|
|
656
|
+
description: "Documentation for Omnify relationship types",
|
|
657
|
+
mimeType: "text/markdown"
|
|
658
|
+
},
|
|
659
|
+
{
|
|
660
|
+
uri: "omnify://examples/all",
|
|
661
|
+
name: "Schema Examples",
|
|
662
|
+
description: "Example schemas for common use cases",
|
|
663
|
+
mimeType: "text/markdown"
|
|
664
|
+
}
|
|
665
|
+
]
|
|
666
|
+
};
|
|
667
|
+
});
|
|
668
|
+
server.setRequestHandler(import_types.ReadResourceRequestSchema, async (request) => {
|
|
669
|
+
const { uri } = request.params;
|
|
670
|
+
switch (uri) {
|
|
671
|
+
case "omnify://docs/types":
|
|
672
|
+
return {
|
|
673
|
+
contents: [{ uri, mimeType: "text/markdown", text: getPropertyTypes() }]
|
|
674
|
+
};
|
|
675
|
+
case "omnify://docs/relationships":
|
|
676
|
+
return {
|
|
677
|
+
contents: [{ uri, mimeType: "text/markdown", text: getRelationshipGuide() }]
|
|
678
|
+
};
|
|
679
|
+
case "omnify://examples/all":
|
|
680
|
+
return {
|
|
681
|
+
contents: [{ uri, mimeType: "text/markdown", text: getExampleSchemas() }]
|
|
682
|
+
};
|
|
683
|
+
default:
|
|
684
|
+
throw new Error(`Unknown resource: ${uri}`);
|
|
685
|
+
}
|
|
686
|
+
});
|
|
687
|
+
async function main() {
|
|
688
|
+
const transport = new import_stdio.StdioServerTransport();
|
|
689
|
+
await server.connect(transport);
|
|
690
|
+
console.error("Omnify MCP Server running on stdio");
|
|
691
|
+
}
|
|
692
|
+
main().catch(console.error);
|
|
693
|
+
//# sourceMappingURL=index.cjs.map
|