midnight-mcp 0.2.7 → 0.2.9
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 +4 -2
- package/dist/bin.js +3 -3
- package/dist/{chunk-2YCZSMDD.js → chunk-5PGBYGCG.js} +113 -16
- package/dist/{chunk-M3QHVBQV.js → chunk-WZVWUFLH.js} +23 -5
- package/dist/db-2VUY2I5E.js +7 -0
- package/dist/index.d.ts +16 -1
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/dist/db-OENJQB5W.js +0 -7
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Midnight MCP Server
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/midnight-mcp)
|
|
4
|
-
[](https://
|
|
4
|
+
[](https://npm-stat.com/charts.html?package=midnight-mcp)
|
|
5
5
|
[](./LICENSE)
|
|
6
6
|
[](https://www.typescriptlang.org/)
|
|
7
7
|
[](https://github.com/Olanetsoft/midnight-mcp/actions/workflows/ci.yml)
|
|
@@ -264,4 +264,6 @@ The hosted API runs on Cloudflare Workers + Vectorize. See [api/README.md](./api
|
|
|
264
264
|
|
|
265
265
|
MIT
|
|
266
266
|
|
|
267
|
-
|
|
267
|
+
## Stargazers ⭐️
|
|
268
|
+
|
|
269
|
+
[](https://star-history.com/#Olanetsoft/midnight-mcp&Date)
|
package/dist/bin.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
startHttpServer,
|
|
4
4
|
startServer
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-5PGBYGCG.js";
|
|
6
6
|
import {
|
|
7
7
|
setOutputFormat
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-WZVWUFLH.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.
|
|
16
|
+
var CURRENT_VERSION = "0.2.9";
|
|
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-
|
|
28
|
+
} from "./chunk-WZVWUFLH.js";
|
|
29
29
|
|
|
30
30
|
// src/tools/search/schemas.ts
|
|
31
31
|
import { z } from "zod";
|
|
@@ -102,7 +102,49 @@ async function tryHostedSearch(searchType, hostedSearchFn, cacheKey, warnings) {
|
|
|
102
102
|
...response,
|
|
103
103
|
...warnings.length > 0 && { warnings }
|
|
104
104
|
};
|
|
105
|
-
searchCache.set(cacheKey,
|
|
105
|
+
searchCache.set(cacheKey, {
|
|
106
|
+
results: finalResponse.results.map((item) => {
|
|
107
|
+
const result = item;
|
|
108
|
+
let startLine;
|
|
109
|
+
let endLine;
|
|
110
|
+
if (result.source.lines) {
|
|
111
|
+
const lineParts = result.source.lines.split("-");
|
|
112
|
+
if (lineParts.length === 2) {
|
|
113
|
+
const parsedStart = parseInt(lineParts[0], 10);
|
|
114
|
+
const parsedEnd = parseInt(lineParts[1], 10);
|
|
115
|
+
if (!Number.isNaN(parsedStart)) {
|
|
116
|
+
startLine = parsedStart;
|
|
117
|
+
}
|
|
118
|
+
if (!Number.isNaN(parsedEnd)) {
|
|
119
|
+
endLine = parsedEnd;
|
|
120
|
+
}
|
|
121
|
+
} else if (lineParts.length === 1) {
|
|
122
|
+
const parsed = parseInt(lineParts[0], 10);
|
|
123
|
+
if (!Number.isNaN(parsed)) {
|
|
124
|
+
startLine = endLine = parsed;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
code: result.code,
|
|
130
|
+
content: result.content,
|
|
131
|
+
relevanceScore: result.relevanceScore,
|
|
132
|
+
source: {
|
|
133
|
+
repository: result.source.repository,
|
|
134
|
+
filePath: result.source.filePath,
|
|
135
|
+
startLine,
|
|
136
|
+
endLine,
|
|
137
|
+
lines: result.source.lines,
|
|
138
|
+
section: result.source.section
|
|
139
|
+
},
|
|
140
|
+
codeType: result.codeType,
|
|
141
|
+
name: result.name,
|
|
142
|
+
isExported: result.isExported
|
|
143
|
+
};
|
|
144
|
+
}),
|
|
145
|
+
totalResults: finalResponse.totalResults ?? finalResponse.results.length,
|
|
146
|
+
warnings: warnings.length > 0 ? warnings : void 0
|
|
147
|
+
});
|
|
106
148
|
return {
|
|
107
149
|
result: finalResponse,
|
|
108
150
|
cached: true
|
|
@@ -122,7 +164,11 @@ function finalizeResponse(response, cacheKey, warnings) {
|
|
|
122
164
|
...response,
|
|
123
165
|
...warnings.length > 0 && { warnings }
|
|
124
166
|
};
|
|
125
|
-
searchCache.set(cacheKey,
|
|
167
|
+
searchCache.set(cacheKey, {
|
|
168
|
+
results: finalResponse.results,
|
|
169
|
+
totalResults: finalResponse.totalResults ?? finalResponse.results.length,
|
|
170
|
+
warnings: warnings.length > 0 ? warnings : void 0
|
|
171
|
+
});
|
|
126
172
|
return finalResponse;
|
|
127
173
|
}
|
|
128
174
|
async function searchCompact(input) {
|
|
@@ -794,8 +840,18 @@ async function explainCircuit(input) {
|
|
|
794
840
|
const circuit = parsed.codeUnits.find((u) => u.type === "circuit");
|
|
795
841
|
if (!circuit) {
|
|
796
842
|
return {
|
|
797
|
-
|
|
798
|
-
|
|
843
|
+
circuitName: "unknown",
|
|
844
|
+
isPublic: false,
|
|
845
|
+
parameters: [],
|
|
846
|
+
returnType: "unknown",
|
|
847
|
+
explanation: "No circuit definition found in the provided code. Make sure to provide a complete circuit definition including the 'circuit' keyword.",
|
|
848
|
+
operations: [],
|
|
849
|
+
zkImplications: [
|
|
850
|
+
"Unable to analyze - no valid circuit found in the provided code"
|
|
851
|
+
],
|
|
852
|
+
privacyConsiderations: [
|
|
853
|
+
"Provide a complete circuit definition for privacy analysis"
|
|
854
|
+
]
|
|
799
855
|
};
|
|
800
856
|
}
|
|
801
857
|
const operations = [];
|
|
@@ -4536,15 +4592,22 @@ Please help me debug by:
|
|
|
4536
4592
|
|
|
4537
4593
|
// src/services/sampling.ts
|
|
4538
4594
|
var samplingCallback = null;
|
|
4595
|
+
var samplingFailedPermanently = false;
|
|
4539
4596
|
function isSamplingAvailable() {
|
|
4597
|
+
if (samplingFailedPermanently) return false;
|
|
4540
4598
|
return samplingCallback !== null;
|
|
4541
4599
|
}
|
|
4600
|
+
function markSamplingFailed() {
|
|
4601
|
+
samplingFailedPermanently = true;
|
|
4602
|
+
logger.warn("Sampling marked as permanently unavailable for this session");
|
|
4603
|
+
}
|
|
4542
4604
|
function registerSamplingCallback(callback) {
|
|
4543
4605
|
samplingCallback = callback;
|
|
4606
|
+
samplingFailedPermanently = false;
|
|
4544
4607
|
logger.info("Sampling capability registered");
|
|
4545
4608
|
}
|
|
4546
4609
|
async function requestCompletion(messages, options = {}) {
|
|
4547
|
-
if (!samplingCallback) {
|
|
4610
|
+
if (!samplingCallback || samplingFailedPermanently) {
|
|
4548
4611
|
throw new Error(
|
|
4549
4612
|
"Sampling not available - client does not support this capability"
|
|
4550
4613
|
);
|
|
@@ -4567,11 +4630,25 @@ async function requestCompletion(messages, options = {}) {
|
|
|
4567
4630
|
messageCount: messages.length,
|
|
4568
4631
|
maxTokens: request.maxTokens
|
|
4569
4632
|
});
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4633
|
+
try {
|
|
4634
|
+
const response = await samplingCallback(request);
|
|
4635
|
+
if (response.content.type !== "text") {
|
|
4636
|
+
throw new Error("Unexpected response content type");
|
|
4637
|
+
}
|
|
4638
|
+
return response.content.text;
|
|
4639
|
+
} catch (error) {
|
|
4640
|
+
const errorStr = String(error);
|
|
4641
|
+
if (errorStr.includes("-32601") || errorStr.includes("Method not found") || errorStr.includes("not supported")) {
|
|
4642
|
+
logger.warn(
|
|
4643
|
+
"Client does not support sampling/createMessage, disabling sampling for this session"
|
|
4644
|
+
);
|
|
4645
|
+
markSamplingFailed();
|
|
4646
|
+
throw new Error(
|
|
4647
|
+
"Sampling not supported by this client - use Claude Desktop for this feature"
|
|
4648
|
+
);
|
|
4649
|
+
}
|
|
4650
|
+
throw error;
|
|
4573
4651
|
}
|
|
4574
|
-
return response.content.text;
|
|
4575
4652
|
}
|
|
4576
4653
|
async function generateContract(requirements, options = {}) {
|
|
4577
4654
|
if (!isSamplingAvailable()) {
|
|
@@ -5170,6 +5247,17 @@ function registerResourceHandlers(server) {
|
|
|
5170
5247
|
"midnight://schema/"
|
|
5171
5248
|
];
|
|
5172
5249
|
const validPrefix = resourceTypes.find((p) => uri.startsWith(p));
|
|
5250
|
+
let suggestion = validPrefix ? `Check the resource path after '${validPrefix}'` : `Valid resource prefixes: ${resourceTypes.join(", ")}`;
|
|
5251
|
+
if (uri.includes("://resources/")) {
|
|
5252
|
+
const resourceName = uri.split("://resources/").pop() || "";
|
|
5253
|
+
if (resourceName.includes("template") || resourceName.includes("pattern") || resourceName.includes("example")) {
|
|
5254
|
+
suggestion = `Try: midnight://code/templates/${resourceName} or midnight://code/examples/${resourceName} or midnight://code/patterns/${resourceName}`;
|
|
5255
|
+
} else if (resourceName.includes("doc") || resourceName.includes("reference") || resourceName.includes("guide")) {
|
|
5256
|
+
suggestion = `Try: midnight://docs/${resourceName}`;
|
|
5257
|
+
} else {
|
|
5258
|
+
suggestion = `'midnight://resources/' is not valid. Use: midnight://docs/, midnight://code/, or midnight://schema/`;
|
|
5259
|
+
}
|
|
5260
|
+
}
|
|
5173
5261
|
return {
|
|
5174
5262
|
contents: [
|
|
5175
5263
|
{
|
|
@@ -5177,8 +5265,9 @@ function registerResourceHandlers(server) {
|
|
|
5177
5265
|
mimeType: "application/json",
|
|
5178
5266
|
text: serialize({
|
|
5179
5267
|
error: `Resource not found: ${uri}`,
|
|
5180
|
-
suggestion
|
|
5181
|
-
hint: "Use ListResources to see all available resources"
|
|
5268
|
+
suggestion,
|
|
5269
|
+
hint: "Use ListResources to see all available resources",
|
|
5270
|
+
validPrefixes: resourceTypes
|
|
5182
5271
|
})
|
|
5183
5272
|
}
|
|
5184
5273
|
]
|
|
@@ -5809,6 +5898,9 @@ CORRECT: pure circuit helper(...): Type { }`
|
|
|
5809
5898
|
import { readFile } from "fs/promises";
|
|
5810
5899
|
import { basename, isAbsolute, resolve } from "path";
|
|
5811
5900
|
import { platform } from "process";
|
|
5901
|
+
function escapeRegex(str) {
|
|
5902
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
5903
|
+
}
|
|
5812
5904
|
function validateFilePath(filePath) {
|
|
5813
5905
|
if (!isAbsolute(filePath)) {
|
|
5814
5906
|
return {
|
|
@@ -6268,16 +6360,20 @@ async function extractContractStructure(input) {
|
|
|
6268
6360
|
if (sealedFields.length > 0) {
|
|
6269
6361
|
for (const circuit of circuits) {
|
|
6270
6362
|
if (circuit.isExport) {
|
|
6363
|
+
const escapedCircuitName = escapeRegex(circuit.name);
|
|
6271
6364
|
const circuitBodyMatch = code.match(
|
|
6272
6365
|
new RegExp(
|
|
6273
|
-
`(?:export\\s+)?circuit\\s+${
|
|
6366
|
+
`(?:export\\s+)?circuit\\s+${escapedCircuitName}\\s*\\([^)]*\\)\\s*:[^{]*\\{([\\s\\S]*?)\\n\\}`,
|
|
6274
6367
|
"m"
|
|
6275
6368
|
)
|
|
6276
6369
|
);
|
|
6277
6370
|
if (circuitBodyMatch) {
|
|
6278
6371
|
const body = circuitBodyMatch[1];
|
|
6279
6372
|
for (const field of sealedFields) {
|
|
6280
|
-
|
|
6373
|
+
const escapedFieldName = escapeRegex(field.name);
|
|
6374
|
+
if (new RegExp(`\\b${escapedFieldName}\\s*=`).test(body) || new RegExp(`\\b${escapedFieldName}\\s*\\.\\s*\\w+\\s*\\(`).test(
|
|
6375
|
+
body
|
|
6376
|
+
)) {
|
|
6281
6377
|
potentialIssues.push({
|
|
6282
6378
|
type: "sealed_export_conflict",
|
|
6283
6379
|
line: circuit.line,
|
|
@@ -6426,8 +6522,9 @@ async function extractContractStructure(input) {
|
|
|
6426
6522
|
constructorParams.push(paramMatch[1]);
|
|
6427
6523
|
}
|
|
6428
6524
|
for (const param of constructorParams) {
|
|
6525
|
+
const escapedParam = escapeRegex(param);
|
|
6429
6526
|
const assignmentPattern = new RegExp(
|
|
6430
|
-
`(\\w+)\\s*=\\s*(?!disclose\\s*\\()${
|
|
6527
|
+
`(\\w+)\\s*=\\s*(?!disclose\\s*\\()${escapedParam}\\b`,
|
|
6431
6528
|
"g"
|
|
6432
6529
|
);
|
|
6433
6530
|
let assignMatch;
|
|
@@ -9533,4 +9630,4 @@ export {
|
|
|
9533
9630
|
startServer,
|
|
9534
9631
|
startHttpServer
|
|
9535
9632
|
};
|
|
9536
|
-
//# sourceMappingURL=chunk-
|
|
9633
|
+
//# sourceMappingURL=chunk-5PGBYGCG.js.map
|
|
@@ -851,7 +851,11 @@ var GitHubClient = class {
|
|
|
851
851
|
}
|
|
852
852
|
}
|
|
853
853
|
/**
|
|
854
|
-
* Filter files by patterns
|
|
854
|
+
* Filter files by patterns (glob matching)
|
|
855
|
+
*
|
|
856
|
+
* SECURITY NOTE: Patterns come from trusted REPOSITORIES config, not user input.
|
|
857
|
+
* The glob-to-regex conversion only handles **, *, and . characters.
|
|
858
|
+
* This is safe because malicious patterns could only come from internal config.
|
|
855
859
|
*/
|
|
856
860
|
filterFilesByPatterns(files, patterns, exclude) {
|
|
857
861
|
const matchPattern = (file, pattern) => {
|
|
@@ -1016,6 +1020,20 @@ var GitHubClient = class {
|
|
|
1016
1020
|
var githubClient = new GitHubClient();
|
|
1017
1021
|
|
|
1018
1022
|
// src/pipeline/parser.ts
|
|
1023
|
+
var LANGUAGES = {
|
|
1024
|
+
COMPACT: "compact",
|
|
1025
|
+
TYPESCRIPT: "typescript",
|
|
1026
|
+
MARKDOWN: "markdown"
|
|
1027
|
+
};
|
|
1028
|
+
var EXTENSION_LANGUAGE_MAP = {
|
|
1029
|
+
compact: LANGUAGES.COMPACT,
|
|
1030
|
+
ts: LANGUAGES.TYPESCRIPT,
|
|
1031
|
+
tsx: LANGUAGES.TYPESCRIPT,
|
|
1032
|
+
js: LANGUAGES.TYPESCRIPT,
|
|
1033
|
+
jsx: LANGUAGES.TYPESCRIPT,
|
|
1034
|
+
md: LANGUAGES.MARKDOWN,
|
|
1035
|
+
mdx: LANGUAGES.MARKDOWN
|
|
1036
|
+
};
|
|
1019
1037
|
function parseCompactFile(path, content) {
|
|
1020
1038
|
const lines = content.split("\n");
|
|
1021
1039
|
const codeUnits = [];
|
|
@@ -1161,7 +1179,7 @@ function parseCompactFile(path, content) {
|
|
|
1161
1179
|
}
|
|
1162
1180
|
return {
|
|
1163
1181
|
path,
|
|
1164
|
-
language:
|
|
1182
|
+
language: LANGUAGES.COMPACT,
|
|
1165
1183
|
content,
|
|
1166
1184
|
codeUnits,
|
|
1167
1185
|
imports,
|
|
@@ -1594,7 +1612,7 @@ async function checkGitHubAPI() {
|
|
|
1594
1612
|
}
|
|
1595
1613
|
async function checkVectorStore() {
|
|
1596
1614
|
try {
|
|
1597
|
-
const { vectorStore: vectorStore2 } = await import("./db-
|
|
1615
|
+
const { vectorStore: vectorStore2 } = await import("./db-2VUY2I5E.js");
|
|
1598
1616
|
if (vectorStore2) {
|
|
1599
1617
|
return {
|
|
1600
1618
|
status: "pass",
|
|
@@ -2069,7 +2087,7 @@ function serialize(data) {
|
|
|
2069
2087
|
}
|
|
2070
2088
|
|
|
2071
2089
|
// src/utils/version.ts
|
|
2072
|
-
var CURRENT_VERSION = "0.2.
|
|
2090
|
+
var CURRENT_VERSION = "0.2.9";
|
|
2073
2091
|
|
|
2074
2092
|
// src/db/vectorStore.ts
|
|
2075
2093
|
var VectorStore = class {
|
|
@@ -2278,4 +2296,4 @@ export {
|
|
|
2278
2296
|
serialize,
|
|
2279
2297
|
CURRENT_VERSION
|
|
2280
2298
|
};
|
|
2281
|
-
//# sourceMappingURL=chunk-
|
|
2299
|
+
//# sourceMappingURL=chunk-WZVWUFLH.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -85,6 +85,13 @@ interface PropertySchema {
|
|
|
85
85
|
properties?: Record<string, PropertySchema>;
|
|
86
86
|
enum?: string[];
|
|
87
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Extended tool definition with handler
|
|
90
|
+
*
|
|
91
|
+
* Note: Handler uses `unknown` for input to allow flexibility in tool implementations.
|
|
92
|
+
* Each tool module defines its own specific input/output types via Zod schemas.
|
|
93
|
+
* The MCP server validates inputs against the inputSchema before calling handlers.
|
|
94
|
+
*/
|
|
88
95
|
interface ExtendedToolDefinition {
|
|
89
96
|
name: string;
|
|
90
97
|
description: string;
|
|
@@ -95,7 +102,15 @@ interface ExtendedToolDefinition {
|
|
|
95
102
|
};
|
|
96
103
|
outputSchema?: OutputSchema;
|
|
97
104
|
annotations?: ToolAnnotations;
|
|
98
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Handler function that processes tool inputs
|
|
107
|
+
* Input is validated against inputSchema before this is called
|
|
108
|
+
* Output should match outputSchema if defined
|
|
109
|
+
*
|
|
110
|
+
* Using `unknown` allows specific handler types to be assigned.
|
|
111
|
+
* Type safety is enforced by Zod schema validation at runtime.
|
|
112
|
+
*/
|
|
113
|
+
handler: (input: any) => Promise<unknown>;
|
|
99
114
|
}
|
|
100
115
|
|
|
101
116
|
/**
|
package/dist/index.js
CHANGED
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
promptDefinitions,
|
|
10
10
|
startHttpServer,
|
|
11
11
|
startServer
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-5PGBYGCG.js";
|
|
13
13
|
import {
|
|
14
14
|
logger
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-WZVWUFLH.js";
|
|
16
16
|
export {
|
|
17
17
|
allResources,
|
|
18
18
|
allTools,
|
package/package.json
CHANGED