@reveldigital/mcp-graphql-proxy 2.1.0 → 2.2.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.
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +16 -0
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/index.js +567 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/types/schema.graphql +337 -27
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,kBAAkB;IACjC,2CAA2C;IAC3C,eAAe,EAAE,MAAM,CAAC;IACxB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,kBAAkB;IACjC,2CAA2C;IAC3C,eAAe,EAAE,MAAM,CAAC;IACxB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CA8hBxE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CA0HzE"}
|
|
@@ -247,6 +247,21 @@ Organizational folders for each resource type. All five tools take the same para
|
|
|
247
247
|
| \`remove_playlist_source\` | Remove a source from a playlist. Params: \`playlistId\`, \`sourceId\`. |
|
|
248
248
|
| \`reorder_playlist_sources\` | Reorder sources within a playlist. Params: \`playlistId\`, \`sourceIds\` (ordered array). |
|
|
249
249
|
|
|
250
|
+
### Template Management
|
|
251
|
+
Templates are screen layouts composed of **modules** (also called **zones** or **regions**) — rectangular areas that display content from a playlist. The terms "module" and "zone" are interchangeable. Module positions (\`left\`, \`top\`, \`width\`, \`height\`) are in pixels; \`sequence\` is the z-order (higher appears in front). Each module can carry **options** (key-value pairs) for type-specific settings (e.g., \`timezone\` for a Clock zone, \`location\` for a Weather zone).
|
|
252
|
+
|
|
253
|
+
| Tool | Description |
|
|
254
|
+
|------|-------------|
|
|
255
|
+
| \`update_template\` | Update a template's properties. Params: \`templateId\`, plus any of \`name?\`, \`groupId?\`, \`tags?\` (newline-delimited), \`script?\`, \`backColor?\` (e.g. \`#000000\`), \`width?\`, \`height?\`, \`orientation?\` (0=Landscape, 1=Portrait, 2=Landscape Reversed, 3=Portrait Reversed). |
|
|
256
|
+
| \`add_template_module\` | Add a new module/zone to a template. Params: \`templateId\`, \`module\` (object: \`name?\`, \`type?\`, \`left?\`, \`top?\`, \`width?\`, \`height?\`, \`playlistId?\`, \`sequence?\`). |
|
|
257
|
+
| \`update_template_module\` | Update a module within a template (partial). Params: \`templateId\`, \`moduleId\`, plus any of \`name?\`, \`type?\`, \`left?\`, \`top?\`, \`width?\`, \`height?\`, \`playlistId?\`, \`sequence?\`. |
|
|
258
|
+
| \`remove_template_module\` | Remove a module from a template. Params: \`templateId\`, \`moduleId\`. |
|
|
259
|
+
| \`reorder_template_modules\` | Reorder modules by z-order. Params: \`templateId\`, \`moduleSequences\` (array of \`{moduleId, sequence}\`). |
|
|
260
|
+
| \`batch_update_template_modules\` | Update multiple modules at once. Params: \`templateId\`, \`modules\` (array of \`{moduleId, ...partial fields}\`). Returns per-module success/failure counts. |
|
|
261
|
+
| \`set_module_options\` | Replace all options for a module. Params: \`templateId\`, \`moduleId\`, \`options\` (array of \`{name, value}\`). |
|
|
262
|
+
| \`upsert_module_option\` | Add or update a single option (matched by name). Params: \`templateId\`, \`moduleId\`, \`option\` (\`{name, value}\`). |
|
|
263
|
+
| \`remove_module_option\` | Remove an option by name. Params: \`templateId\`, \`moduleId\`, \`optionName\`. |
|
|
264
|
+
|
|
250
265
|
### Data Table Management
|
|
251
266
|
| Tool | Description |
|
|
252
267
|
|------|-------------|
|
|
@@ -615,6 +630,7 @@ Types: \`device\`, \`template\`, \`schedule\`, \`playlist\`, \`media\`, \`device
|
|
|
615
630
|
**Media**: \`create_media_from_url\`, \`update_media\`, \`approve_media\` (id), \`decline_media\` (id, reason?) — both reversible — \`delete_media\` (currently no-op)
|
|
616
631
|
**Playlists**: \`add_playlist_source\`, \`update_playlist_source\`, \`remove_playlist_source\`, \`reorder_playlist_sources\`
|
|
617
632
|
Playlist sources support optional \`conditions\` (array) to control when/where they play — e.g., \`DATE_RANGE\`, \`TIME_RANGE\`, \`DAYS_OF_WEEK\`, \`SPECIFIC_DEVICE\`, \`DEVICE_BY_GROUP\`. Each condition has \`type\`, optional \`operator\` (AND/OR/AND_NOT/OR_NOT), and \`value1\`–\`value4\`.
|
|
633
|
+
**Templates**: \`update_template\` (name, group, tags, dimensions, backColor, orientation, script), \`add_template_module\`, \`update_template_module\`, \`remove_template_module\`, \`reorder_template_modules\`, \`batch_update_template_modules\`, \`set_module_options\`, \`upsert_module_option\`, \`remove_module_option\`. Modules (aka zones) are rectangular content areas: \`left\`/\`top\`/\`width\`/\`height\` in px, \`sequence\` = z-order, \`playlistId\` = content; options are \`{name, value}\` key-value settings.
|
|
618
634
|
**Data Tables**: \`create_data_table\` (column types: STRING, NUMBER, BOOLEAN, DATE, SELECT, MEDIA, URL, RICHTEXT, TIME, HIDDEN), \`update_data_table\`, \`delete_data_table\`, \`create_data_table_row\`, \`update_data_table_row\` (supports \`eTag\` for optimistic concurrency), \`delete_data_table_row\`, \`batch_create_data_table_rows\`, \`batch_delete_data_table_rows\`, \`import_data_table_rows\` (CSV), \`reorder_data_table_rows\`, \`rollback_data_table_row\`. Row mutations return \`structuredValidationErrors\` on validation failure.
|
|
619
635
|
|
|
620
636
|
**Workflow**: Check permissions → describe action to user → get confirmation → execute → report result
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAA2B;IAC9D,MAAM,EAAE,eAAe,EAAE,QAAQ,GAAG,KAAK,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IAEnE,wCAAwC;IACxC,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,eAAe,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACjF,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACnF,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAErF,OAAO;;;mBAGU,eAAe;kBAChB,QAAQ;eACX,KAAK;mBACD,SAAS;kBACV,OAAO;mBACN,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,oBAAoB,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE
|
|
1
|
+
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1153,6 +1153,562 @@ mutation ReorderPlaylistSources($input: ReorderPlaylistSourcesInput) {
|
|
|
1153
1153
|
}
|
|
1154
1154
|
});
|
|
1155
1155
|
// ============================================================================
|
|
1156
|
+
// Tool: Update Template
|
|
1157
|
+
// ============================================================================
|
|
1158
|
+
server.tool('update_template', "Update a template's properties (name, group, tags, dimensions, colors, orientation, script). Only provided fields are changed. Example: AI adjusts template dimensions to optimize for a new display resolution.", {
|
|
1159
|
+
templateId: z.string().describe('The template ID to update'),
|
|
1160
|
+
name: z.string().optional().describe('Template name'),
|
|
1161
|
+
groupId: z.string().optional().describe('Group ID to assign the template to'),
|
|
1162
|
+
tags: z.string().optional().describe('Tags (newline-delimited values stored in the Description field)'),
|
|
1163
|
+
script: z.string().optional().describe('Template script for custom logic'),
|
|
1164
|
+
backColor: z.string().optional().describe("Background color (e.g., '#000000')"),
|
|
1165
|
+
width: z.number().optional().describe('Template width in pixels'),
|
|
1166
|
+
height: z.number().optional().describe('Template height in pixels'),
|
|
1167
|
+
orientation: z.number().optional().describe('Display orientation (0=Landscape, 1=Portrait, 2=Landscape Reversed, 3=Portrait Reversed)'),
|
|
1168
|
+
}, async (args) => {
|
|
1169
|
+
try {
|
|
1170
|
+
const mutation = `
|
|
1171
|
+
mutation UpdateTemplate($input: UpdateTemplateInput) {
|
|
1172
|
+
updateTemplate(input: $input) {
|
|
1173
|
+
success
|
|
1174
|
+
template {
|
|
1175
|
+
id
|
|
1176
|
+
name
|
|
1177
|
+
width
|
|
1178
|
+
height
|
|
1179
|
+
orientation
|
|
1180
|
+
modules {
|
|
1181
|
+
id
|
|
1182
|
+
name
|
|
1183
|
+
type
|
|
1184
|
+
left
|
|
1185
|
+
top
|
|
1186
|
+
width
|
|
1187
|
+
height
|
|
1188
|
+
playlistId
|
|
1189
|
+
sequence
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
error
|
|
1193
|
+
}
|
|
1194
|
+
}`;
|
|
1195
|
+
const input = { templateId: args.templateId };
|
|
1196
|
+
if (args.name !== undefined)
|
|
1197
|
+
input.name = args.name;
|
|
1198
|
+
if (args.groupId !== undefined)
|
|
1199
|
+
input.groupId = args.groupId;
|
|
1200
|
+
if (args.tags !== undefined)
|
|
1201
|
+
input.tags = args.tags;
|
|
1202
|
+
if (args.script !== undefined)
|
|
1203
|
+
input.script = args.script;
|
|
1204
|
+
if (args.backColor !== undefined)
|
|
1205
|
+
input.backColor = args.backColor;
|
|
1206
|
+
if (args.width !== undefined)
|
|
1207
|
+
input.width = args.width;
|
|
1208
|
+
if (args.height !== undefined)
|
|
1209
|
+
input.height = args.height;
|
|
1210
|
+
if (args.orientation !== undefined)
|
|
1211
|
+
input.orientation = args.orientation;
|
|
1212
|
+
const response = await graphqlClient.query(mutation, { input });
|
|
1213
|
+
if (response.errors && response.errors.length > 0) {
|
|
1214
|
+
const result = {
|
|
1215
|
+
success: false,
|
|
1216
|
+
error: response.errors.map((e) => e.message).join('; '),
|
|
1217
|
+
};
|
|
1218
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1219
|
+
}
|
|
1220
|
+
const result = {
|
|
1221
|
+
success: true,
|
|
1222
|
+
data: response.data,
|
|
1223
|
+
};
|
|
1224
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1225
|
+
}
|
|
1226
|
+
catch (error) {
|
|
1227
|
+
const result = {
|
|
1228
|
+
success: false,
|
|
1229
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
1230
|
+
};
|
|
1231
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1232
|
+
}
|
|
1233
|
+
});
|
|
1234
|
+
// ============================================================================
|
|
1235
|
+
// Tool: Add Template Module
|
|
1236
|
+
// ============================================================================
|
|
1237
|
+
server.tool('add_template_module', "Add a new module (zone/region) to a template. Modules define rectangular areas where content from a playlist is displayed. Example: AI adds a new weather module to show real-time conditions in the corner.", {
|
|
1238
|
+
templateId: z.string().describe('The template ID to add the module to'),
|
|
1239
|
+
module: z.object({
|
|
1240
|
+
name: z.string().optional().describe('Module/zone name'),
|
|
1241
|
+
type: z.string().optional().describe("Module/zone type (e.g., 'Playlist', 'Clock', 'Weather', 'Ticker', 'Web')"),
|
|
1242
|
+
left: z.number().optional().describe('Left position in pixels'),
|
|
1243
|
+
top: z.number().optional().describe('Top position in pixels'),
|
|
1244
|
+
width: z.number().optional().describe('Width in pixels'),
|
|
1245
|
+
height: z.number().optional().describe('Height in pixels'),
|
|
1246
|
+
playlistId: z.string().optional().describe('Playlist ID assigned to this module'),
|
|
1247
|
+
sequence: z.number().optional().describe('Z-order/sequence for overlapping modules (higher appears in front)'),
|
|
1248
|
+
}).describe('The module to add'),
|
|
1249
|
+
}, async (args) => {
|
|
1250
|
+
try {
|
|
1251
|
+
const mutation = `
|
|
1252
|
+
mutation AddTemplateModule($input: AddTemplateModuleInput) {
|
|
1253
|
+
addTemplateModule(input: $input) {
|
|
1254
|
+
success
|
|
1255
|
+
module {
|
|
1256
|
+
id
|
|
1257
|
+
name
|
|
1258
|
+
type
|
|
1259
|
+
left
|
|
1260
|
+
top
|
|
1261
|
+
width
|
|
1262
|
+
height
|
|
1263
|
+
playlistId
|
|
1264
|
+
sequence
|
|
1265
|
+
options {
|
|
1266
|
+
id
|
|
1267
|
+
name
|
|
1268
|
+
value
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
error
|
|
1272
|
+
}
|
|
1273
|
+
}`;
|
|
1274
|
+
const response = await graphqlClient.query(mutation, {
|
|
1275
|
+
input: {
|
|
1276
|
+
templateId: args.templateId,
|
|
1277
|
+
module: args.module,
|
|
1278
|
+
},
|
|
1279
|
+
});
|
|
1280
|
+
if (response.errors && response.errors.length > 0) {
|
|
1281
|
+
const result = {
|
|
1282
|
+
success: false,
|
|
1283
|
+
error: response.errors.map((e) => e.message).join('; '),
|
|
1284
|
+
};
|
|
1285
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1286
|
+
}
|
|
1287
|
+
const result = {
|
|
1288
|
+
success: true,
|
|
1289
|
+
data: response.data,
|
|
1290
|
+
};
|
|
1291
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1292
|
+
}
|
|
1293
|
+
catch (error) {
|
|
1294
|
+
const result = {
|
|
1295
|
+
success: false,
|
|
1296
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
1297
|
+
};
|
|
1298
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1299
|
+
}
|
|
1300
|
+
});
|
|
1301
|
+
// ============================================================================
|
|
1302
|
+
// Tool: Update Template Module
|
|
1303
|
+
// ============================================================================
|
|
1304
|
+
server.tool('update_template_module', 'Update a module (zone/region) within a template. Only provided fields are changed. Example: AI repositions a module based on engagement analytics, or changes the assigned playlist.', {
|
|
1305
|
+
templateId: z.string().describe('The template ID containing the module'),
|
|
1306
|
+
moduleId: z.string().describe('The module ID to update'),
|
|
1307
|
+
name: z.string().optional().describe('Module/zone name'),
|
|
1308
|
+
type: z.string().optional().describe("Module/zone type (e.g., 'Playlist', 'Clock', 'Weather', 'Ticker', 'Web')"),
|
|
1309
|
+
left: z.number().optional().describe('Left position in pixels'),
|
|
1310
|
+
top: z.number().optional().describe('Top position in pixels'),
|
|
1311
|
+
width: z.number().optional().describe('Width in pixels'),
|
|
1312
|
+
height: z.number().optional().describe('Height in pixels'),
|
|
1313
|
+
playlistId: z.string().optional().describe('Playlist ID assigned to this module'),
|
|
1314
|
+
sequence: z.number().optional().describe('Z-order/sequence for overlapping modules'),
|
|
1315
|
+
}, async (args) => {
|
|
1316
|
+
try {
|
|
1317
|
+
const mutation = `
|
|
1318
|
+
mutation UpdateTemplateModule($input: UpdateTemplateModuleInput) {
|
|
1319
|
+
updateTemplateModule(input: $input) {
|
|
1320
|
+
success
|
|
1321
|
+
module {
|
|
1322
|
+
id
|
|
1323
|
+
name
|
|
1324
|
+
type
|
|
1325
|
+
left
|
|
1326
|
+
top
|
|
1327
|
+
width
|
|
1328
|
+
height
|
|
1329
|
+
playlistId
|
|
1330
|
+
sequence
|
|
1331
|
+
options {
|
|
1332
|
+
id
|
|
1333
|
+
name
|
|
1334
|
+
value
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
error
|
|
1338
|
+
}
|
|
1339
|
+
}`;
|
|
1340
|
+
const input = {
|
|
1341
|
+
templateId: args.templateId,
|
|
1342
|
+
moduleId: args.moduleId,
|
|
1343
|
+
};
|
|
1344
|
+
if (args.name !== undefined)
|
|
1345
|
+
input.name = args.name;
|
|
1346
|
+
if (args.type !== undefined)
|
|
1347
|
+
input.type = args.type;
|
|
1348
|
+
if (args.left !== undefined)
|
|
1349
|
+
input.left = args.left;
|
|
1350
|
+
if (args.top !== undefined)
|
|
1351
|
+
input.top = args.top;
|
|
1352
|
+
if (args.width !== undefined)
|
|
1353
|
+
input.width = args.width;
|
|
1354
|
+
if (args.height !== undefined)
|
|
1355
|
+
input.height = args.height;
|
|
1356
|
+
if (args.playlistId !== undefined)
|
|
1357
|
+
input.playlistId = args.playlistId;
|
|
1358
|
+
if (args.sequence !== undefined)
|
|
1359
|
+
input.sequence = args.sequence;
|
|
1360
|
+
const response = await graphqlClient.query(mutation, { input });
|
|
1361
|
+
if (response.errors && response.errors.length > 0) {
|
|
1362
|
+
const result = {
|
|
1363
|
+
success: false,
|
|
1364
|
+
error: response.errors.map((e) => e.message).join('; '),
|
|
1365
|
+
};
|
|
1366
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1367
|
+
}
|
|
1368
|
+
const result = {
|
|
1369
|
+
success: true,
|
|
1370
|
+
data: response.data,
|
|
1371
|
+
};
|
|
1372
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1373
|
+
}
|
|
1374
|
+
catch (error) {
|
|
1375
|
+
const result = {
|
|
1376
|
+
success: false,
|
|
1377
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
1378
|
+
};
|
|
1379
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1380
|
+
}
|
|
1381
|
+
});
|
|
1382
|
+
// ============================================================================
|
|
1383
|
+
// Tool: Remove Template Module
|
|
1384
|
+
// ============================================================================
|
|
1385
|
+
server.tool('remove_template_module', 'Remove a module (zone/region) from a template by module ID. Example: AI removes an underperforming ad module to optimize content flow.', {
|
|
1386
|
+
templateId: z.string().describe('The template ID containing the module'),
|
|
1387
|
+
moduleId: z.string().describe('The module ID to remove'),
|
|
1388
|
+
}, async (args) => {
|
|
1389
|
+
try {
|
|
1390
|
+
const mutation = `
|
|
1391
|
+
mutation RemoveTemplateModule($input: RemoveTemplateModuleInput) {
|
|
1392
|
+
removeTemplateModule(input: $input) {
|
|
1393
|
+
success
|
|
1394
|
+
module {
|
|
1395
|
+
id
|
|
1396
|
+
name
|
|
1397
|
+
type
|
|
1398
|
+
}
|
|
1399
|
+
error
|
|
1400
|
+
}
|
|
1401
|
+
}`;
|
|
1402
|
+
const response = await graphqlClient.query(mutation, {
|
|
1403
|
+
input: {
|
|
1404
|
+
templateId: args.templateId,
|
|
1405
|
+
moduleId: args.moduleId,
|
|
1406
|
+
},
|
|
1407
|
+
});
|
|
1408
|
+
if (response.errors && response.errors.length > 0) {
|
|
1409
|
+
const result = {
|
|
1410
|
+
success: false,
|
|
1411
|
+
error: response.errors.map((e) => e.message).join('; '),
|
|
1412
|
+
};
|
|
1413
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1414
|
+
}
|
|
1415
|
+
const result = {
|
|
1416
|
+
success: true,
|
|
1417
|
+
data: response.data,
|
|
1418
|
+
};
|
|
1419
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1420
|
+
}
|
|
1421
|
+
catch (error) {
|
|
1422
|
+
const result = {
|
|
1423
|
+
success: false,
|
|
1424
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
1425
|
+
};
|
|
1426
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1427
|
+
}
|
|
1428
|
+
});
|
|
1429
|
+
// ============================================================================
|
|
1430
|
+
// Tool: Reorder Template Modules
|
|
1431
|
+
// ============================================================================
|
|
1432
|
+
server.tool('reorder_template_modules', 'Reorder modules (zones) within a template by updating their sequence/z-order. Higher sequence values appear in front. Example: AI reorders modules to bring important content to the front based on viewer engagement.', {
|
|
1433
|
+
templateId: z.string().describe('The template ID'),
|
|
1434
|
+
moduleSequences: z.array(z.object({
|
|
1435
|
+
moduleId: z.string().describe('The module ID'),
|
|
1436
|
+
sequence: z.number().describe('The new sequence/z-order value'),
|
|
1437
|
+
})).describe('List of module IDs with their new sequence numbers'),
|
|
1438
|
+
}, async (args) => {
|
|
1439
|
+
try {
|
|
1440
|
+
const mutation = `
|
|
1441
|
+
mutation ReorderTemplateModules($input: ReorderTemplateModulesInput) {
|
|
1442
|
+
reorderTemplateModules(input: $input) {
|
|
1443
|
+
success
|
|
1444
|
+
template {
|
|
1445
|
+
id
|
|
1446
|
+
name
|
|
1447
|
+
modules {
|
|
1448
|
+
id
|
|
1449
|
+
name
|
|
1450
|
+
type
|
|
1451
|
+
sequence
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
error
|
|
1455
|
+
}
|
|
1456
|
+
}`;
|
|
1457
|
+
const response = await graphqlClient.query(mutation, {
|
|
1458
|
+
input: {
|
|
1459
|
+
templateId: args.templateId,
|
|
1460
|
+
moduleSequences: args.moduleSequences,
|
|
1461
|
+
},
|
|
1462
|
+
});
|
|
1463
|
+
if (response.errors && response.errors.length > 0) {
|
|
1464
|
+
const result = {
|
|
1465
|
+
success: false,
|
|
1466
|
+
error: response.errors.map((e) => e.message).join('; '),
|
|
1467
|
+
};
|
|
1468
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1469
|
+
}
|
|
1470
|
+
const result = {
|
|
1471
|
+
success: true,
|
|
1472
|
+
data: response.data,
|
|
1473
|
+
};
|
|
1474
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1475
|
+
}
|
|
1476
|
+
catch (error) {
|
|
1477
|
+
const result = {
|
|
1478
|
+
success: false,
|
|
1479
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
1480
|
+
};
|
|
1481
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1482
|
+
}
|
|
1483
|
+
});
|
|
1484
|
+
// ============================================================================
|
|
1485
|
+
// Tool: Batch Update Template Modules
|
|
1486
|
+
// ============================================================================
|
|
1487
|
+
server.tool('batch_update_template_modules', 'Batch update multiple modules in a template at once. Each entry must include the moduleId; only provided fields are changed. Example: AI repositions all modules to create a new layout optimized for viewer attention.', {
|
|
1488
|
+
templateId: z.string().describe('The template ID'),
|
|
1489
|
+
modules: z.array(z.object({
|
|
1490
|
+
moduleId: z.string().describe('The module ID to update'),
|
|
1491
|
+
name: z.string().optional().describe('Module/zone name'),
|
|
1492
|
+
type: z.string().optional().describe('Module/zone type'),
|
|
1493
|
+
left: z.number().optional().describe('Left position in pixels'),
|
|
1494
|
+
top: z.number().optional().describe('Top position in pixels'),
|
|
1495
|
+
width: z.number().optional().describe('Width in pixels'),
|
|
1496
|
+
height: z.number().optional().describe('Height in pixels'),
|
|
1497
|
+
playlistId: z.string().optional().describe('Playlist ID assigned to this module'),
|
|
1498
|
+
sequence: z.number().optional().describe('Z-order/sequence'),
|
|
1499
|
+
})).describe('List of module updates to apply (each requires moduleId)'),
|
|
1500
|
+
}, async (args) => {
|
|
1501
|
+
try {
|
|
1502
|
+
const mutation = `
|
|
1503
|
+
mutation BatchUpdateTemplateModules($input: BatchUpdateTemplateModulesInput) {
|
|
1504
|
+
batchUpdateTemplateModules(input: $input) {
|
|
1505
|
+
totalModules
|
|
1506
|
+
successCount
|
|
1507
|
+
failureCount
|
|
1508
|
+
results {
|
|
1509
|
+
success
|
|
1510
|
+
module {
|
|
1511
|
+
id
|
|
1512
|
+
name
|
|
1513
|
+
type
|
|
1514
|
+
left
|
|
1515
|
+
top
|
|
1516
|
+
width
|
|
1517
|
+
height
|
|
1518
|
+
playlistId
|
|
1519
|
+
sequence
|
|
1520
|
+
}
|
|
1521
|
+
error
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
}`;
|
|
1525
|
+
const modules = args.modules.map((m) => ({ ...m, templateId: args.templateId }));
|
|
1526
|
+
const response = await graphqlClient.query(mutation, {
|
|
1527
|
+
input: {
|
|
1528
|
+
templateId: args.templateId,
|
|
1529
|
+
modules,
|
|
1530
|
+
},
|
|
1531
|
+
});
|
|
1532
|
+
if (response.errors && response.errors.length > 0) {
|
|
1533
|
+
const result = {
|
|
1534
|
+
success: false,
|
|
1535
|
+
error: response.errors.map((e) => e.message).join('; '),
|
|
1536
|
+
};
|
|
1537
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1538
|
+
}
|
|
1539
|
+
const result = {
|
|
1540
|
+
success: true,
|
|
1541
|
+
data: response.data,
|
|
1542
|
+
};
|
|
1543
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1544
|
+
}
|
|
1545
|
+
catch (error) {
|
|
1546
|
+
const result = {
|
|
1547
|
+
success: false,
|
|
1548
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
1549
|
+
};
|
|
1550
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1551
|
+
}
|
|
1552
|
+
});
|
|
1553
|
+
// ============================================================================
|
|
1554
|
+
// Tool: Set Module Options
|
|
1555
|
+
// ============================================================================
|
|
1556
|
+
server.tool('set_module_options', 'Set all configuration options for a module/zone (replaces existing options). Options are key-value pairs storing type-specific settings. Example: AI configures a weather module with location, units, and API key settings.', {
|
|
1557
|
+
templateId: z.string().describe('The template ID'),
|
|
1558
|
+
moduleId: z.string().describe('The module ID'),
|
|
1559
|
+
options: z.array(z.object({
|
|
1560
|
+
name: z.string().describe("Option name/key (e.g., 'timezone', 'location', 'url')"),
|
|
1561
|
+
value: z.string().describe('Option value (string representation, parsed by option type)'),
|
|
1562
|
+
})).describe('List of options to set (replaces all existing options)'),
|
|
1563
|
+
}, async (args) => {
|
|
1564
|
+
try {
|
|
1565
|
+
const mutation = `
|
|
1566
|
+
mutation SetModuleOptions($input: SetModuleOptionsInput) {
|
|
1567
|
+
setModuleOptions(input: $input) {
|
|
1568
|
+
success
|
|
1569
|
+
module {
|
|
1570
|
+
id
|
|
1571
|
+
name
|
|
1572
|
+
type
|
|
1573
|
+
options {
|
|
1574
|
+
id
|
|
1575
|
+
name
|
|
1576
|
+
value
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
error
|
|
1580
|
+
}
|
|
1581
|
+
}`;
|
|
1582
|
+
const response = await graphqlClient.query(mutation, {
|
|
1583
|
+
input: {
|
|
1584
|
+
templateId: args.templateId,
|
|
1585
|
+
moduleId: args.moduleId,
|
|
1586
|
+
options: args.options,
|
|
1587
|
+
},
|
|
1588
|
+
});
|
|
1589
|
+
if (response.errors && response.errors.length > 0) {
|
|
1590
|
+
const result = {
|
|
1591
|
+
success: false,
|
|
1592
|
+
error: response.errors.map((e) => e.message).join('; '),
|
|
1593
|
+
};
|
|
1594
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1595
|
+
}
|
|
1596
|
+
const result = {
|
|
1597
|
+
success: true,
|
|
1598
|
+
data: response.data,
|
|
1599
|
+
};
|
|
1600
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1601
|
+
}
|
|
1602
|
+
catch (error) {
|
|
1603
|
+
const result = {
|
|
1604
|
+
success: false,
|
|
1605
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
1606
|
+
};
|
|
1607
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1608
|
+
}
|
|
1609
|
+
});
|
|
1610
|
+
// ============================================================================
|
|
1611
|
+
// Tool: Upsert Module Option
|
|
1612
|
+
// ============================================================================
|
|
1613
|
+
server.tool('upsert_module_option', 'Add or update a single module/zone option (matched by name). Example: AI updates the refresh interval for a web module.', {
|
|
1614
|
+
templateId: z.string().describe('The template ID'),
|
|
1615
|
+
moduleId: z.string().describe('The module ID'),
|
|
1616
|
+
option: z.object({
|
|
1617
|
+
name: z.string().describe("Option name/key (e.g., 'timezone', 'location', 'url')"),
|
|
1618
|
+
value: z.string().describe('Option value (string representation, parsed by option type)'),
|
|
1619
|
+
}).describe('The option to create or update (matched by name)'),
|
|
1620
|
+
}, async (args) => {
|
|
1621
|
+
try {
|
|
1622
|
+
const mutation = `
|
|
1623
|
+
mutation UpsertModuleOption($input: UpsertModuleOptionInput) {
|
|
1624
|
+
upsertModuleOption(input: $input) {
|
|
1625
|
+
success
|
|
1626
|
+
option {
|
|
1627
|
+
id
|
|
1628
|
+
name
|
|
1629
|
+
value
|
|
1630
|
+
}
|
|
1631
|
+
error
|
|
1632
|
+
}
|
|
1633
|
+
}`;
|
|
1634
|
+
const response = await graphqlClient.query(mutation, {
|
|
1635
|
+
input: {
|
|
1636
|
+
templateId: args.templateId,
|
|
1637
|
+
moduleId: args.moduleId,
|
|
1638
|
+
option: args.option,
|
|
1639
|
+
},
|
|
1640
|
+
});
|
|
1641
|
+
if (response.errors && response.errors.length > 0) {
|
|
1642
|
+
const result = {
|
|
1643
|
+
success: false,
|
|
1644
|
+
error: response.errors.map((e) => e.message).join('; '),
|
|
1645
|
+
};
|
|
1646
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1647
|
+
}
|
|
1648
|
+
const result = {
|
|
1649
|
+
success: true,
|
|
1650
|
+
data: response.data,
|
|
1651
|
+
};
|
|
1652
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1653
|
+
}
|
|
1654
|
+
catch (error) {
|
|
1655
|
+
const result = {
|
|
1656
|
+
success: false,
|
|
1657
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
1658
|
+
};
|
|
1659
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1660
|
+
}
|
|
1661
|
+
});
|
|
1662
|
+
// ============================================================================
|
|
1663
|
+
// Tool: Remove Module Option
|
|
1664
|
+
// ============================================================================
|
|
1665
|
+
server.tool('remove_module_option', 'Remove a module/zone option by name. Example: AI removes an outdated configuration setting from a module.', {
|
|
1666
|
+
templateId: z.string().describe('The template ID'),
|
|
1667
|
+
moduleId: z.string().describe('The module ID'),
|
|
1668
|
+
optionName: z.string().describe('The option name to remove'),
|
|
1669
|
+
}, async (args) => {
|
|
1670
|
+
try {
|
|
1671
|
+
const mutation = `
|
|
1672
|
+
mutation RemoveModuleOption($input: RemoveModuleOptionInput) {
|
|
1673
|
+
removeModuleOption(input: $input) {
|
|
1674
|
+
success
|
|
1675
|
+
option {
|
|
1676
|
+
id
|
|
1677
|
+
name
|
|
1678
|
+
value
|
|
1679
|
+
}
|
|
1680
|
+
error
|
|
1681
|
+
}
|
|
1682
|
+
}`;
|
|
1683
|
+
const response = await graphqlClient.query(mutation, {
|
|
1684
|
+
input: {
|
|
1685
|
+
templateId: args.templateId,
|
|
1686
|
+
moduleId: args.moduleId,
|
|
1687
|
+
optionName: args.optionName,
|
|
1688
|
+
},
|
|
1689
|
+
});
|
|
1690
|
+
if (response.errors && response.errors.length > 0) {
|
|
1691
|
+
const result = {
|
|
1692
|
+
success: false,
|
|
1693
|
+
error: response.errors.map((e) => e.message).join('; '),
|
|
1694
|
+
};
|
|
1695
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1696
|
+
}
|
|
1697
|
+
const result = {
|
|
1698
|
+
success: true,
|
|
1699
|
+
data: response.data,
|
|
1700
|
+
};
|
|
1701
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1702
|
+
}
|
|
1703
|
+
catch (error) {
|
|
1704
|
+
const result = {
|
|
1705
|
+
success: false,
|
|
1706
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
1707
|
+
};
|
|
1708
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1709
|
+
}
|
|
1710
|
+
});
|
|
1711
|
+
// ============================================================================
|
|
1156
1712
|
// Tool: List Data Tables
|
|
1157
1713
|
// ============================================================================
|
|
1158
1714
|
server.tool('list_data_tables', 'List data tables in the account. Returns table summaries with pagination. Use to discover available tables before querying rows.', {
|
|
@@ -2191,6 +2747,17 @@ Raw logs return too much data for AI context windows.
|
|
|
2191
2747
|
- remove_playlist_source - Remove a source from a playlist
|
|
2192
2748
|
- reorder_playlist_sources - Reorder sources within a playlist
|
|
2193
2749
|
|
|
2750
|
+
### Template Management
|
|
2751
|
+
- update_template - Update a template's properties (name, group, tags, dimensions, colors, orientation, script)
|
|
2752
|
+
- add_template_module - Add a new module (zone) to a template
|
|
2753
|
+
- update_template_module - Update a module within a template
|
|
2754
|
+
- remove_template_module - Remove a module from a template
|
|
2755
|
+
- reorder_template_modules - Reorder modules within a template (sequence/z-order)
|
|
2756
|
+
- batch_update_template_modules - Update multiple modules in a template at once
|
|
2757
|
+
- set_module_options - Set all options for a module (replaces existing)
|
|
2758
|
+
- upsert_module_option - Add or update a single module option (matched by name)
|
|
2759
|
+
- remove_module_option - Remove a module option by name
|
|
2760
|
+
|
|
2194
2761
|
### Data Table Management
|
|
2195
2762
|
- create_data_table - Create a new data table with column schema
|
|
2196
2763
|
- update_data_table - Update table definition (partial update)
|