midnight-mcp 0.2.2 → 0.2.4

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.
@@ -25,7 +25,7 @@ import {
25
25
  validateNumber,
26
26
  validateQuery,
27
27
  vectorStore
28
- } from "./chunk-HOWO4K5A.js";
28
+ } from "./chunk-KB6HV57P.js";
29
29
 
30
30
  // src/tools/search/schemas.ts
31
31
  import { z } from "zod";
@@ -48,6 +48,14 @@ var SearchDocsInputSchema = z.object({
48
48
  category: z.enum(["guides", "api", "concepts", "all"]).optional().default("all").describe("Filter by documentation category"),
49
49
  limit: z.number().optional().default(10)
50
50
  });
51
+ var FetchDocsInputSchema = z.object({
52
+ path: z.string().describe(
53
+ "Documentation page path (e.g., '/develop/faq', '/getting-started/installation', '/compact')"
54
+ ),
55
+ extractSection: z.string().optional().describe(
56
+ "Optional: Extract only a specific section by heading (e.g., 'General questions')"
57
+ )
58
+ });
51
59
 
52
60
  // src/tools/search/handlers.ts
53
61
  function validateSearchInput(query, limit) {
@@ -235,13 +243,16 @@ async function searchDocs(input) {
235
243
  );
236
244
  const cached = checkSearchCache(cacheKey);
237
245
  if (cached) return cached;
246
+ const freshnessHint = "For guaranteed freshness, use midnight-fetch-docs with the path from these results (e.g., /develop/faq)";
238
247
  const hostedResult = await tryHostedSearch(
239
248
  "docs",
240
249
  () => searchDocsHosted(sanitizedQuery, limit, input.category),
241
250
  cacheKey,
242
251
  warnings
243
252
  );
244
- if (hostedResult) return hostedResult.result;
253
+ if (hostedResult) {
254
+ return { ...hostedResult.result, hint: freshnessHint };
255
+ }
245
256
  const filter = {
246
257
  language: "markdown"
247
258
  };
@@ -261,10 +272,169 @@ async function searchDocs(input) {
261
272
  })),
262
273
  totalResults: results.length,
263
274
  query: sanitizedQuery,
264
- category: input.category
275
+ category: input.category,
276
+ hint: "For guaranteed freshness, use midnight-fetch-docs with the path from these results (e.g., /develop/faq)"
265
277
  };
266
278
  return finalizeResponse(response, cacheKey, warnings);
267
279
  }
280
+ var DOCS_BASE_URL = "https://docs.midnight.network";
281
+ var FETCH_TIMEOUT = 15e3;
282
+ var KNOWN_DOC_PATHS = [
283
+ "/develop/faq",
284
+ "/develop/getting-help",
285
+ "/develop/tutorial/building",
286
+ "/develop/how-midnight-works",
287
+ "/getting-started/installation",
288
+ "/getting-started/create-mn-app",
289
+ "/getting-started/deploy-mn-app",
290
+ "/getting-started/interact-with-mn-app",
291
+ "/compact",
292
+ "/learn/what-is-midnight",
293
+ "/learn/glossary",
294
+ "/develop/reference/midnight-api",
295
+ "/relnotes/overview",
296
+ "/blog"
297
+ ];
298
+ function extractContentFromHtml(html, extractSection) {
299
+ const titleMatch = html.match(/<title[^>]*>([^<]+)<\/title>/i);
300
+ const title = titleMatch ? titleMatch[1].replace(" | Midnight Docs", "").trim() : "Unknown";
301
+ const lastUpdatedMatch = html.match(
302
+ /<time[^>]*datetime="([^"]+)"[^>]*itemprop="dateModified"/i
303
+ );
304
+ const lastUpdated = lastUpdatedMatch ? lastUpdatedMatch[1] : void 0;
305
+ const articleMatch = html.match(/<article[^>]*>([\s\S]*?)<\/article>/i);
306
+ const articleHtml = articleMatch ? articleMatch[1] : html;
307
+ const headings = [];
308
+ const headingRegex = /<h([1-6])[^>]*class="[^"]*anchor[^"]*"[^>]*id="([^"]*)"[^>]*>([^<]*(?:<[^/][^>]*>[^<]*<\/[^>]+>)*[^<]*)/gi;
309
+ let headingMatch;
310
+ while ((headingMatch = headingRegex.exec(articleHtml)) !== null) {
311
+ const text = headingMatch[3].replace(/<[^>]+>/g, "").replace(/\u200B/g, "").replace(/​/g, "").trim();
312
+ if (text) {
313
+ headings.push({
314
+ level: parseInt(headingMatch[1]),
315
+ text,
316
+ id: headingMatch[2]
317
+ });
318
+ }
319
+ }
320
+ let content = articleHtml.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "").replace(/<svg[^>]*>[\s\S]*?<\/svg>/gi, "").replace(/<nav[^>]*class="[^"]*breadcrumb[^"]*"[^>]*>[\s\S]*?<\/nav>/gi, "").replace(/<footer[^>]*>[\s\S]*?<\/footer>/gi, "").replace(/<a[^>]*class="[^"]*hash-link[^"]*"[^>]*>[\s\S]*?<\/a>/gi, "").replace(/<button[^>]*>[\s\S]*?<\/button>/gi, "");
321
+ content = content.replace(/<h1[^>]*>/gi, "\n# ").replace(/<\/h1>/gi, "\n").replace(/<h2[^>]*>/gi, "\n## ").replace(/<\/h2>/gi, "\n").replace(/<h3[^>]*>/gi, "\n### ").replace(/<\/h3>/gi, "\n").replace(/<h4[^>]*>/gi, "\n#### ").replace(/<\/h4>/gi, "\n").replace(/<p[^>]*>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<ul[^>]*>/gi, "\n").replace(/<\/ul>/gi, "\n").replace(/<ol[^>]*>/gi, "\n").replace(/<\/ol>/gi, "\n").replace(/<li[^>]*>/gi, "\u2022 ").replace(/<\/li>/gi, "\n").replace(/<pre[^>]*><code[^>]*>/gi, "\n```\n").replace(/<\/code><\/pre>/gi, "\n```\n").replace(/<code[^>]*>/gi, "`").replace(/<\/code>/gi, "`").replace(/<a[^>]*href="([^"]*)"[^>]*>([^<]*)<\/a>/gi, "$2 ($1)").replace(/<strong[^>]*>/gi, "**").replace(/<\/strong>/gi, "**").replace(/<em[^>]*>/gi, "_").replace(/<\/em>/gi, "_").replace(/<[^>]+>/g, "").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#x27;/g, "'").replace(/&nbsp;/g, " ").replace(/\n{3,}/g, "\n\n").trim();
322
+ if (extractSection) {
323
+ const sectionLower = extractSection.toLowerCase();
324
+ const lines = content.split("\n");
325
+ const result = [];
326
+ let inSection = false;
327
+ let sectionLevel = 0;
328
+ for (const line of lines) {
329
+ const headerMatch = line.match(/^(#{1,4})\s+(.+)$/);
330
+ if (headerMatch) {
331
+ const level = headerMatch[1].length;
332
+ const headerText = headerMatch[2].toLowerCase();
333
+ if (headerText.includes(sectionLower)) {
334
+ inSection = true;
335
+ sectionLevel = level;
336
+ result.push(line);
337
+ } else if (inSection && level <= sectionLevel) {
338
+ break;
339
+ } else if (inSection) {
340
+ result.push(line);
341
+ }
342
+ } else if (inSection) {
343
+ result.push(line);
344
+ }
345
+ }
346
+ if (result.length > 0) {
347
+ content = result.join("\n").trim();
348
+ }
349
+ }
350
+ return { title, content, headings, lastUpdated };
351
+ }
352
+ async function fetchDocs(input) {
353
+ const { path: path2, extractSection } = input;
354
+ let normalizedPath = path2.startsWith("/") ? path2 : `/${path2}`;
355
+ normalizedPath = normalizedPath.replace(/\/$/, "");
356
+ if (/[<>"\s]/.test(normalizedPath)) {
357
+ return {
358
+ error: "Invalid path",
359
+ details: ["Path contains invalid characters"],
360
+ suggestion: `Use a clean path like '/develop/faq' or '/getting-started/installation'`
361
+ };
362
+ }
363
+ const url = `${DOCS_BASE_URL}${normalizedPath}`;
364
+ logger.debug("Fetching live documentation", { url, extractSection });
365
+ try {
366
+ const controller = new AbortController();
367
+ const timeoutId = setTimeout(() => controller.abort(), FETCH_TIMEOUT);
368
+ const response = await fetch(url, {
369
+ signal: controller.signal,
370
+ headers: {
371
+ "User-Agent": "midnight-mcp/1.0 (Documentation Fetcher)",
372
+ Accept: "text/html"
373
+ }
374
+ });
375
+ clearTimeout(timeoutId);
376
+ if (!response.ok) {
377
+ if (response.status === 404) {
378
+ return {
379
+ error: "Page not found",
380
+ path: normalizedPath,
381
+ suggestion: `Try one of these known paths: ${KNOWN_DOC_PATHS.slice(0, 5).join(", ")}`,
382
+ knownPaths: KNOWN_DOC_PATHS
383
+ };
384
+ }
385
+ return {
386
+ error: `Failed to fetch documentation: ${response.status} ${response.statusText}`,
387
+ path: normalizedPath,
388
+ suggestion: "Try again later or check if the URL is correct"
389
+ };
390
+ }
391
+ const html = await response.text();
392
+ if (!html.includes("<article") && !html.includes("<main")) {
393
+ return {
394
+ error: "Page returned but content not found",
395
+ path: normalizedPath,
396
+ suggestion: "The page may not have main content. Try a different path."
397
+ };
398
+ }
399
+ const { title, content, headings, lastUpdated } = extractContentFromHtml(
400
+ html,
401
+ extractSection
402
+ );
403
+ const MAX_CONTENT_LENGTH = 15e3;
404
+ const truncated = content.length > MAX_CONTENT_LENGTH;
405
+ const finalContent = truncated ? content.slice(0, MAX_CONTENT_LENGTH) + "\n\n[Content truncated...]" : content;
406
+ return {
407
+ title,
408
+ path: normalizedPath,
409
+ url,
410
+ content: finalContent,
411
+ headings: headings.length > 0 ? headings : void 0,
412
+ lastUpdated,
413
+ truncated,
414
+ contentLength: content.length,
415
+ note: extractSection ? `Extracted section matching: "${extractSection}"` : "Full page content"
416
+ };
417
+ } catch (error) {
418
+ if (error instanceof Error) {
419
+ if (error.name === "AbortError") {
420
+ return {
421
+ error: "Request timed out",
422
+ path: normalizedPath,
423
+ suggestion: "The documentation site may be slow. Try again or use midnight-search-docs for cached content."
424
+ };
425
+ }
426
+ return {
427
+ error: `Failed to fetch: ${error.message}`,
428
+ path: normalizedPath,
429
+ suggestion: "Check your network connection or try midnight-search-docs for cached content."
430
+ };
431
+ }
432
+ return {
433
+ error: "Unknown error fetching documentation",
434
+ path: normalizedPath
435
+ };
436
+ }
437
+ }
268
438
 
269
439
  // src/tools/search/tools.ts
270
440
  var searchResultSchema = {
@@ -324,7 +494,12 @@ var searchToolAnnotations = {
324
494
  var searchTools = [
325
495
  {
326
496
  name: "midnight-search-compact",
327
- description: "Semantic search across Compact smart contract code and patterns. Use this to find circuit definitions, witness functions, ledger declarations, and best practices for Midnight smart contracts.",
497
+ description: `Semantic search across Compact smart contract code and patterns. Use this to find circuit definitions, witness functions, ledger declarations, and best practices for Midnight smart contracts.
498
+
499
+ USAGE GUIDANCE:
500
+ \u2022 Call at most 2 times per question - if first search doesn't help, try different keywords
501
+ \u2022 For comprehensive results, combine with midnight-search-docs
502
+ \u2022 Use specific terms like "ledger", "circuit", "witness" for better matches`,
328
503
  inputSchema: {
329
504
  type: "object",
330
505
  properties: {
@@ -356,7 +531,12 @@ var searchTools = [
356
531
  },
357
532
  {
358
533
  name: "midnight-search-typescript",
359
- description: "Search TypeScript SDK code, types, and API implementations. Use this to find how to use the Midnight JavaScript SDK, type definitions, and integration patterns.",
534
+ description: `Search TypeScript SDK code, types, and API implementations. Use this to find how to use the Midnight JavaScript SDK, type definitions, and integration patterns.
535
+
536
+ USAGE GUIDANCE:
537
+ \u2022 Call at most 2 times per question - refine keywords rather than repeating
538
+ \u2022 For contract code, use midnight-search-compact instead
539
+ \u2022 Include "type" or "interface" in query for type definitions`,
360
540
  inputSchema: {
361
541
  type: "object",
362
542
  properties: {
@@ -388,7 +568,12 @@ var searchTools = [
388
568
  },
389
569
  {
390
570
  name: "midnight-search-docs",
391
- description: "Full-text search across official Midnight documentation. Use this to find guides, API documentation, and conceptual explanations about Midnight blockchain and the Compact language.",
571
+ description: `Full-text search across official Midnight documentation. Use this to find guides, API documentation, and conceptual explanations about Midnight blockchain and the Compact language.
572
+
573
+ USAGE GUIDANCE:
574
+ \u2022 Call at most 2 times per question - use different keywords if first search fails
575
+ \u2022 For code examples, combine with midnight-search-compact or midnight-search-typescript
576
+ \u2022 Use category filter to narrow results (guides, api, concepts)`,
392
577
  inputSchema: {
393
578
  type: "object",
394
579
  properties: {
@@ -414,6 +599,80 @@ var searchTools = [
414
599
  title: "Search Documentation"
415
600
  },
416
601
  handler: searchDocs
602
+ },
603
+ {
604
+ name: "midnight-fetch-docs",
605
+ description: `\u{1F310} LIVE FETCH: Retrieve latest documentation directly from docs.midnight.network (SSG-enabled).
606
+
607
+ Unlike midnight-search-docs which uses pre-indexed content, this tool fetches LIVE documentation pages in real-time. Use when you need:
608
+ \u2022 The absolute latest content (just updated docs)
609
+ \u2022 A specific page you know the path to
610
+ \u2022 Full page content rather than search snippets
611
+
612
+ COMMON PATHS:
613
+ \u2022 /develop/faq - Frequently asked questions
614
+ \u2022 /getting-started/installation - Installation guide
615
+ \u2022 /getting-started/create-mn-app - Create an MN app
616
+ \u2022 /compact - Compact language reference
617
+ \u2022 /develop/tutorial/building - Build guide
618
+ \u2022 /develop/reference/midnight-api - API documentation
619
+ \u2022 /learn/what-is-midnight - What is Midnight
620
+ \u2022 /blog - Dev diaries
621
+
622
+ USAGE GUIDANCE:
623
+ \u2022 Use extractSection to get only a specific heading (e.g., "Developer questions")
624
+ \u2022 Prefer midnight-search-docs for discovery, use this for known pages
625
+ \u2022 Content is truncated at 15KB for token efficiency`,
626
+ inputSchema: {
627
+ type: "object",
628
+ properties: {
629
+ path: {
630
+ type: "string",
631
+ description: "Documentation page path (e.g., '/develop/faq', '/getting-started/installation')"
632
+ },
633
+ extractSection: {
634
+ type: "string",
635
+ description: "Optional: Extract only a specific section by heading text"
636
+ }
637
+ },
638
+ required: ["path"]
639
+ },
640
+ outputSchema: {
641
+ type: "object",
642
+ properties: {
643
+ title: { type: "string", description: "Page title" },
644
+ path: { type: "string", description: "Normalized path" },
645
+ url: { type: "string", description: "Full URL" },
646
+ content: { type: "string", description: "Extracted page content" },
647
+ headings: {
648
+ type: "array",
649
+ description: "Page headings/table of contents",
650
+ items: {
651
+ type: "object",
652
+ properties: {
653
+ level: { type: "number" },
654
+ text: { type: "string" },
655
+ id: { type: "string" }
656
+ }
657
+ }
658
+ },
659
+ lastUpdated: { type: "string", description: "Last update timestamp" },
660
+ truncated: {
661
+ type: "boolean",
662
+ description: "Whether content was truncated"
663
+ }
664
+ },
665
+ required: ["title", "path", "content"],
666
+ description: "Live documentation page content"
667
+ },
668
+ annotations: {
669
+ readOnlyHint: true,
670
+ openWorldHint: true,
671
+ // Fetches from external URL
672
+ title: "\u{1F310} Fetch Live Docs",
673
+ category: "search"
674
+ },
675
+ handler: fetchDocs
417
676
  }
418
677
  ];
419
678
 
@@ -784,7 +1043,17 @@ var explainCircuitOutputSchema = {
784
1043
  var analyzeTools = [
785
1044
  {
786
1045
  name: "midnight-analyze-contract",
787
- description: "\u26A0\uFE0F STATIC ANALYSIS ONLY - Analyze contract structure and patterns. \u{1F6AB} THIS DOES NOT COMPILE THE CONTRACT. Cannot catch: sealed field rules, disclose() requirements, semantic errors. \u{1F449} Use 'midnight-extract-contract-structure' for pre-compilation checks. Use this for: understanding structure, security pattern analysis, recommendations. NEVER claim a contract 'works' or 'compiles' based on this tool alone.",
1046
+ description: `\u26A0\uFE0F STATIC ANALYSIS ONLY - Analyze contract structure and patterns.
1047
+ \u{1F6AB} THIS DOES NOT COMPILE THE CONTRACT. Cannot catch: sealed field rules, disclose() requirements, semantic errors.
1048
+ \u{1F449} Use 'midnight-extract-contract-structure' for pre-compilation checks.
1049
+
1050
+ Use this for: understanding structure, security pattern analysis, recommendations.
1051
+ NEVER claim a contract 'works' or 'compiles' based on this tool alone.
1052
+
1053
+ USAGE GUIDANCE:
1054
+ \u2022 Call once per contract - results are deterministic
1055
+ \u2022 For security review, also use midnight-review-contract (requires sampling)
1056
+ \u2022 Run before making changes, not repeatedly during iteration`,
788
1057
  inputSchema: {
789
1058
  type: "object",
790
1059
  properties: {
@@ -810,7 +1079,12 @@ var analyzeTools = [
810
1079
  },
811
1080
  {
812
1081
  name: "midnight-explain-circuit",
813
- description: "Explain what a specific Compact circuit does in plain language, including its zero-knowledge proof implications and privacy considerations.",
1082
+ description: `Explain what a specific Compact circuit does in plain language, including its zero-knowledge proof implications and privacy considerations.
1083
+
1084
+ USAGE GUIDANCE:
1085
+ \u2022 Call once per circuit - explanations are deterministic
1086
+ \u2022 Provide complete circuit code including parameters and body
1087
+ \u2022 For full contract analysis, use midnight-analyze-contract first`,
814
1088
  inputSchema: {
815
1089
  type: "object",
816
1090
  properties: {
@@ -6935,7 +7209,12 @@ function getInstallCommand(repoName, version) {
6935
7209
  var repositoryTools = [
6936
7210
  {
6937
7211
  name: "midnight-get-file",
6938
- description: "Retrieve a specific file from Midnight repositories. Use repository aliases like 'compact', 'midnight-js', 'counter', or 'bboard' for convenience.",
7212
+ description: `Retrieve a specific file from Midnight repositories. Use repository aliases like 'compact', 'midnight-js', 'counter', or 'bboard' for convenience.
7213
+
7214
+ USAGE GUIDANCE:
7215
+ \u2022 Use midnight-list-examples first if you're unsure which file to get
7216
+ \u2022 For searching across files, use midnight-search-* tools instead
7217
+ \u2022 Use 'ref' parameter to get specific versions (branch, tag, or commit)`,
6939
7218
  inputSchema: {
6940
7219
  type: "object",
6941
7220
  properties: {
@@ -8015,6 +8294,11 @@ var ListCategoryToolsInputSchema = z6.object({
8015
8294
  ]).describe("Category to list tools for"),
8016
8295
  includeSchemas: z6.boolean().optional().default(false).describe("Include input/output schemas")
8017
8296
  });
8297
+ var SuggestToolInputSchema = z6.object({
8298
+ intent: z6.string().describe(
8299
+ "What you want to accomplish (e.g., 'find example voting contract', 'check if my version is outdated', 'analyze my contract for security issues')"
8300
+ )
8301
+ });
8018
8302
  var CATEGORY_INFO = {
8019
8303
  search: {
8020
8304
  description: "Semantic search across Midnight codebase - find code by meaning, not keywords",
@@ -8022,7 +8306,33 @@ var CATEGORY_INFO = {
8022
8306
  "Find example implementations",
8023
8307
  "Search for patterns",
8024
8308
  "Discover relevant code"
8025
- ]
8309
+ ],
8310
+ intentKeywords: [
8311
+ // Core search verbs
8312
+ "find",
8313
+ "search",
8314
+ "look for",
8315
+ "locate",
8316
+ "discover",
8317
+ "explore",
8318
+ // Question patterns
8319
+ "example",
8320
+ "how to",
8321
+ "show me",
8322
+ "where is",
8323
+ "what is",
8324
+ "can i see",
8325
+ "give me",
8326
+ // Code-specific
8327
+ "pattern",
8328
+ "implementation",
8329
+ "code for",
8330
+ "sample",
8331
+ "snippet",
8332
+ "reference",
8333
+ "similar to"
8334
+ ],
8335
+ startWith: "midnight-search-compact"
8026
8336
  },
8027
8337
  analyze: {
8028
8338
  description: "Static analysis of Compact contracts - security, structure, patterns",
@@ -8030,7 +8340,34 @@ var CATEGORY_INFO = {
8030
8340
  "Security audit",
8031
8341
  "Code review",
8032
8342
  "Understand contract structure"
8033
- ]
8343
+ ],
8344
+ intentKeywords: [
8345
+ // Analysis verbs
8346
+ "analyze",
8347
+ "check",
8348
+ "inspect",
8349
+ "examine",
8350
+ "evaluate",
8351
+ "assess",
8352
+ // Security-related
8353
+ "security",
8354
+ "audit",
8355
+ "vulnerability",
8356
+ "vulnerabilities",
8357
+ "safe",
8358
+ "secure",
8359
+ "risk",
8360
+ // Understanding
8361
+ "review",
8362
+ "structure",
8363
+ "explain",
8364
+ "understand",
8365
+ "what does",
8366
+ "breakdown",
8367
+ "how does",
8368
+ "meaning of"
8369
+ ],
8370
+ startWith: "midnight-analyze-contract"
8034
8371
  },
8035
8372
  repository: {
8036
8373
  description: "Access repository files, examples, and recent updates",
@@ -8038,7 +8375,32 @@ var CATEGORY_INFO = {
8038
8375
  "Get specific files",
8039
8376
  "List examples",
8040
8377
  "Track repository changes"
8041
- ]
8378
+ ],
8379
+ intentKeywords: [
8380
+ // File access
8381
+ "get file",
8382
+ "fetch",
8383
+ "download",
8384
+ "read file",
8385
+ "open",
8386
+ "source code",
8387
+ "raw",
8388
+ // Listing
8389
+ "list",
8390
+ "examples",
8391
+ "show examples",
8392
+ "available",
8393
+ "what examples",
8394
+ // Repository state
8395
+ "recent",
8396
+ "updates",
8397
+ "changes",
8398
+ "commits",
8399
+ "history",
8400
+ "modified",
8401
+ "new files"
8402
+ ],
8403
+ startWith: "midnight-list-examples"
8042
8404
  },
8043
8405
  versioning: {
8044
8406
  description: "Version management, breaking changes, and migration assistance",
@@ -8047,15 +8409,92 @@ var CATEGORY_INFO = {
8047
8409
  "Plan upgrades",
8048
8410
  "Compare versions",
8049
8411
  "Get migration guides"
8050
- ]
8412
+ ],
8413
+ intentKeywords: [
8414
+ // Version-related
8415
+ "version",
8416
+ "upgrade",
8417
+ "update",
8418
+ "migrate",
8419
+ "migration",
8420
+ // State checks
8421
+ "breaking",
8422
+ "outdated",
8423
+ "latest",
8424
+ "current",
8425
+ "deprecated",
8426
+ "old",
8427
+ "new version",
8428
+ // Comparison
8429
+ "compare",
8430
+ "diff",
8431
+ "difference",
8432
+ "changed between",
8433
+ "what changed",
8434
+ // Guidance
8435
+ "syntax",
8436
+ "correct syntax",
8437
+ "reference"
8438
+ ],
8439
+ startWith: "midnight-upgrade-check"
8051
8440
  },
8052
8441
  generation: {
8053
8442
  description: "AI-powered code generation, review, and documentation (requires sampling)",
8054
- useCases: ["Generate contracts", "Review code", "Generate documentation"]
8443
+ useCases: ["Generate contracts", "Review code", "Generate documentation"],
8444
+ intentKeywords: [
8445
+ // Creation verbs
8446
+ "generate",
8447
+ "create",
8448
+ "write",
8449
+ "build",
8450
+ "make",
8451
+ "scaffold",
8452
+ "boilerplate",
8453
+ // AI-specific
8454
+ "ai",
8455
+ "help me write",
8456
+ "draft",
8457
+ "produce",
8458
+ // Documentation
8459
+ "document",
8460
+ "documentation",
8461
+ "explain code",
8462
+ "comment",
8463
+ // Review
8464
+ "improve",
8465
+ "suggest fix",
8466
+ "refactor"
8467
+ ],
8468
+ startWith: "midnight-generate-contract"
8055
8469
  },
8056
8470
  health: {
8057
8471
  description: "Server health checks and status monitoring",
8058
- useCases: ["Check API status", "Monitor rate limits", "Debug connectivity"]
8472
+ useCases: ["Check API status", "Monitor rate limits", "Debug connectivity"],
8473
+ intentKeywords: [
8474
+ // Status checks
8475
+ "health",
8476
+ "status",
8477
+ "working",
8478
+ "alive",
8479
+ "running",
8480
+ "up",
8481
+ // Problems
8482
+ "rate limit",
8483
+ "throttle",
8484
+ "quota",
8485
+ "error",
8486
+ "issue",
8487
+ "problem",
8488
+ // Debugging
8489
+ "debug",
8490
+ "connection",
8491
+ "connectivity",
8492
+ "api",
8493
+ "server",
8494
+ "not working",
8495
+ "broken"
8496
+ ],
8497
+ startWith: "midnight-health-check"
8059
8498
  },
8060
8499
  compound: {
8061
8500
  description: "Multi-step operations in a single call - saves tokens and reduces latency",
@@ -8063,9 +8502,425 @@ var CATEGORY_INFO = {
8063
8502
  "Full upgrade analysis",
8064
8503
  "Get complete repo context",
8065
8504
  "One-shot operations"
8066
- ]
8505
+ ],
8506
+ intentKeywords: [
8507
+ // Completeness
8508
+ "everything",
8509
+ "all",
8510
+ "complete",
8511
+ "full",
8512
+ "comprehensive",
8513
+ "entire",
8514
+ "whole",
8515
+ // Starting points
8516
+ "start",
8517
+ "begin",
8518
+ "setup",
8519
+ "getting started",
8520
+ "onboard",
8521
+ "new project",
8522
+ // Efficiency
8523
+ "one shot",
8524
+ "single call",
8525
+ "efficient",
8526
+ "quick",
8527
+ "fast"
8528
+ ],
8529
+ startWith: "midnight-get-repo-context"
8067
8530
  }
8068
8531
  };
8532
+ var INTENT_TO_TOOL = [
8533
+ // Examples & Getting Started
8534
+ {
8535
+ patterns: [
8536
+ "counter",
8537
+ "simple",
8538
+ "beginner",
8539
+ "start",
8540
+ "hello world",
8541
+ "basic",
8542
+ "first contract",
8543
+ "tutorial",
8544
+ "starter"
8545
+ ],
8546
+ tool: "midnight-list-examples",
8547
+ reason: "Lists all example contracts including the beginner-friendly counter"
8548
+ },
8549
+ {
8550
+ patterns: [
8551
+ "getting started",
8552
+ "begin",
8553
+ "first time",
8554
+ "new to midnight",
8555
+ "learn midnight",
8556
+ "introduction",
8557
+ "overview",
8558
+ "onboarding",
8559
+ "setup project"
8560
+ ],
8561
+ tool: "midnight-get-repo-context",
8562
+ reason: "Get everything needed to start working (compound tool)"
8563
+ },
8564
+ // Domain-specific searches
8565
+ {
8566
+ patterns: [
8567
+ "voting",
8568
+ "governance",
8569
+ "election",
8570
+ "ballot",
8571
+ "poll",
8572
+ "referendum",
8573
+ "proposal",
8574
+ "dao"
8575
+ ],
8576
+ tool: "midnight-search-compact",
8577
+ reason: "Search for voting/governance-related patterns and examples"
8578
+ },
8579
+ {
8580
+ patterns: [
8581
+ "token",
8582
+ "transfer",
8583
+ "balance",
8584
+ "mint",
8585
+ "burn",
8586
+ "erc20",
8587
+ "fungible",
8588
+ "asset",
8589
+ "coin"
8590
+ ],
8591
+ tool: "midnight-search-compact",
8592
+ reason: "Search for token-related implementations"
8593
+ },
8594
+ {
8595
+ patterns: [
8596
+ "nft",
8597
+ "non-fungible",
8598
+ "collectible",
8599
+ "unique",
8600
+ "ownership",
8601
+ "deed"
8602
+ ],
8603
+ tool: "midnight-search-compact",
8604
+ reason: "Search for NFT and non-fungible token patterns"
8605
+ },
8606
+ {
8607
+ patterns: ["auction", "bid", "bidding", "marketplace", "sale", "exchange"],
8608
+ tool: "midnight-search-compact",
8609
+ reason: "Search for auction and marketplace patterns"
8610
+ },
8611
+ {
8612
+ patterns: [
8613
+ "access control",
8614
+ "permission",
8615
+ "role",
8616
+ "admin",
8617
+ "owner",
8618
+ "authorization",
8619
+ "acl"
8620
+ ],
8621
+ tool: "midnight-search-compact",
8622
+ reason: "Search for access control and permission patterns"
8623
+ },
8624
+ // Security & Analysis
8625
+ {
8626
+ patterns: [
8627
+ "security",
8628
+ "vulnerability",
8629
+ "audit",
8630
+ "safe",
8631
+ "attack",
8632
+ "exploit",
8633
+ "risk",
8634
+ "issue",
8635
+ "bug"
8636
+ ],
8637
+ tool: "midnight-analyze-contract",
8638
+ reason: "Performs security analysis on your contract code"
8639
+ },
8640
+ {
8641
+ patterns: [
8642
+ "circuit",
8643
+ "zk",
8644
+ "zero knowledge",
8645
+ "proof",
8646
+ "privacy",
8647
+ "private",
8648
+ "witness",
8649
+ "constraint"
8650
+ ],
8651
+ tool: "midnight-explain-circuit",
8652
+ reason: "Explains circuit logic and ZK implications"
8653
+ },
8654
+ // Version & Upgrade
8655
+ {
8656
+ patterns: [
8657
+ "upgrade",
8658
+ "update",
8659
+ "outdated",
8660
+ "new version",
8661
+ "breaking",
8662
+ "deprecat",
8663
+ "migrate",
8664
+ "migration guide"
8665
+ ],
8666
+ tool: "midnight-upgrade-check",
8667
+ reason: "Complete upgrade analysis in one call (compound tool)"
8668
+ },
8669
+ {
8670
+ patterns: [
8671
+ "syntax",
8672
+ "correct",
8673
+ "how to write",
8674
+ "format",
8675
+ "proper way",
8676
+ "right way",
8677
+ "convention",
8678
+ "best practice"
8679
+ ],
8680
+ tool: "midnight-get-latest-syntax",
8681
+ reason: "Get authoritative syntax reference to avoid mistakes"
8682
+ },
8683
+ {
8684
+ patterns: [
8685
+ "what changed",
8686
+ "changelog",
8687
+ "release notes",
8688
+ "difference between",
8689
+ "compare versions"
8690
+ ],
8691
+ tool: "midnight-compare-syntax",
8692
+ reason: "Compare syntax/features between versions"
8693
+ },
8694
+ // SDK & TypeScript
8695
+ {
8696
+ patterns: [
8697
+ "sdk",
8698
+ "typescript",
8699
+ "javascript",
8700
+ "api",
8701
+ "integration",
8702
+ "client",
8703
+ "frontend",
8704
+ "dapp",
8705
+ "web3"
8706
+ ],
8707
+ tool: "midnight-search-typescript",
8708
+ reason: "Search TypeScript SDK code and types"
8709
+ },
8710
+ {
8711
+ patterns: ["type", "types", "interface", "typing", "definition"],
8712
+ tool: "midnight-search-typescript",
8713
+ reason: "Search TypeScript type definitions"
8714
+ },
8715
+ // Documentation
8716
+ {
8717
+ patterns: [
8718
+ "docs",
8719
+ "documentation",
8720
+ "guide",
8721
+ "tutorial",
8722
+ "learn",
8723
+ "concept",
8724
+ "explanation",
8725
+ "manual"
8726
+ ],
8727
+ tool: "midnight-search-docs",
8728
+ reason: "Search official Midnight documentation"
8729
+ },
8730
+ {
8731
+ patterns: [
8732
+ "fetch docs",
8733
+ "get docs",
8734
+ "latest docs",
8735
+ "live docs",
8736
+ "docs page",
8737
+ "faq",
8738
+ "installation guide",
8739
+ "getting started page"
8740
+ ],
8741
+ tool: "midnight-fetch-docs",
8742
+ reason: "Fetch live documentation directly from docs.midnight.network"
8743
+ },
8744
+ // Code Generation
8745
+ {
8746
+ patterns: [
8747
+ "generate",
8748
+ "create contract",
8749
+ "write contract",
8750
+ "new contract",
8751
+ "scaffold",
8752
+ "template",
8753
+ "boilerplate"
8754
+ ],
8755
+ tool: "midnight-generate-contract",
8756
+ reason: "AI-powered contract generation (requires sampling)"
8757
+ },
8758
+ {
8759
+ patterns: [
8760
+ "review",
8761
+ "check my code",
8762
+ "is this correct",
8763
+ "feedback",
8764
+ "improve my",
8765
+ "fix my"
8766
+ ],
8767
+ tool: "midnight-review-contract",
8768
+ reason: "AI-powered code review (requires sampling)"
8769
+ },
8770
+ {
8771
+ patterns: [
8772
+ "document my",
8773
+ "add comments",
8774
+ "explain my code",
8775
+ "generate docs"
8776
+ ],
8777
+ tool: "midnight-generate-documentation",
8778
+ reason: "AI-powered documentation generation (requires sampling)"
8779
+ },
8780
+ // Health & Debugging
8781
+ {
8782
+ patterns: [
8783
+ "not working",
8784
+ "error",
8785
+ "broken",
8786
+ "failing",
8787
+ "issue with server",
8788
+ "api down"
8789
+ ],
8790
+ tool: "midnight-health-check",
8791
+ reason: "Check server status and connectivity"
8792
+ },
8793
+ {
8794
+ patterns: ["rate limit", "quota", "throttle", "429", "too many requests"],
8795
+ tool: "midnight-health-check",
8796
+ reason: "Check rate limit status and remaining quota"
8797
+ },
8798
+ {
8799
+ patterns: ["server status", "api status", "is api up", "check server"],
8800
+ tool: "midnight-get-status",
8801
+ reason: "Get detailed server and API status information"
8802
+ },
8803
+ {
8804
+ patterns: [
8805
+ "mcp version",
8806
+ "server version",
8807
+ "what version am i using",
8808
+ "installed version"
8809
+ ],
8810
+ tool: "midnight-check-version",
8811
+ reason: "Check the current MCP server version"
8812
+ },
8813
+ {
8814
+ patterns: [
8815
+ "auto update",
8816
+ "keep updated",
8817
+ "automatic updates",
8818
+ "stay current",
8819
+ "update automatically"
8820
+ ],
8821
+ tool: "midnight-auto-update-config",
8822
+ reason: "Configure automatic syntax updates"
8823
+ },
8824
+ // Repository & Files
8825
+ {
8826
+ patterns: [
8827
+ "recent changes",
8828
+ "latest commits",
8829
+ "what's new",
8830
+ "updates",
8831
+ "modified",
8832
+ "new features",
8833
+ "repo activity"
8834
+ ],
8835
+ tool: "midnight-get-latest-updates",
8836
+ reason: "See recent repository activity and changes"
8837
+ },
8838
+ {
8839
+ patterns: ["read file", "get file", "show file", "file content", "source"],
8840
+ tool: "midnight-get-file",
8841
+ reason: "Fetch specific file content from repository"
8842
+ },
8843
+ {
8844
+ patterns: [
8845
+ "file from version",
8846
+ "old version of file",
8847
+ "file at version",
8848
+ "historical file",
8849
+ "previous version"
8850
+ ],
8851
+ tool: "midnight-get-file-at-version",
8852
+ reason: "Get a file as it existed in a specific version"
8853
+ },
8854
+ // Version Comparison & Info
8855
+ {
8856
+ patterns: [
8857
+ "what version",
8858
+ "current version",
8859
+ "latest version",
8860
+ "version number",
8861
+ "compact version"
8862
+ ],
8863
+ tool: "midnight-get-version-info",
8864
+ reason: "Get version information for Midnight components"
8865
+ },
8866
+ {
8867
+ patterns: [
8868
+ "breaking changes",
8869
+ "what broke",
8870
+ "incompatible",
8871
+ "api changes",
8872
+ "deprecations"
8873
+ ],
8874
+ tool: "midnight-check-breaking-changes",
8875
+ reason: "Check for breaking changes between versions"
8876
+ },
8877
+ {
8878
+ patterns: [
8879
+ "how to migrate",
8880
+ "migration steps",
8881
+ "upgrade guide",
8882
+ "migration path",
8883
+ "move to new version"
8884
+ ],
8885
+ tool: "midnight-get-migration-guide",
8886
+ reason: "Get step-by-step migration guidance"
8887
+ },
8888
+ {
8889
+ patterns: [
8890
+ "compare syntax",
8891
+ "syntax diff",
8892
+ "syntax between versions",
8893
+ "syntax comparison"
8894
+ ],
8895
+ tool: "midnight-compare-syntax",
8896
+ reason: "Compare Compact syntax between two versions"
8897
+ },
8898
+ // Contract Structure
8899
+ {
8900
+ patterns: [
8901
+ "extract structure",
8902
+ "contract structure",
8903
+ "parse contract",
8904
+ "contract outline",
8905
+ "functions in contract",
8906
+ "contract anatomy"
8907
+ ],
8908
+ tool: "midnight-extract-contract-structure",
8909
+ reason: "Extract and analyze contract structure (functions, state, etc.)"
8910
+ },
8911
+ // Meta/Discovery (fallback patterns)
8912
+ {
8913
+ patterns: [
8914
+ "what tools",
8915
+ "available tools",
8916
+ "list tools",
8917
+ "show tools",
8918
+ "tool list"
8919
+ ],
8920
+ tool: "midnight-list-tool-categories",
8921
+ reason: "Browse available tool categories"
8922
+ }
8923
+ ];
8069
8924
 
8070
8925
  // src/tools/meta/handlers.ts
8071
8926
  var _metaTools = [];
@@ -8156,6 +9011,76 @@ function generateCategorySuggestion(category) {
8156
9011
  return `Use these tools for ${CATEGORY_INFO[category]?.useCases[0] || "related operations"}.`;
8157
9012
  }
8158
9013
  }
9014
+ async function suggestTool(input) {
9015
+ const intentLower = input.intent.toLowerCase();
9016
+ const matchedTools = [];
9017
+ for (const mapping of INTENT_TO_TOOL) {
9018
+ const matchCount = mapping.patterns.filter(
9019
+ (p) => intentLower.includes(p.toLowerCase())
9020
+ ).length;
9021
+ if (matchCount > 0) {
9022
+ matchedTools.push({
9023
+ tool: mapping.tool,
9024
+ reason: mapping.reason,
9025
+ confidence: matchCount >= 2 ? "high" : "medium"
9026
+ });
9027
+ }
9028
+ }
9029
+ const matchedCategories = [];
9030
+ for (const [category, info] of Object.entries(CATEGORY_INFO)) {
9031
+ const matchCount = info.intentKeywords.filter(
9032
+ (k) => intentLower.includes(k.toLowerCase())
9033
+ ).length;
9034
+ if (matchCount > 0 && info.startWith) {
9035
+ matchedCategories.push({
9036
+ category,
9037
+ startWith: info.startWith,
9038
+ description: info.description,
9039
+ confidence: matchCount >= 2 ? "medium" : "low"
9040
+ });
9041
+ }
9042
+ }
9043
+ const confidenceOrder = { high: 0, medium: 1, low: 2 };
9044
+ matchedTools.sort(
9045
+ (a, b) => confidenceOrder[a.confidence] - confidenceOrder[b.confidence]
9046
+ );
9047
+ if (matchedTools.length === 0 && matchedCategories.length === 0) {
9048
+ return {
9049
+ intent: input.intent,
9050
+ suggestions: [],
9051
+ fallback: {
9052
+ tool: "midnight-list-tool-categories",
9053
+ reason: "No specific match found. Start by exploring available tool categories."
9054
+ },
9055
+ tip: "Try rephrasing your intent with keywords like: search, analyze, generate, upgrade, version, security, example"
9056
+ };
9057
+ }
9058
+ const seenTools = /* @__PURE__ */ new Set();
9059
+ const suggestions = [];
9060
+ for (const match of matchedTools) {
9061
+ if (!seenTools.has(match.tool)) {
9062
+ seenTools.add(match.tool);
9063
+ suggestions.push(match);
9064
+ }
9065
+ }
9066
+ for (const match of matchedCategories) {
9067
+ if (!seenTools.has(match.startWith)) {
9068
+ seenTools.add(match.startWith);
9069
+ suggestions.push({
9070
+ tool: match.startWith,
9071
+ reason: `Recommended starting tool for ${match.category}: ${match.description}`,
9072
+ confidence: match.confidence
9073
+ });
9074
+ }
9075
+ }
9076
+ const topSuggestions = suggestions.slice(0, 3);
9077
+ return {
9078
+ intent: input.intent,
9079
+ suggestions: topSuggestions,
9080
+ primaryRecommendation: topSuggestions[0],
9081
+ tip: topSuggestions[0]?.confidence === "high" ? `Strong match! Use ${topSuggestions[0].tool} for this task.` : "Multiple tools may help. Consider the suggestions based on your specific needs."
9082
+ };
9083
+ }
8159
9084
 
8160
9085
  // src/tools/meta/tools.ts
8161
9086
  var listCategoriesOutputSchema = {
@@ -8219,10 +9144,39 @@ var listCategoryToolsOutputSchema = {
8219
9144
  required: ["category", "tools"],
8220
9145
  description: "Tools within a specific category"
8221
9146
  };
9147
+ var suggestToolOutputSchema = {
9148
+ type: "object",
9149
+ properties: {
9150
+ intent: { type: "string", description: "The original intent" },
9151
+ suggestions: {
9152
+ type: "array",
9153
+ description: "Suggested tools ranked by relevance",
9154
+ items: {
9155
+ type: "object",
9156
+ properties: {
9157
+ tool: { type: "string", description: "Tool name" },
9158
+ reason: { type: "string", description: "Why this tool is suggested" },
9159
+ confidence: {
9160
+ type: "string",
9161
+ enum: ["high", "medium", "low"],
9162
+ description: "Match confidence"
9163
+ }
9164
+ }
9165
+ }
9166
+ },
9167
+ primaryRecommendation: {
9168
+ type: "object",
9169
+ description: "Top recommendation"
9170
+ },
9171
+ tip: { type: "string", description: "Helpful tip" }
9172
+ },
9173
+ required: ["intent", "suggestions"],
9174
+ description: "Tool suggestions based on intent"
9175
+ };
8222
9176
  var metaTools = [
8223
9177
  {
8224
9178
  name: "midnight-list-tool-categories",
8225
- description: "\u{1F4CB} DISCOVERY TOOL: List available tool categories for progressive exploration. Use this FIRST to understand what capabilities are available, then drill into specific categories with midnight-list-category-tools. Reduces cognitive load by organizing 25 tools into 7 logical groups.",
9179
+ description: "\u{1F4CB} DISCOVERY TOOL: List available tool categories for progressive exploration. Use this FIRST to understand what capabilities are available, then drill into specific categories with midnight-list-category-tools. Reduces cognitive load by organizing 28 tools into 7 logical groups.",
8226
9180
  inputSchema: {
8227
9181
  type: "object",
8228
9182
  properties: {
@@ -8276,6 +9230,41 @@ var metaTools = [
8276
9230
  category: "health"
8277
9231
  },
8278
9232
  handler: listCategoryTools
9233
+ },
9234
+ {
9235
+ name: "midnight-suggest-tool",
9236
+ description: `\u{1F3AF} SMART DISCOVERY: Describe what you want to do in natural language, and get tool recommendations.
9237
+
9238
+ EXAMPLES:
9239
+ \u2022 "I want to find example voting contracts" \u2192 midnight-search-compact
9240
+ \u2022 "Check if my version is outdated" \u2192 midnight-upgrade-check
9241
+ \u2022 "Analyze my contract for security issues" \u2192 midnight-analyze-contract
9242
+ \u2022 "I'm new to Midnight and want to get started" \u2192 midnight-get-repo-context
9243
+
9244
+ This tool matches your intent against known patterns and suggests the most appropriate tools with confidence levels.
9245
+
9246
+ USAGE GUIDANCE:
9247
+ \u2022 Call once with your intent - no need to call repeatedly
9248
+ \u2022 More specific intents get better matches
9249
+ \u2022 Use the primaryRecommendation for the best match`,
9250
+ inputSchema: {
9251
+ type: "object",
9252
+ properties: {
9253
+ intent: {
9254
+ type: "string",
9255
+ description: "What you want to accomplish (natural language description)"
9256
+ }
9257
+ },
9258
+ required: ["intent"]
9259
+ },
9260
+ outputSchema: suggestToolOutputSchema,
9261
+ annotations: {
9262
+ readOnlyHint: true,
9263
+ idempotentHint: true,
9264
+ title: "\u{1F3AF} Suggest Tool",
9265
+ category: "health"
9266
+ },
9267
+ handler: suggestTool
8279
9268
  }
8280
9269
  ];
8281
9270
  setMetaTools(metaTools);
@@ -8303,4 +9292,4 @@ export {
8303
9292
  startServer,
8304
9293
  startHttpServer
8305
9294
  };
8306
- //# sourceMappingURL=chunk-S7G4OHA4.js.map
9295
+ //# sourceMappingURL=chunk-5DMOVW6Q.js.map