latitude-mcp-server 2.2.1 → 2.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.
- package/dist/api.d.ts +2 -1
- package/dist/api.js +76 -34
- package/package.json +1 -1
package/dist/api.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ export declare class LatitudeApiError extends Error {
|
|
|
33
33
|
*/
|
|
34
34
|
export declare function getProjectId(): string;
|
|
35
35
|
export declare function listVersions(): Promise<Version[]>;
|
|
36
|
+
export declare function getVersion(versionUuid: string): Promise<Version>;
|
|
36
37
|
export declare function createVersion(name: string): Promise<Version>;
|
|
37
38
|
export declare function publishVersion(versionUuid: string, title?: string): Promise<Version>;
|
|
38
39
|
export declare function listDocuments(versionUuid?: string): Promise<Document[]>;
|
|
@@ -72,6 +73,6 @@ export declare function runDocument(path: string, parameters?: Record<string, un
|
|
|
72
73
|
*
|
|
73
74
|
* This is the same workflow the CLI uses, ensuring proper validation.
|
|
74
75
|
*/
|
|
75
|
-
export declare function deployToLive(changes: DocumentChange[],
|
|
76
|
+
export declare function deployToLive(changes: DocumentChange[], _versionName?: string): Promise<DeployResult>;
|
|
76
77
|
export declare function getPromptNames(): Promise<string[]>;
|
|
77
78
|
export {};
|
package/dist/api.js
CHANGED
|
@@ -16,6 +16,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
16
16
|
exports.LatitudeApiError = void 0;
|
|
17
17
|
exports.getProjectId = getProjectId;
|
|
18
18
|
exports.listVersions = listVersions;
|
|
19
|
+
exports.getVersion = getVersion;
|
|
19
20
|
exports.createVersion = createVersion;
|
|
20
21
|
exports.publishVersion = publishVersion;
|
|
21
22
|
exports.listDocuments = listDocuments;
|
|
@@ -60,6 +61,13 @@ async function request(endpoint, options = {}) {
|
|
|
60
61
|
const timeoutId = setTimeout(() => controller.abort(), options.timeout || API_TIMEOUT_MS);
|
|
61
62
|
logger.debug(`API ${method} ${endpoint}`);
|
|
62
63
|
try {
|
|
64
|
+
// Add __internal: { source: 'api' } to all POST requests (required by Latitude API)
|
|
65
|
+
const body = options.body && method === 'POST'
|
|
66
|
+
? { ...options.body, __internal: { source: 'api' } }
|
|
67
|
+
: options.body;
|
|
68
|
+
if (body) {
|
|
69
|
+
logger.debug(`Request body: ${JSON.stringify(body, null, 2)}`);
|
|
70
|
+
}
|
|
63
71
|
const response = await fetch(url, {
|
|
64
72
|
method,
|
|
65
73
|
headers: {
|
|
@@ -67,7 +75,7 @@ async function request(endpoint, options = {}) {
|
|
|
67
75
|
Accept: 'application/json',
|
|
68
76
|
Authorization: `Bearer ${apiKey}`,
|
|
69
77
|
},
|
|
70
|
-
body:
|
|
78
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
71
79
|
signal: controller.signal,
|
|
72
80
|
});
|
|
73
81
|
clearTimeout(timeoutId);
|
|
@@ -264,6 +272,10 @@ async function listVersions() {
|
|
|
264
272
|
const projectId = getProjectId();
|
|
265
273
|
return request(`/projects/${projectId}/versions`);
|
|
266
274
|
}
|
|
275
|
+
async function getVersion(versionUuid) {
|
|
276
|
+
const projectId = getProjectId();
|
|
277
|
+
return request(`/projects/${projectId}/versions/${versionUuid}`);
|
|
278
|
+
}
|
|
267
279
|
async function createVersion(name) {
|
|
268
280
|
const projectId = getProjectId();
|
|
269
281
|
return request(`/projects/${projectId}/versions`, {
|
|
@@ -386,27 +398,38 @@ async function runDocument(path, parameters, versionUuid = 'live') {
|
|
|
386
398
|
});
|
|
387
399
|
}
|
|
388
400
|
/**
|
|
389
|
-
*
|
|
390
|
-
*
|
|
401
|
+
* Identify which documents fail validation by testing each one individually.
|
|
402
|
+
* Used when a batch publish fails to provide actionable error messages.
|
|
391
403
|
*/
|
|
392
|
-
function
|
|
393
|
-
const
|
|
394
|
-
const
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
404
|
+
async function identifyFailingDocuments(changes) {
|
|
405
|
+
const failed = [];
|
|
406
|
+
for (const change of changes) {
|
|
407
|
+
if (change.status === 'deleted')
|
|
408
|
+
continue; // Deletes don't have content validation
|
|
409
|
+
try {
|
|
410
|
+
// Create a test draft for this single document
|
|
411
|
+
const testDraft = await createVersion(`validation-test-${change.path}`);
|
|
412
|
+
// Push just this document
|
|
413
|
+
await pushChanges(testDraft.uuid, [change]);
|
|
414
|
+
// Try to publish - this will fail if document has validation errors
|
|
415
|
+
await publishVersion(testDraft.uuid);
|
|
416
|
+
// If we get here, document is valid - the draft was published but that's ok
|
|
417
|
+
logger.debug(`Document ${change.path} validated successfully`);
|
|
418
|
+
}
|
|
419
|
+
catch (error) {
|
|
420
|
+
// This document failed - capture the error
|
|
421
|
+
const errorMsg = error instanceof LatitudeApiError
|
|
422
|
+
? error.message
|
|
423
|
+
: (error instanceof Error ? error.message : 'Unknown validation error');
|
|
424
|
+
failed.push({
|
|
425
|
+
path: change.path,
|
|
426
|
+
error: errorMsg,
|
|
427
|
+
content: change.content?.substring(0, 200) + (change.content && change.content.length > 200 ? '...' : ''),
|
|
428
|
+
});
|
|
429
|
+
logger.debug(`Document ${change.path} failed validation: ${errorMsg}`);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return failed;
|
|
410
433
|
}
|
|
411
434
|
/**
|
|
412
435
|
* Create a synthetic Version object for no-op deploys.
|
|
@@ -432,7 +455,7 @@ function createNoOpVersion() {
|
|
|
432
455
|
*
|
|
433
456
|
* This is the same workflow the CLI uses, ensuring proper validation.
|
|
434
457
|
*/
|
|
435
|
-
async function deployToLive(changes,
|
|
458
|
+
async function deployToLive(changes, _versionName) {
|
|
436
459
|
if (changes.length === 0) {
|
|
437
460
|
logger.info('No changes to deploy');
|
|
438
461
|
return {
|
|
@@ -459,27 +482,46 @@ async function deployToLive(changes, versionName) {
|
|
|
459
482
|
const added = actualChanges.filter((c) => c.status === 'added').map((c) => c.path);
|
|
460
483
|
const modified = actualChanges.filter((c) => c.status === 'modified').map((c) => c.path);
|
|
461
484
|
const deleted = actualChanges.filter((c) => c.status === 'deleted').map((c) => c.path);
|
|
462
|
-
const name = formatVersionName(versionName);
|
|
463
485
|
logger.info(`Deploying to LIVE: ${added.length} added, ${modified.length} modified, ${deleted.length} deleted`);
|
|
464
486
|
// Step 1: Create a new draft version
|
|
465
|
-
|
|
466
|
-
|
|
487
|
+
const draftName = `MCP deploy ${new Date().toISOString()}`;
|
|
488
|
+
logger.info(`Creating draft version: ${draftName}`);
|
|
489
|
+
const draft = await createVersion(draftName);
|
|
467
490
|
logger.info(`Draft created: ${draft.uuid}`);
|
|
468
491
|
// Step 2: Push all changes to the draft in ONE batch
|
|
469
492
|
logger.info(`Pushing ${actualChanges.length} change(s) to draft...`);
|
|
493
|
+
logger.debug(`Changes payload: ${JSON.stringify(actualChanges, null, 2)}`);
|
|
470
494
|
const pushResult = await pushChanges(draft.uuid, actualChanges);
|
|
471
495
|
logger.info(`Push complete: ${pushResult.documentsProcessed} documents processed`);
|
|
472
496
|
// Step 3: Publish the draft to make it LIVE
|
|
473
497
|
logger.info(`Publishing draft ${draft.uuid} to LIVE...`);
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
498
|
+
try {
|
|
499
|
+
const published = await publishVersion(draft.uuid, draftName);
|
|
500
|
+
logger.info(`Published successfully! Version is now LIVE: ${published.uuid}`);
|
|
501
|
+
return {
|
|
502
|
+
version: published,
|
|
503
|
+
documentsProcessed: pushResult.documentsProcessed,
|
|
504
|
+
added,
|
|
505
|
+
modified,
|
|
506
|
+
deleted,
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
catch (publishError) {
|
|
510
|
+
// Publish failed - identify which document(s) have validation errors
|
|
511
|
+
logger.warn('Batch publish failed, identifying problematic documents...');
|
|
512
|
+
const failedDocs = await identifyFailingDocuments(actualChanges);
|
|
513
|
+
if (failedDocs.length > 0) {
|
|
514
|
+
const errorDetails = failedDocs.map(f => `- ${f.path}: ${f.error}`).join('\n');
|
|
515
|
+
throw new LatitudeApiError({
|
|
516
|
+
name: 'DocumentValidationError',
|
|
517
|
+
errorCode: 'DOCUMENT_VALIDATION_FAILED',
|
|
518
|
+
message: `${failedDocs.length} document(s) failed validation:\n${errorDetails}`,
|
|
519
|
+
details: { failedDocuments: failedDocs },
|
|
520
|
+
}, 422);
|
|
521
|
+
}
|
|
522
|
+
// Re-throw original error if we couldn't identify specific failures
|
|
523
|
+
throw publishError;
|
|
524
|
+
}
|
|
483
525
|
}
|
|
484
526
|
async function getPromptNames() {
|
|
485
527
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "latitude-mcp-server",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.3",
|
|
4
4
|
"description": "Simplified MCP server for Latitude.so prompt management - 8 focused tools for push, pull, run, and manage prompts",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|