midnight-mcp 0.1.8 → 0.1.10
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 +60 -197
- package/dist/tools/analyze.js +2 -0
- package/dist/tools/generation.js +3 -0
- package/dist/tools/health.js +2 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +3 -0
- package/dist/tools/meta.d.ts +61 -0
- package/dist/tools/meta.js +281 -0
- package/dist/tools/repository/handlers.d.ts +73 -15
- package/dist/tools/repository/handlers.js +229 -28
- package/dist/tools/repository/schemas.d.ts +25 -0
- package/dist/tools/repository/schemas.js +18 -0
- package/dist/tools/repository/tools.js +121 -1
- package/dist/tools/search.js +1 -0
- package/dist/types/mcp.d.ts +20 -0
- package/dist/utils/errors.d.ts +66 -0
- package/dist/utils/errors.js +70 -0
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +1 -1
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { githubClient } from "../../pipeline/index.js";
|
|
6
6
|
import { releaseTracker } from "../../pipeline/releases.js";
|
|
7
|
-
import { logger, DEFAULT_REPOSITORIES } from "../../utils/index.js";
|
|
7
|
+
import { logger, DEFAULT_REPOSITORIES, SelfCorrectionHints, } from "../../utils/index.js";
|
|
8
8
|
import { REPO_ALIASES, EXAMPLES } from "./constants.js";
|
|
9
9
|
/**
|
|
10
10
|
* Resolve repository name alias to owner/repo
|
|
@@ -36,18 +36,11 @@ export async function getFile(input) {
|
|
|
36
36
|
logger.debug("Getting file", { repo: input.repo, path: input.path });
|
|
37
37
|
const repoInfo = resolveRepo(input.repo);
|
|
38
38
|
if (!repoInfo) {
|
|
39
|
-
return
|
|
40
|
-
error: `Unknown repository: ${input.repo}`,
|
|
41
|
-
suggestion: `Valid repositories: ${Object.keys(REPO_ALIASES).join(", ")}`,
|
|
42
|
-
};
|
|
39
|
+
return SelfCorrectionHints.UNKNOWN_REPO(input.repo, Object.keys(REPO_ALIASES));
|
|
43
40
|
}
|
|
44
41
|
const file = await githubClient.getFileContent(repoInfo.owner, repoInfo.repo, input.path, input.ref);
|
|
45
42
|
if (!file) {
|
|
46
|
-
return {
|
|
47
|
-
error: `File not found: ${input.path}`,
|
|
48
|
-
repository: `${repoInfo.owner}/${repoInfo.repo}`,
|
|
49
|
-
suggestion: "Check the file path and try again. Use midnight:list-examples to see available example files.",
|
|
50
|
-
};
|
|
43
|
+
return SelfCorrectionHints.FILE_NOT_FOUND(input.path, `${repoInfo.owner}/${repoInfo.repo}`);
|
|
51
44
|
}
|
|
52
45
|
return {
|
|
53
46
|
content: file.content,
|
|
@@ -141,8 +134,10 @@ export async function getLatestUpdates(input) {
|
|
|
141
134
|
* Get version and release info for a repository
|
|
142
135
|
*/
|
|
143
136
|
export async function getVersionInfo(input) {
|
|
144
|
-
|
|
145
|
-
const
|
|
137
|
+
// Ensure repo defaults to compact if undefined/empty
|
|
138
|
+
const repoName = input?.repo || "compact";
|
|
139
|
+
logger.debug("Getting version info", { repo: repoName });
|
|
140
|
+
const resolved = resolveRepo(repoName);
|
|
146
141
|
if (!resolved) {
|
|
147
142
|
throw new Error(`Unknown repository: ${input.repo}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
|
|
148
143
|
}
|
|
@@ -170,10 +165,15 @@ export async function getVersionInfo(input) {
|
|
|
170
165
|
* Check for breaking changes since a specific version
|
|
171
166
|
*/
|
|
172
167
|
export async function checkBreakingChanges(input) {
|
|
173
|
-
|
|
174
|
-
const
|
|
168
|
+
// Ensure repo defaults to compact if undefined/empty
|
|
169
|
+
const repoName = input?.repo || "compact";
|
|
170
|
+
logger.debug("Checking breaking changes", {
|
|
171
|
+
repo: repoName,
|
|
172
|
+
currentVersion: input.currentVersion,
|
|
173
|
+
});
|
|
174
|
+
const resolved = resolveRepo(repoName);
|
|
175
175
|
if (!resolved) {
|
|
176
|
-
throw new Error(`Unknown repository: ${
|
|
176
|
+
throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
|
|
177
177
|
}
|
|
178
178
|
const outdatedInfo = await releaseTracker.isOutdated(resolved.owner, resolved.repo, input.currentVersion);
|
|
179
179
|
const breakingChanges = await releaseTracker.getBreakingChangesSince(resolved.owner, resolved.repo, input.currentVersion);
|
|
@@ -196,10 +196,16 @@ export async function checkBreakingChanges(input) {
|
|
|
196
196
|
* Get migration guide between versions
|
|
197
197
|
*/
|
|
198
198
|
export async function getMigrationGuide(input) {
|
|
199
|
-
|
|
200
|
-
const
|
|
199
|
+
// Ensure repo defaults to compact if undefined/empty
|
|
200
|
+
const repoName = input?.repo || "compact";
|
|
201
|
+
logger.debug("Getting migration guide", {
|
|
202
|
+
repo: repoName,
|
|
203
|
+
fromVersion: input.fromVersion,
|
|
204
|
+
toVersion: input.toVersion,
|
|
205
|
+
});
|
|
206
|
+
const resolved = resolveRepo(repoName);
|
|
201
207
|
if (!resolved) {
|
|
202
|
-
throw new Error(`Unknown repository: ${
|
|
208
|
+
throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
|
|
203
209
|
}
|
|
204
210
|
const guide = await releaseTracker.getMigrationGuide(resolved.owner, resolved.repo, input.fromVersion, input.toVersion);
|
|
205
211
|
return {
|
|
@@ -226,14 +232,20 @@ export async function getMigrationGuide(input) {
|
|
|
226
232
|
* Get a file at a specific version - critical for version-accurate recommendations
|
|
227
233
|
*/
|
|
228
234
|
export async function getFileAtVersion(input) {
|
|
229
|
-
|
|
230
|
-
const
|
|
235
|
+
// Ensure repo defaults to compact if undefined/empty
|
|
236
|
+
const repoName = input?.repo || "compact";
|
|
237
|
+
logger.debug("Getting file at version", {
|
|
238
|
+
repo: repoName,
|
|
239
|
+
path: input.path,
|
|
240
|
+
version: input.version,
|
|
241
|
+
});
|
|
242
|
+
const resolved = resolveRepo(repoName);
|
|
231
243
|
if (!resolved) {
|
|
232
|
-
throw new Error(`Unknown repository: ${
|
|
244
|
+
throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
|
|
233
245
|
}
|
|
234
246
|
const result = await releaseTracker.getFileAtVersion(resolved.owner, resolved.repo, input.path, input.version);
|
|
235
247
|
if (!result) {
|
|
236
|
-
throw new Error(`File not found: ${input.path} at version ${input.version} in ${
|
|
248
|
+
throw new Error(`File not found: ${input.path} at version ${input.version} in ${repoName}`);
|
|
237
249
|
}
|
|
238
250
|
return {
|
|
239
251
|
repository: `${resolved.owner}/${resolved.repo}`,
|
|
@@ -247,10 +259,16 @@ export async function getFileAtVersion(input) {
|
|
|
247
259
|
* Compare syntax between two versions - shows what changed
|
|
248
260
|
*/
|
|
249
261
|
export async function compareSyntax(input) {
|
|
250
|
-
|
|
251
|
-
const
|
|
262
|
+
// Ensure repo defaults to compact if undefined/empty
|
|
263
|
+
const repoName = input?.repo || "compact";
|
|
264
|
+
logger.debug("Comparing syntax between versions", {
|
|
265
|
+
repo: repoName,
|
|
266
|
+
oldVersion: input.oldVersion,
|
|
267
|
+
newVersion: input.newVersion,
|
|
268
|
+
});
|
|
269
|
+
const resolved = resolveRepo(repoName);
|
|
252
270
|
if (!resolved) {
|
|
253
|
-
throw new Error(`Unknown repository: ${
|
|
271
|
+
throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
|
|
254
272
|
}
|
|
255
273
|
// If no newVersion specified, get latest
|
|
256
274
|
let newVersion = input.newVersion;
|
|
@@ -280,10 +298,12 @@ export async function compareSyntax(input) {
|
|
|
280
298
|
* This is the source of truth for writing valid, compilable contracts
|
|
281
299
|
*/
|
|
282
300
|
export async function getLatestSyntax(input) {
|
|
283
|
-
|
|
284
|
-
const
|
|
301
|
+
// Ensure repo defaults to compact if undefined/empty
|
|
302
|
+
const repoName = input?.repo || "compact";
|
|
303
|
+
logger.debug("Getting latest syntax reference", { repo: repoName });
|
|
304
|
+
const resolved = resolveRepo(repoName);
|
|
285
305
|
if (!resolved) {
|
|
286
|
-
throw new Error(`Unknown repository: ${
|
|
306
|
+
throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
|
|
287
307
|
}
|
|
288
308
|
const reference = await releaseTracker.getLatestSyntaxReference(resolved.owner, resolved.repo);
|
|
289
309
|
if (!reference || reference.syntaxFiles.length === 0) {
|
|
@@ -308,4 +328,185 @@ export async function getLatestSyntax(input) {
|
|
|
308
328
|
note: `This is the authoritative syntax reference at version ${reference.version}. Use this to ensure contracts are compilable.`,
|
|
309
329
|
};
|
|
310
330
|
}
|
|
331
|
+
// ============================================================================
|
|
332
|
+
// COMPOUND TOOLS - Reduce multiple API calls to single operations
|
|
333
|
+
// These tools combine related operations to minimize round-trips and token usage
|
|
334
|
+
// ============================================================================
|
|
335
|
+
/**
|
|
336
|
+
* Compound tool: Full upgrade check
|
|
337
|
+
* Combines: getVersionInfo + checkBreakingChanges + getMigrationGuide
|
|
338
|
+
* Reduces 3 tool calls to 1, saving ~60% tokens
|
|
339
|
+
*/
|
|
340
|
+
export async function upgradeCheck(input) {
|
|
341
|
+
const repoName = input?.repo || "compact";
|
|
342
|
+
const currentVersion = input.currentVersion;
|
|
343
|
+
logger.debug("Running compound upgrade check", {
|
|
344
|
+
repo: repoName,
|
|
345
|
+
currentVersion,
|
|
346
|
+
});
|
|
347
|
+
const resolved = resolveRepo(repoName);
|
|
348
|
+
if (!resolved) {
|
|
349
|
+
throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
|
|
350
|
+
}
|
|
351
|
+
// Fetch all data in parallel
|
|
352
|
+
const [versionInfo, outdatedInfo, breakingChanges] = await Promise.all([
|
|
353
|
+
releaseTracker.getVersionInfo(resolved.owner, resolved.repo),
|
|
354
|
+
releaseTracker.isOutdated(resolved.owner, resolved.repo, currentVersion),
|
|
355
|
+
releaseTracker.getBreakingChangesSince(resolved.owner, resolved.repo, currentVersion),
|
|
356
|
+
]);
|
|
357
|
+
const latestVersion = versionInfo.latestStableRelease?.tag || versionInfo.latestRelease?.tag;
|
|
358
|
+
// Only fetch migration guide if there are breaking changes
|
|
359
|
+
let migrationGuide = null;
|
|
360
|
+
if (breakingChanges.length > 0 && latestVersion) {
|
|
361
|
+
migrationGuide = await releaseTracker.getMigrationGuide(resolved.owner, resolved.repo, currentVersion, latestVersion);
|
|
362
|
+
}
|
|
363
|
+
// Compute upgrade urgency
|
|
364
|
+
const urgency = computeUpgradeUrgency(outdatedInfo, breakingChanges.length);
|
|
365
|
+
return {
|
|
366
|
+
repository: `${resolved.owner}/${resolved.repo}`,
|
|
367
|
+
currentVersion,
|
|
368
|
+
// Version summary
|
|
369
|
+
version: {
|
|
370
|
+
latest: latestVersion || "No releases",
|
|
371
|
+
latestStable: versionInfo.latestStableRelease?.tag || "No stable releases",
|
|
372
|
+
publishedAt: versionInfo.latestRelease?.publishedAt || null,
|
|
373
|
+
isOutdated: outdatedInfo.isOutdated,
|
|
374
|
+
versionsBehind: outdatedInfo.versionsBehind,
|
|
375
|
+
},
|
|
376
|
+
// Breaking changes summary
|
|
377
|
+
breakingChanges: {
|
|
378
|
+
count: breakingChanges.length,
|
|
379
|
+
hasBreakingChanges: breakingChanges.length > 0,
|
|
380
|
+
items: breakingChanges.slice(0, 10), // Limit to avoid token bloat
|
|
381
|
+
},
|
|
382
|
+
// Migration guide (only if needed)
|
|
383
|
+
migration: migrationGuide
|
|
384
|
+
? {
|
|
385
|
+
steps: migrationGuide.migrationSteps,
|
|
386
|
+
deprecations: migrationGuide.deprecations,
|
|
387
|
+
newFeatures: migrationGuide.newFeatures.slice(0, 5),
|
|
388
|
+
}
|
|
389
|
+
: null,
|
|
390
|
+
// Actionable recommendation
|
|
391
|
+
urgency,
|
|
392
|
+
recommendation: generateUpgradeRecommendation(urgency, breakingChanges.length, outdatedInfo),
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Compound tool: Full repository context
|
|
397
|
+
* Combines: getVersionInfo + getLatestSyntax + listExamples (filtered)
|
|
398
|
+
* Provides everything needed to start working with a repo
|
|
399
|
+
*/
|
|
400
|
+
export async function getFullRepoContext(input) {
|
|
401
|
+
const repoName = input?.repo || "compact";
|
|
402
|
+
logger.debug("Getting full repo context", { repo: repoName });
|
|
403
|
+
const resolved = resolveRepo(repoName);
|
|
404
|
+
if (!resolved) {
|
|
405
|
+
throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
|
|
406
|
+
}
|
|
407
|
+
// Fetch version info
|
|
408
|
+
const versionInfo = await releaseTracker.getVersionInfo(resolved.owner, resolved.repo);
|
|
409
|
+
const version = versionInfo.latestStableRelease?.tag ||
|
|
410
|
+
versionInfo.latestRelease?.tag ||
|
|
411
|
+
"main";
|
|
412
|
+
// Conditionally fetch syntax reference
|
|
413
|
+
let syntaxRef = null;
|
|
414
|
+
if (input.includeSyntax !== false) {
|
|
415
|
+
syntaxRef = await releaseTracker.getLatestSyntaxReference(resolved.owner, resolved.repo);
|
|
416
|
+
}
|
|
417
|
+
// Get relevant examples for this repo
|
|
418
|
+
let examples = [];
|
|
419
|
+
if (input.includeExamples !== false) {
|
|
420
|
+
// Filter examples relevant to this repo type
|
|
421
|
+
const repoType = getRepoType(repoName);
|
|
422
|
+
examples = EXAMPLES.filter((ex) => repoType === "all" || ex.category === repoType || repoType === "compact")
|
|
423
|
+
.slice(0, 5)
|
|
424
|
+
.map((ex) => ({
|
|
425
|
+
name: ex.name,
|
|
426
|
+
description: ex.description,
|
|
427
|
+
complexity: ex.complexity,
|
|
428
|
+
}));
|
|
429
|
+
}
|
|
430
|
+
return {
|
|
431
|
+
repository: `${resolved.owner}/${resolved.repo}`,
|
|
432
|
+
// Quick start info
|
|
433
|
+
quickStart: {
|
|
434
|
+
version,
|
|
435
|
+
installCommand: getInstallCommand(repoName, version),
|
|
436
|
+
docsUrl: `https://github.com/${resolved.owner}/${resolved.repo}`,
|
|
437
|
+
},
|
|
438
|
+
// Version context
|
|
439
|
+
version: {
|
|
440
|
+
current: version,
|
|
441
|
+
stable: versionInfo.latestStableRelease?.tag || null,
|
|
442
|
+
publishedAt: versionInfo.latestRelease?.publishedAt || null,
|
|
443
|
+
recentReleases: versionInfo.recentReleases.slice(0, 3).map((r) => ({
|
|
444
|
+
tag: r.tag,
|
|
445
|
+
date: r.publishedAt.split("T")[0],
|
|
446
|
+
})),
|
|
447
|
+
},
|
|
448
|
+
// Syntax reference (condensed)
|
|
449
|
+
syntax: syntaxRef
|
|
450
|
+
? {
|
|
451
|
+
version: syntaxRef.version,
|
|
452
|
+
files: syntaxRef.syntaxFiles.map((f) => f.path),
|
|
453
|
+
// Include first file content as primary reference
|
|
454
|
+
primaryReference: syntaxRef.syntaxFiles[0]?.content?.slice(0, 2000) || null,
|
|
455
|
+
}
|
|
456
|
+
: null,
|
|
457
|
+
// Relevant examples
|
|
458
|
+
examples,
|
|
459
|
+
note: `Use this context to write ${repoName} code at version ${version}. For detailed syntax, use midnight-get-latest-syntax.`,
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
// Helper functions for compound tools
|
|
463
|
+
function computeUpgradeUrgency(outdatedInfo, breakingCount) {
|
|
464
|
+
if (!outdatedInfo.isOutdated)
|
|
465
|
+
return "none";
|
|
466
|
+
if (breakingCount === 0 && outdatedInfo.versionsBehind <= 2)
|
|
467
|
+
return "low";
|
|
468
|
+
if (breakingCount <= 2 && outdatedInfo.versionsBehind <= 5)
|
|
469
|
+
return "medium";
|
|
470
|
+
if (breakingCount <= 5)
|
|
471
|
+
return "high";
|
|
472
|
+
return "critical";
|
|
473
|
+
}
|
|
474
|
+
function generateUpgradeRecommendation(urgency, breakingCount, outdatedInfo) {
|
|
475
|
+
switch (urgency) {
|
|
476
|
+
case "none":
|
|
477
|
+
return "✅ You're on the latest version. No action needed.";
|
|
478
|
+
case "low":
|
|
479
|
+
return `📦 Minor update available (${outdatedInfo.versionsBehind} versions behind). Safe to upgrade at your convenience.`;
|
|
480
|
+
case "medium":
|
|
481
|
+
return `⚠️ Update recommended. ${breakingCount} breaking change(s) to review. Plan upgrade within 2 weeks.`;
|
|
482
|
+
case "high":
|
|
483
|
+
return `🔶 Important update. ${breakingCount} breaking changes require attention. Schedule upgrade soon.`;
|
|
484
|
+
case "critical":
|
|
485
|
+
return `🚨 Critical update needed! ${breakingCount} breaking changes and ${outdatedInfo.versionsBehind} versions behind. Upgrade immediately.`;
|
|
486
|
+
default:
|
|
487
|
+
return "Check the breaking changes and plan your upgrade.";
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
function getRepoType(repoName) {
|
|
491
|
+
const name = repoName.toLowerCase();
|
|
492
|
+
if (name.includes("counter"))
|
|
493
|
+
return "counter";
|
|
494
|
+
if (name.includes("bboard"))
|
|
495
|
+
return "bboard";
|
|
496
|
+
if (name.includes("token") || name.includes("dex"))
|
|
497
|
+
return "token";
|
|
498
|
+
if (name.includes("voting"))
|
|
499
|
+
return "voting";
|
|
500
|
+
return "all";
|
|
501
|
+
}
|
|
502
|
+
function getInstallCommand(repoName, version) {
|
|
503
|
+
const name = repoName.toLowerCase();
|
|
504
|
+
if (name === "compact" || name.includes("compact")) {
|
|
505
|
+
return `npx @aspect-sh/pnpm dlx @midnight-ntwrk/create-midnight-app@${version}`;
|
|
506
|
+
}
|
|
507
|
+
if (name === "midnight-js" || name.includes("js")) {
|
|
508
|
+
return `npm install @midnight-ntwrk/midnight-js@${version}`;
|
|
509
|
+
}
|
|
510
|
+
return `git clone https://github.com/midnight-ntwrk/${repoName}.git && cd ${repoName} && git checkout ${version}`;
|
|
511
|
+
}
|
|
311
512
|
//# sourceMappingURL=handlers.js.map
|
|
@@ -99,6 +99,29 @@ export declare const GetLatestSyntaxInputSchema: z.ZodObject<{
|
|
|
99
99
|
}, {
|
|
100
100
|
repo?: string | undefined;
|
|
101
101
|
}>;
|
|
102
|
+
export declare const UpgradeCheckInputSchema: z.ZodObject<{
|
|
103
|
+
repo: z.ZodDefault<z.ZodString>;
|
|
104
|
+
currentVersion: z.ZodString;
|
|
105
|
+
}, "strip", z.ZodTypeAny, {
|
|
106
|
+
repo: string;
|
|
107
|
+
currentVersion: string;
|
|
108
|
+
}, {
|
|
109
|
+
currentVersion: string;
|
|
110
|
+
repo?: string | undefined;
|
|
111
|
+
}>;
|
|
112
|
+
export declare const FullRepoContextInputSchema: z.ZodObject<{
|
|
113
|
+
repo: z.ZodString;
|
|
114
|
+
includeExamples: z.ZodDefault<z.ZodBoolean>;
|
|
115
|
+
includeSyntax: z.ZodDefault<z.ZodBoolean>;
|
|
116
|
+
}, "strip", z.ZodTypeAny, {
|
|
117
|
+
repo: string;
|
|
118
|
+
includeExamples: boolean;
|
|
119
|
+
includeSyntax: boolean;
|
|
120
|
+
}, {
|
|
121
|
+
repo: string;
|
|
122
|
+
includeExamples?: boolean | undefined;
|
|
123
|
+
includeSyntax?: boolean | undefined;
|
|
124
|
+
}>;
|
|
102
125
|
export type GetFileInput = z.infer<typeof GetFileInputSchema>;
|
|
103
126
|
export type ListExamplesInput = z.infer<typeof ListExamplesInputSchema>;
|
|
104
127
|
export type GetLatestUpdatesInput = z.infer<typeof GetLatestUpdatesInputSchema>;
|
|
@@ -108,4 +131,6 @@ export type GetMigrationGuideInput = z.infer<typeof GetMigrationGuideInputSchema
|
|
|
108
131
|
export type GetFileAtVersionInput = z.infer<typeof GetFileAtVersionInputSchema>;
|
|
109
132
|
export type CompareSyntaxInput = z.infer<typeof CompareSyntaxInputSchema>;
|
|
110
133
|
export type GetLatestSyntaxInput = z.infer<typeof GetLatestSyntaxInputSchema>;
|
|
134
|
+
export type UpgradeCheckInput = z.infer<typeof UpgradeCheckInputSchema>;
|
|
135
|
+
export type FullRepoContextInput = z.infer<typeof FullRepoContextInputSchema>;
|
|
111
136
|
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -70,4 +70,22 @@ export const GetLatestSyntaxInputSchema = z.object({
|
|
|
70
70
|
.default("compact")
|
|
71
71
|
.describe("Repository name (default: 'compact')"),
|
|
72
72
|
});
|
|
73
|
+
// Compound tool schemas - reduce multiple API calls to one
|
|
74
|
+
export const UpgradeCheckInputSchema = z.object({
|
|
75
|
+
repo: z
|
|
76
|
+
.string()
|
|
77
|
+
.default("compact")
|
|
78
|
+
.describe("Repository name (default: 'compact')"),
|
|
79
|
+
currentVersion: z
|
|
80
|
+
.string()
|
|
81
|
+
.describe("Your current version (e.g., 'v0.14.0', '0.13.5')"),
|
|
82
|
+
});
|
|
83
|
+
export const FullRepoContextInputSchema = z.object({
|
|
84
|
+
repo: z.string().describe("Repository name (e.g., 'compact', 'midnight-js')"),
|
|
85
|
+
includeExamples: z
|
|
86
|
+
.boolean()
|
|
87
|
+
.default(true)
|
|
88
|
+
.describe("Include example code snippets"),
|
|
89
|
+
includeSyntax: z.boolean().default(true).describe("Include syntax reference"),
|
|
90
|
+
});
|
|
73
91
|
//# sourceMappingURL=schemas.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Repository tool definitions
|
|
3
3
|
* MCP tool registration for repository-related operations
|
|
4
4
|
*/
|
|
5
|
-
import { getFile, listExamples, getLatestUpdates, getVersionInfo, checkBreakingChanges, getMigrationGuide, getFileAtVersion, compareSyntax, getLatestSyntax, } from "./handlers.js";
|
|
5
|
+
import { getFile, listExamples, getLatestUpdates, getVersionInfo, checkBreakingChanges, getMigrationGuide, getFileAtVersion, compareSyntax, getLatestSyntax, upgradeCheck, getFullRepoContext, } from "./handlers.js";
|
|
6
6
|
// Tool definitions for MCP
|
|
7
7
|
export const repositoryTools = [
|
|
8
8
|
{
|
|
@@ -30,6 +30,7 @@ export const repositoryTools = [
|
|
|
30
30
|
readOnlyHint: true,
|
|
31
31
|
openWorldHint: true,
|
|
32
32
|
title: "Get Repository File",
|
|
33
|
+
category: "repository",
|
|
33
34
|
},
|
|
34
35
|
handler: getFile,
|
|
35
36
|
},
|
|
@@ -51,6 +52,7 @@ export const repositoryTools = [
|
|
|
51
52
|
readOnlyHint: true,
|
|
52
53
|
idempotentHint: true,
|
|
53
54
|
title: "List Example Contracts",
|
|
55
|
+
category: "repository",
|
|
54
56
|
},
|
|
55
57
|
handler: listExamples,
|
|
56
58
|
},
|
|
@@ -76,6 +78,7 @@ export const repositoryTools = [
|
|
|
76
78
|
readOnlyHint: true,
|
|
77
79
|
openWorldHint: true,
|
|
78
80
|
title: "Get Latest Updates",
|
|
81
|
+
category: "repository",
|
|
79
82
|
},
|
|
80
83
|
handler: getLatestUpdates,
|
|
81
84
|
},
|
|
@@ -96,6 +99,7 @@ export const repositoryTools = [
|
|
|
96
99
|
readOnlyHint: true,
|
|
97
100
|
openWorldHint: true,
|
|
98
101
|
title: "Get Version Info",
|
|
102
|
+
category: "versioning",
|
|
99
103
|
},
|
|
100
104
|
handler: getVersionInfo,
|
|
101
105
|
},
|
|
@@ -120,6 +124,7 @@ export const repositoryTools = [
|
|
|
120
124
|
readOnlyHint: true,
|
|
121
125
|
openWorldHint: true,
|
|
122
126
|
title: "Check Breaking Changes",
|
|
127
|
+
category: "versioning",
|
|
123
128
|
},
|
|
124
129
|
handler: checkBreakingChanges,
|
|
125
130
|
},
|
|
@@ -148,6 +153,7 @@ export const repositoryTools = [
|
|
|
148
153
|
readOnlyHint: true,
|
|
149
154
|
openWorldHint: true,
|
|
150
155
|
title: "Get Migration Guide",
|
|
156
|
+
category: "versioning",
|
|
151
157
|
},
|
|
152
158
|
handler: getMigrationGuide,
|
|
153
159
|
},
|
|
@@ -177,6 +183,7 @@ export const repositoryTools = [
|
|
|
177
183
|
idempotentHint: true,
|
|
178
184
|
openWorldHint: true,
|
|
179
185
|
title: "Get File at Version",
|
|
186
|
+
category: "versioning",
|
|
180
187
|
},
|
|
181
188
|
handler: getFileAtVersion,
|
|
182
189
|
},
|
|
@@ -210,6 +217,7 @@ export const repositoryTools = [
|
|
|
210
217
|
idempotentHint: true,
|
|
211
218
|
openWorldHint: true,
|
|
212
219
|
title: "Compare Syntax Between Versions",
|
|
220
|
+
category: "versioning",
|
|
213
221
|
},
|
|
214
222
|
handler: compareSyntax,
|
|
215
223
|
},
|
|
@@ -230,8 +238,120 @@ export const repositoryTools = [
|
|
|
230
238
|
readOnlyHint: true,
|
|
231
239
|
openWorldHint: true,
|
|
232
240
|
title: "Get Latest Syntax Reference",
|
|
241
|
+
category: "versioning",
|
|
233
242
|
},
|
|
234
243
|
handler: getLatestSyntax,
|
|
235
244
|
},
|
|
245
|
+
// ============================================================================
|
|
246
|
+
// COMPOUND TOOLS - Multi-step operations in a single call
|
|
247
|
+
// These reduce token usage by 50-70% compared to calling individual tools
|
|
248
|
+
// ============================================================================
|
|
249
|
+
{
|
|
250
|
+
name: "midnight-upgrade-check",
|
|
251
|
+
description: "🚀 COMPOUND TOOL: Complete upgrade analysis in ONE call. Combines version check + breaking changes + migration guide. Use this instead of calling midnight-get-version-info, midnight-check-breaking-changes, and midnight-get-migration-guide separately. Saves ~60% tokens.",
|
|
252
|
+
inputSchema: {
|
|
253
|
+
type: "object",
|
|
254
|
+
properties: {
|
|
255
|
+
repo: {
|
|
256
|
+
type: "string",
|
|
257
|
+
description: "Repository name (default: 'compact')",
|
|
258
|
+
},
|
|
259
|
+
currentVersion: {
|
|
260
|
+
type: "string",
|
|
261
|
+
description: "Your current version (e.g., 'v0.14.0', '0.13.5')",
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
required: ["currentVersion"],
|
|
265
|
+
},
|
|
266
|
+
outputSchema: {
|
|
267
|
+
type: "object",
|
|
268
|
+
properties: {
|
|
269
|
+
repository: { type: "string", description: "Full repository path" },
|
|
270
|
+
currentVersion: {
|
|
271
|
+
type: "string",
|
|
272
|
+
description: "Version being checked",
|
|
273
|
+
},
|
|
274
|
+
version: {
|
|
275
|
+
type: "object",
|
|
276
|
+
description: "Version summary",
|
|
277
|
+
properties: {
|
|
278
|
+
latest: { type: "string" },
|
|
279
|
+
latestStable: { type: "string" },
|
|
280
|
+
isOutdated: { type: "boolean" },
|
|
281
|
+
versionsBehind: { type: "number" },
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
breakingChanges: {
|
|
285
|
+
type: "object",
|
|
286
|
+
description: "Breaking changes summary",
|
|
287
|
+
properties: {
|
|
288
|
+
count: { type: "number" },
|
|
289
|
+
hasBreakingChanges: { type: "boolean" },
|
|
290
|
+
items: { type: "array" },
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
migration: { type: "object", description: "Migration guide if needed" },
|
|
294
|
+
urgency: {
|
|
295
|
+
type: "string",
|
|
296
|
+
description: "none|low|medium|high|critical",
|
|
297
|
+
},
|
|
298
|
+
recommendation: {
|
|
299
|
+
type: "string",
|
|
300
|
+
description: "Actionable recommendation",
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
annotations: {
|
|
305
|
+
readOnlyHint: true,
|
|
306
|
+
openWorldHint: true,
|
|
307
|
+
longRunningHint: true,
|
|
308
|
+
title: "⚡ Upgrade Check (Compound)",
|
|
309
|
+
category: "compound",
|
|
310
|
+
},
|
|
311
|
+
handler: upgradeCheck,
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
name: "midnight-get-repo-context",
|
|
315
|
+
description: "🚀 COMPOUND TOOL: Get everything needed to start working with a repository in ONE call. Combines version info + syntax reference + relevant examples. Use this at the start of a coding session instead of multiple individual calls. Saves ~50% tokens.",
|
|
316
|
+
inputSchema: {
|
|
317
|
+
type: "object",
|
|
318
|
+
properties: {
|
|
319
|
+
repo: {
|
|
320
|
+
type: "string",
|
|
321
|
+
description: "Repository name (e.g., 'compact', 'midnight-js')",
|
|
322
|
+
},
|
|
323
|
+
includeExamples: {
|
|
324
|
+
type: "boolean",
|
|
325
|
+
description: "Include example code snippets (default: true)",
|
|
326
|
+
},
|
|
327
|
+
includeSyntax: {
|
|
328
|
+
type: "boolean",
|
|
329
|
+
description: "Include syntax reference (default: true)",
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
required: ["repo"],
|
|
333
|
+
},
|
|
334
|
+
outputSchema: {
|
|
335
|
+
type: "object",
|
|
336
|
+
properties: {
|
|
337
|
+
repository: { type: "string", description: "Full repository path" },
|
|
338
|
+
quickStart: {
|
|
339
|
+
type: "object",
|
|
340
|
+
description: "Version and install command",
|
|
341
|
+
},
|
|
342
|
+
version: { type: "object", description: "Version details" },
|
|
343
|
+
syntax: { type: "object", description: "Syntax reference summary" },
|
|
344
|
+
examples: { type: "array", description: "Relevant examples" },
|
|
345
|
+
},
|
|
346
|
+
},
|
|
347
|
+
annotations: {
|
|
348
|
+
readOnlyHint: true,
|
|
349
|
+
openWorldHint: true,
|
|
350
|
+
longRunningHint: true,
|
|
351
|
+
title: "⚡ Get Repo Context (Compound)",
|
|
352
|
+
category: "compound",
|
|
353
|
+
},
|
|
354
|
+
handler: getFullRepoContext,
|
|
355
|
+
},
|
|
236
356
|
];
|
|
237
357
|
//# sourceMappingURL=tools.js.map
|
package/dist/tools/search.js
CHANGED
package/dist/types/mcp.d.ts
CHANGED
|
@@ -31,7 +31,27 @@ export interface ToolAnnotations {
|
|
|
31
31
|
* Human-readable title for display in UIs
|
|
32
32
|
*/
|
|
33
33
|
title?: string;
|
|
34
|
+
/**
|
|
35
|
+
* If true, this tool performs destructive or irreversible actions
|
|
36
|
+
* Clients should require human confirmation before execution
|
|
37
|
+
*/
|
|
38
|
+
destructiveHint?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* If true, this tool requires explicit human confirmation
|
|
41
|
+
* before execution (e.g., financial transactions, deletions)
|
|
42
|
+
*/
|
|
43
|
+
requiresConfirmation?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Tool category for progressive disclosure
|
|
46
|
+
* Allows clients to group/filter tools by domain
|
|
47
|
+
*/
|
|
48
|
+
category?: ToolCategory;
|
|
34
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Tool categories for progressive disclosure
|
|
52
|
+
* Clients can initially show categories, then expand to individual tools
|
|
53
|
+
*/
|
|
54
|
+
export type ToolCategory = "search" | "analyze" | "repository" | "versioning" | "generation" | "health" | "compound";
|
|
35
55
|
/**
|
|
36
56
|
* JSON Schema for structured tool outputs
|
|
37
57
|
* Enables better LLM parsing and IDE integration
|