midnight-mcp 0.2.6 → 0.2.7

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/bin.js CHANGED
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  startHttpServer,
4
4
  startServer
5
- } from "./chunk-L5CXYFG2.js";
5
+ } from "./chunk-2YCZSMDD.js";
6
6
  import {
7
7
  setOutputFormat
8
- } from "./chunk-WC2FPYQO.js";
8
+ } from "./chunk-M3QHVBQV.js";
9
9
 
10
10
  // src/bin.ts
11
11
  import { config } from "dotenv";
@@ -13,7 +13,7 @@ import { resolve } from "path";
13
13
  import yargs from "yargs";
14
14
  import { hideBin } from "yargs/helpers";
15
15
  config({ path: resolve(process.cwd(), ".env") });
16
- var CURRENT_VERSION = "0.2.6";
16
+ var CURRENT_VERSION = "0.2.7";
17
17
  process.on("uncaughtException", (error) => {
18
18
  console.error("Uncaught exception:", error);
19
19
  process.exit(1);
@@ -25,7 +25,7 @@ import {
25
25
  validateNumber,
26
26
  validateQuery,
27
27
  vectorStore
28
- } from "./chunk-WC2FPYQO.js";
28
+ } from "./chunk-M3QHVBQV.js";
29
29
 
30
30
  // src/tools/search/schemas.ts
31
31
  import { z } from "zod";
@@ -1115,7 +1115,13 @@ var GetFileInputSchema = z3.object({
1115
1115
  "Repository name (e.g., 'compact', 'midnight-js', 'example-counter')"
1116
1116
  ),
1117
1117
  path: z3.string().describe("File path within repository"),
1118
- ref: z3.string().optional().describe("Branch, tag, or commit SHA (default: main)")
1118
+ ref: z3.string().optional().describe("Branch, tag, or commit SHA (default: main)"),
1119
+ startLine: z3.number().int().positive().optional().describe(
1120
+ "Start line number (1-based, inclusive). Use to request specific sections of large files."
1121
+ ),
1122
+ endLine: z3.number().int().positive().optional().describe(
1123
+ "End line number (1-based, inclusive). Use with startLine to get a specific range."
1124
+ )
1119
1125
  });
1120
1126
  var ListExamplesInputSchema = z3.object({
1121
1127
  category: z3.enum(["counter", "bboard", "token", "voting", "all"]).optional().default("all").describe("Filter by example type")
@@ -6525,8 +6531,112 @@ function resolveRepo(repoName) {
6525
6531
  }
6526
6532
  return null;
6527
6533
  }
6534
+ var MAX_FILE_CONTENT_LENGTH = 5e4;
6535
+ var TRUNCATION_RATIOS = {
6536
+ compact: { top: 0.8, bottom: 0.2 },
6537
+ // 40KB top, 10KB bottom
6538
+ typescript: { top: 0.5, bottom: 0.5 },
6539
+ // 25KB each
6540
+ javascript: { top: 0.5, bottom: 0.5 },
6541
+ default: { top: 0.6, bottom: 0.4 }
6542
+ // Slight preference for top
6543
+ };
6544
+ function detectLanguage(filePath) {
6545
+ const ext = filePath.split(".").pop()?.toLowerCase();
6546
+ switch (ext) {
6547
+ case "compact":
6548
+ return "compact";
6549
+ case "ts":
6550
+ case "tsx":
6551
+ return "typescript";
6552
+ case "js":
6553
+ case "jsx":
6554
+ case "mjs":
6555
+ return "javascript";
6556
+ default:
6557
+ return "default";
6558
+ }
6559
+ }
6560
+ function smartTruncate(content, filePath = "", maxLength = MAX_FILE_CONTENT_LENGTH) {
6561
+ if (content.length <= maxLength) {
6562
+ return { content, truncated: false };
6563
+ }
6564
+ const language = detectLanguage(filePath);
6565
+ const ratio = TRUNCATION_RATIOS[language] || TRUNCATION_RATIOS.default;
6566
+ const lines = content.split("\n");
6567
+ const totalLines = lines.length;
6568
+ const topLength = Math.floor(maxLength * ratio.top);
6569
+ const bottomLength = maxLength - topLength;
6570
+ const firstPart = content.slice(0, topLength);
6571
+ const lastPart = content.slice(-bottomLength);
6572
+ const omittedBytes = content.length - maxLength;
6573
+ const firstPartLines = firstPart.split("\n").length;
6574
+ const lastPartLines = lastPart.split("\n").length;
6575
+ const omittedStartLine = firstPartLines + 1;
6576
+ const omittedEndLine = totalLines - lastPartLines;
6577
+ const languageContext = language === "compact" ? "Compact files: pragma and imports preserved at top (critical for compilation)" : language === "typescript" || language === "javascript" ? "TS/JS files: balanced truncation preserves imports AND exports" : "Balanced truncation applied";
6578
+ const truncatedContent = firstPart + `
6579
+
6580
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
6581
+ CONTENT TRUNCATED: Lines ${omittedStartLine}-${omittedEndLine} omitted (${omittedBytes.toLocaleString()} bytes)
6582
+ ${languageContext}
6583
+
6584
+ To get the omitted content, call this tool again with:
6585
+ - startLine: ${omittedStartLine}, endLine: ${Math.min(omittedStartLine + 200, omittedEndLine)} (first part of omitted)
6586
+ - startLine: ${Math.max(omittedStartLine, omittedEndLine - 200)}, endLine: ${omittedEndLine} (last part of omitted)
6587
+
6588
+ Or request the full middle section:
6589
+ - startLine: ${omittedStartLine}, endLine: ${omittedEndLine}
6590
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
6591
+
6592
+ ` + lastPart;
6593
+ return {
6594
+ content: truncatedContent,
6595
+ truncated: true,
6596
+ truncationInfo: {
6597
+ originalSize: content.length,
6598
+ keptBytes: maxLength,
6599
+ omittedBytes,
6600
+ keptLineRanges: [
6601
+ { start: 1, end: firstPartLines },
6602
+ { start: totalLines - lastPartLines + 1, end: totalLines }
6603
+ ],
6604
+ omittedLineRange: { start: omittedStartLine, end: omittedEndLine },
6605
+ language,
6606
+ ratioUsed: ratio
6607
+ },
6608
+ agentGuidance: {
6609
+ whatYouHave: `Lines 1-${firstPartLines} (${Math.round(ratio.top * 100)}% from top) and lines ${totalLines - lastPartLines + 1}-${totalLines} (${Math.round(ratio.bottom * 100)}% from bottom)`,
6610
+ whatIsMissing: `Lines ${omittedStartLine}-${omittedEndLine} (${omittedEndLine - omittedStartLine + 1} lines, ${omittedBytes.toLocaleString()} bytes)`,
6611
+ howToGetMore: [
6612
+ `Call midnight-get-file again with startLine and endLine parameters`,
6613
+ `The omitted content is in the middle of the file`,
6614
+ `You can request it in chunks (e.g., 200 lines at a time) or all at once`
6615
+ ],
6616
+ suggestedNextCalls: [
6617
+ {
6618
+ startLine: omittedStartLine,
6619
+ endLine: Math.min(omittedStartLine + 199, omittedEndLine),
6620
+ reason: "First chunk of omitted content"
6621
+ },
6622
+ ...omittedEndLine - omittedStartLine > 200 ? [
6623
+ {
6624
+ startLine: Math.max(omittedStartLine, omittedEndLine - 199),
6625
+ endLine: omittedEndLine,
6626
+ reason: "Last chunk of omitted content (may overlap if file is small)"
6627
+ }
6628
+ ] : []
6629
+ ]
6630
+ }
6631
+ };
6632
+ }
6528
6633
  async function getFile(input) {
6529
- logger.debug("Getting file", { repo: input.repo, path: input.path });
6634
+ logger.debug("Getting file", {
6635
+ repo: input.repo,
6636
+ path: input.path,
6637
+ startLine: input.startLine,
6638
+ endLine: input.endLine
6639
+ });
6530
6640
  const repoInfo = resolveRepo(input.repo);
6531
6641
  if (!repoInfo) {
6532
6642
  return SelfCorrectionHints.UNKNOWN_REPO(
@@ -6546,12 +6656,53 @@ async function getFile(input) {
6546
6656
  `${repoInfo.owner}/${repoInfo.repo}`
6547
6657
  );
6548
6658
  }
6659
+ let content = file.content;
6660
+ let totalLines = content.split("\n").length;
6661
+ let lineRange;
6662
+ if (input.startLine || input.endLine) {
6663
+ const lines = content.split("\n");
6664
+ const start = Math.max(1, input.startLine || 1);
6665
+ const end = Math.min(lines.length, input.endLine || lines.length);
6666
+ if (start > end) {
6667
+ return {
6668
+ error: `Invalid line range: startLine (${start}) > endLine (${end})`,
6669
+ suggestion: "Ensure startLine is less than or equal to endLine"
6670
+ };
6671
+ }
6672
+ content = lines.slice(start - 1, end).join("\n");
6673
+ lineRange = { start, end };
6674
+ logger.debug("Extracted line range", {
6675
+ start,
6676
+ end,
6677
+ extractedLines: end - start + 1
6678
+ });
6679
+ }
6680
+ const truncateResult = smartTruncate(content, input.path);
6681
+ if (truncateResult.truncated) {
6682
+ logger.info("File content truncated", {
6683
+ repository: `${repoInfo.owner}/${repoInfo.repo}`,
6684
+ path: input.path,
6685
+ language: truncateResult.truncationInfo?.language,
6686
+ originalSize: file.size,
6687
+ contentLength: content.length,
6688
+ omittedLines: truncateResult.truncationInfo?.omittedLineRange
6689
+ });
6690
+ }
6549
6691
  return {
6550
- content: file.content,
6692
+ content: truncateResult.content,
6551
6693
  path: file.path,
6552
6694
  repository: `${repoInfo.owner}/${repoInfo.repo}`,
6553
6695
  sha: file.sha,
6554
6696
  size: file.size,
6697
+ totalLines,
6698
+ ...lineRange && { lineRange },
6699
+ truncated: truncateResult.truncated,
6700
+ ...truncateResult.truncationInfo && {
6701
+ truncationInfo: truncateResult.truncationInfo
6702
+ },
6703
+ ...truncateResult.agentGuidance && {
6704
+ agentGuidance: truncateResult.agentGuidance
6705
+ },
6555
6706
  url: `https://github.com/${repoInfo.owner}/${repoInfo.repo}/blob/${input.ref || "main"}/${file.path}`
6556
6707
  };
6557
6708
  }
@@ -6748,11 +6899,29 @@ async function getFileAtVersion(input) {
6748
6899
  `File not found: ${input.path} at version ${input.version} in ${repoName}`
6749
6900
  );
6750
6901
  }
6902
+ const truncateResult = smartTruncate(result.content, input.path);
6903
+ if (truncateResult.truncated) {
6904
+ logger.info("File content truncated (versioned)", {
6905
+ repository: `${resolved.owner}/${resolved.repo}`,
6906
+ path: input.path,
6907
+ version: input.version,
6908
+ language: truncateResult.truncationInfo?.language,
6909
+ contentLength: result.content.length,
6910
+ omittedLines: truncateResult.truncationInfo?.omittedLineRange
6911
+ });
6912
+ }
6751
6913
  return {
6752
6914
  repository: `${resolved.owner}/${resolved.repo}`,
6753
6915
  path: input.path,
6754
6916
  version: result.version,
6755
- content: result.content,
6917
+ content: truncateResult.content,
6918
+ truncated: truncateResult.truncated,
6919
+ ...truncateResult.truncationInfo && {
6920
+ truncationInfo: truncateResult.truncationInfo
6921
+ },
6922
+ ...truncateResult.agentGuidance && {
6923
+ agentGuidance: truncateResult.agentGuidance
6924
+ },
6756
6925
  note: `This is the exact content at version ${result.version}. Use this as the source of truth for syntax and API at this version.`
6757
6926
  };
6758
6927
  }
@@ -6784,14 +6953,38 @@ async function compareSyntax(input) {
6784
6953
  input.oldVersion,
6785
6954
  newVersion
6786
6955
  );
6956
+ const truncateForComparison = (content, label) => {
6957
+ if (!content) return { content: null, truncated: false };
6958
+ const result = smartTruncate(content, input.path);
6959
+ if (result.truncated) {
6960
+ logger.info("Comparison content truncated", {
6961
+ repository: `${resolved.owner}/${resolved.repo}`,
6962
+ path: input.path,
6963
+ version: label,
6964
+ language: result.truncationInfo?.language,
6965
+ contentLength: content.length,
6966
+ truncationInfo: result.truncationInfo
6967
+ });
6968
+ }
6969
+ return result;
6970
+ };
6971
+ const old = truncateForComparison(
6972
+ comparison.oldContent,
6973
+ comparison.oldVersion
6974
+ );
6975
+ const newC = truncateForComparison(
6976
+ comparison.newContent,
6977
+ comparison.newVersion
6978
+ );
6787
6979
  return {
6788
6980
  repository: `${resolved.owner}/${resolved.repo}`,
6789
6981
  path: input.path,
6790
6982
  oldVersion: comparison.oldVersion,
6791
6983
  newVersion: comparison.newVersion,
6792
6984
  hasDifferences: comparison.hasDifferences,
6793
- oldContent: comparison.oldContent,
6794
- newContent: comparison.newContent,
6985
+ oldContent: old.content,
6986
+ newContent: newC.content,
6987
+ contentTruncated: old.truncated || newC.truncated,
6795
6988
  recommendation: comparison.hasDifferences ? `\u26A0\uFE0F This file has changed between ${comparison.oldVersion} and ${comparison.newVersion}. Review the differences before using code patterns from the old version.` : `\u2705 No changes in this file between versions.`
6796
6989
  };
6797
6990
  }
@@ -6989,10 +7182,25 @@ Version: ${COMPACT_VERSION.min}-${COMPACT_VERSION.max} (updated: ${COMPACT_VERSI
6989
7182
  return {
6990
7183
  repository: `${resolved.owner}/${resolved.repo}`,
6991
7184
  version: reference.version,
6992
- syntaxFiles: reference.syntaxFiles.map((f) => ({
6993
- path: f.path,
6994
- content: f.content
6995
- })),
7185
+ syntaxFiles: reference.syntaxFiles.map((f) => {
7186
+ const result = smartTruncate(f.content, f.path);
7187
+ if (result.truncated) {
7188
+ logger.info("Syntax file truncated", {
7189
+ repository: `${resolved.owner}/${resolved.repo}`,
7190
+ path: f.path,
7191
+ version: reference.version,
7192
+ language: result.truncationInfo?.language,
7193
+ contentLength: f.content.length,
7194
+ truncationInfo: result.truncationInfo
7195
+ });
7196
+ }
7197
+ return {
7198
+ path: f.path,
7199
+ content: result.content,
7200
+ truncated: result.truncated,
7201
+ ...result.truncationInfo && { truncationInfo: result.truncationInfo }
7202
+ };
7203
+ }),
6996
7204
  note: `This is the authoritative syntax reference at version ${reference.version}. Use this to ensure contracts are compilable.`
6997
7205
  };
6998
7206
  }
@@ -7216,7 +7424,9 @@ var repositoryTools = [
7216
7424
  USAGE GUIDANCE:
7217
7425
  \u2022 Use midnight-list-examples first if you're unsure which file to get
7218
7426
  \u2022 For searching across files, use midnight-search-* tools instead
7219
- \u2022 Use 'ref' parameter to get specific versions (branch, tag, or commit)`,
7427
+ \u2022 Use 'ref' parameter to get specific versions (branch, tag, or commit)
7428
+ \u2022 Use startLine/endLine to request specific sections of large files
7429
+ \u2022 Files >50KB are truncated (first 25KB + last 25KB preserved)`,
7220
7430
  inputSchema: {
7221
7431
  type: "object",
7222
7432
  properties: {
@@ -7231,6 +7441,14 @@ USAGE GUIDANCE:
7231
7441
  ref: {
7232
7442
  type: "string",
7233
7443
  description: "Branch, tag, or commit SHA (default: main)"
7444
+ },
7445
+ startLine: {
7446
+ type: "number",
7447
+ description: "Start line number (1-based, inclusive). Use to request specific sections."
7448
+ },
7449
+ endLine: {
7450
+ type: "number",
7451
+ description: "End line number (1-based, inclusive). Use with startLine for a range."
7234
7452
  }
7235
7453
  },
7236
7454
  required: ["repo", "path"]
@@ -9315,4 +9533,4 @@ export {
9315
9533
  startServer,
9316
9534
  startHttpServer
9317
9535
  };
9318
- //# sourceMappingURL=chunk-L5CXYFG2.js.map
9536
+ //# sourceMappingURL=chunk-2YCZSMDD.js.map
@@ -1594,7 +1594,7 @@ async function checkGitHubAPI() {
1594
1594
  }
1595
1595
  async function checkVectorStore() {
1596
1596
  try {
1597
- const { vectorStore: vectorStore2 } = await import("./db-2KZMPC3W.js");
1597
+ const { vectorStore: vectorStore2 } = await import("./db-OENJQB5W.js");
1598
1598
  if (vectorStore2) {
1599
1599
  return {
1600
1600
  status: "pass",
@@ -2069,7 +2069,7 @@ function serialize(data) {
2069
2069
  }
2070
2070
 
2071
2071
  // src/utils/version.ts
2072
- var CURRENT_VERSION = "0.2.6";
2072
+ var CURRENT_VERSION = "0.2.7";
2073
2073
 
2074
2074
  // src/db/vectorStore.ts
2075
2075
  var VectorStore = class {
@@ -2278,4 +2278,4 @@ export {
2278
2278
  serialize,
2279
2279
  CURRENT_VERSION
2280
2280
  };
2281
- //# sourceMappingURL=chunk-WC2FPYQO.js.map
2281
+ //# sourceMappingURL=chunk-M3QHVBQV.js.map
@@ -0,0 +1,7 @@
1
+ import {
2
+ vectorStore
3
+ } from "./chunk-M3QHVBQV.js";
4
+ export {
5
+ vectorStore
6
+ };
7
+ //# sourceMappingURL=db-OENJQB5W.js.map
package/dist/index.js CHANGED
@@ -9,10 +9,10 @@ import {
9
9
  promptDefinitions,
10
10
  startHttpServer,
11
11
  startServer
12
- } from "./chunk-L5CXYFG2.js";
12
+ } from "./chunk-2YCZSMDD.js";
13
13
  import {
14
14
  logger
15
- } from "./chunk-WC2FPYQO.js";
15
+ } from "./chunk-M3QHVBQV.js";
16
16
  export {
17
17
  allResources,
18
18
  allTools,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "midnight-mcp",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "description": "Model Context Protocol Server for Midnight Blockchain Development",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,7 +0,0 @@
1
- import {
2
- vectorStore
3
- } from "./chunk-WC2FPYQO.js";
4
- export {
5
- vectorStore
6
- };
7
- //# sourceMappingURL=db-2KZMPC3W.js.map