midnight-mcp 0.1.0 → 0.1.1
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 +18 -9
- package/dist/server.d.ts +4 -0
- package/dist/server.js +19 -2
- package/dist/services/sampling.js +23 -2
- package/dist/tools/analyze.js +94 -56
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ Add to your `claude_desktop_config.json`:
|
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
<details>
|
|
29
|
-
<summary><strong
|
|
29
|
+
<summary><strong>Config file locations</strong></summary>
|
|
30
30
|
|
|
31
31
|
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
32
32
|
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
@@ -36,6 +36,13 @@ Add to your `claude_desktop_config.json`:
|
|
|
36
36
|
|
|
37
37
|
### Cursor
|
|
38
38
|
|
|
39
|
+
**Click the button to auto install the MCP for Cursor**
|
|
40
|
+
|
|
41
|
+
[](https://cursor.com/en-US/install-mcp?name=midnight&config=eyJjb21tYW5kIjoibnB4IC15IG1pZG5pZ2h0LW1jcCJ9)
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
**Manual setup instructions are below if you need them:**
|
|
45
|
+
|
|
39
46
|
Add to Cursor's MCP settings (Settings → MCP → Add Server):
|
|
40
47
|
|
|
41
48
|
```json
|
|
@@ -62,6 +69,8 @@ Or add to `.cursor/mcp.json` in your project:
|
|
|
62
69
|
}
|
|
63
70
|
```
|
|
64
71
|
|
|
72
|
+
|
|
73
|
+
|
|
65
74
|
### Windsurf
|
|
66
75
|
|
|
67
76
|
Add to `~/.codeium/windsurf/mcp_config.json`:
|
|
@@ -87,11 +96,11 @@ Restart your editor after adding the config. All features work out of the box—
|
|
|
87
96
|
|
|
88
97
|
By default, the MCP uses a **hosted API** for semantic search:
|
|
89
98
|
|
|
90
|
-
-
|
|
91
|
-
-
|
|
92
|
-
-
|
|
99
|
+
- **Zero configuration** — just install and use
|
|
100
|
+
- **Semantic search** works immediately
|
|
101
|
+
- **No API keys** needed
|
|
93
102
|
|
|
94
|
-
>
|
|
103
|
+
> **Quality Metrics**: To ensure the MCP stays accurate as Midnight's codebase evolves rapidly, we collect anonymous usage metrics (query counts, relevance scores) to monitor search quality. No query content or personal data is stored. This helps us identify when re-indexing is needed and improve results over time.
|
|
95
104
|
|
|
96
105
|
### Local Mode (Optional)
|
|
97
106
|
|
|
@@ -143,11 +152,11 @@ Add `"GITHUB_TOKEN": "ghp_..."` for higher GitHub API rate limits (60 → 5000 r
|
|
|
143
152
|
| `midnight-get-latest-syntax` | Latest syntax reference |
|
|
144
153
|
| `midnight-health-check` | Check server health status |
|
|
145
154
|
| `midnight-get-status` | Get rate limits and cache stats |
|
|
146
|
-
| `midnight-generate-contract`
|
|
147
|
-
| `midnight-review-contract`
|
|
148
|
-
| `midnight-document-contract`
|
|
155
|
+
| `midnight-generate-contract` | AI-generate contracts from natural language |
|
|
156
|
+
| `midnight-review-contract` | AI-powered security review of contracts |
|
|
157
|
+
| `midnight-document-contract` | AI-generate documentation for contracts |
|
|
149
158
|
|
|
150
|
-
>
|
|
159
|
+
> **Note:** The AI-powered tools require a client with [MCP Sampling](https://spec.modelcontextprotocol.io/specification/client/sampling/) support (e.g., Claude Desktop). Without sampling, these tools will return a helpful message instead.
|
|
151
160
|
|
|
152
161
|
### Resource Templates (4)
|
|
153
162
|
|
package/dist/server.d.ts
CHANGED
package/dist/server.js
CHANGED
|
@@ -15,6 +15,13 @@ const SERVER_INFO = {
|
|
|
15
15
|
};
|
|
16
16
|
// Resource subscriptions tracking
|
|
17
17
|
const resourceSubscriptions = new Set();
|
|
18
|
+
/**
|
|
19
|
+
* Clear all subscriptions (useful for server restart/testing)
|
|
20
|
+
*/
|
|
21
|
+
export function clearSubscriptions() {
|
|
22
|
+
resourceSubscriptions.clear();
|
|
23
|
+
logger.debug("Subscriptions cleared");
|
|
24
|
+
}
|
|
18
25
|
// Resource templates for parameterized resources (RFC 6570 URI Templates)
|
|
19
26
|
const resourceTemplates = [
|
|
20
27
|
{
|
|
@@ -295,7 +302,7 @@ function registerSubscriptionHandlers(server) {
|
|
|
295
302
|
const isValid = validPrefixes.some((prefix) => uri.startsWith(prefix));
|
|
296
303
|
if (!isValid) {
|
|
297
304
|
logger.warn(`Invalid subscription URI: ${uri}`);
|
|
298
|
-
|
|
305
|
+
throw new Error(`Invalid subscription URI: ${uri}. Valid prefixes: ${validPrefixes.join(", ")}`);
|
|
299
306
|
}
|
|
300
307
|
resourceSubscriptions.add(uri);
|
|
301
308
|
logger.debug(`Active subscriptions: ${resourceSubscriptions.size}`);
|
|
@@ -355,7 +362,17 @@ function setupSampling(server) {
|
|
|
355
362
|
},
|
|
356
363
|
// Use a schema that matches the expected response
|
|
357
364
|
{
|
|
358
|
-
parse: (data) =>
|
|
365
|
+
parse: (data) => {
|
|
366
|
+
const response = data;
|
|
367
|
+
// Basic validation of expected response structure
|
|
368
|
+
if (!response || typeof response !== "object") {
|
|
369
|
+
throw new Error("Invalid sampling response: expected object");
|
|
370
|
+
}
|
|
371
|
+
if (!response.content || typeof response.content !== "object") {
|
|
372
|
+
throw new Error("Invalid sampling response: missing content");
|
|
373
|
+
}
|
|
374
|
+
return response;
|
|
375
|
+
},
|
|
359
376
|
_def: { typeName: "SamplingResponse" },
|
|
360
377
|
});
|
|
361
378
|
return response;
|
|
@@ -191,10 +191,31 @@ Respond in JSON format:
|
|
|
191
191
|
maxTokens: 4096,
|
|
192
192
|
temperature: 0.2,
|
|
193
193
|
});
|
|
194
|
-
// Parse JSON response
|
|
194
|
+
// Parse JSON response with error handling
|
|
195
195
|
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
196
196
|
if (jsonMatch) {
|
|
197
|
-
|
|
197
|
+
try {
|
|
198
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
199
|
+
// Validate expected structure
|
|
200
|
+
return {
|
|
201
|
+
summary: typeof parsed.summary === "string"
|
|
202
|
+
? parsed.summary
|
|
203
|
+
: "Review complete",
|
|
204
|
+
issues: Array.isArray(parsed.issues) ? parsed.issues : [],
|
|
205
|
+
improvedCode: typeof parsed.improvedCode === "string"
|
|
206
|
+
? parsed.improvedCode
|
|
207
|
+
: undefined,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
catch (parseError) {
|
|
211
|
+
logger.warn("Failed to parse JSON from LLM response", {
|
|
212
|
+
error: String(parseError),
|
|
213
|
+
});
|
|
214
|
+
return {
|
|
215
|
+
summary: response,
|
|
216
|
+
issues: [],
|
|
217
|
+
};
|
|
218
|
+
}
|
|
198
219
|
}
|
|
199
220
|
return {
|
|
200
221
|
summary: response,
|
package/dist/tools/analyze.js
CHANGED
|
@@ -230,46 +230,77 @@ function getPrivacyConsiderations(circuit) {
|
|
|
230
230
|
}
|
|
231
231
|
return considerations;
|
|
232
232
|
}
|
|
233
|
-
// Output schemas for analysis tools
|
|
233
|
+
// Output schemas for analysis tools - aligned with actual function return types
|
|
234
234
|
const analyzeContractOutputSchema = {
|
|
235
235
|
type: "object",
|
|
236
236
|
properties: {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
type: "
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
},
|
|
237
|
+
summary: {
|
|
238
|
+
type: "object",
|
|
239
|
+
description: "Summary statistics of the contract",
|
|
240
|
+
properties: {
|
|
241
|
+
hasLedger: { type: "boolean" },
|
|
242
|
+
hasCircuits: { type: "boolean" },
|
|
243
|
+
hasWitnesses: { type: "boolean" },
|
|
244
|
+
totalLines: { type: "number" },
|
|
245
|
+
publicCircuits: { type: "number" },
|
|
246
|
+
privateCircuits: { type: "number" },
|
|
247
|
+
publicState: { type: "number" },
|
|
248
|
+
privateState: { type: "number" },
|
|
249
249
|
},
|
|
250
250
|
},
|
|
251
|
-
|
|
252
|
-
type: "
|
|
253
|
-
description: "
|
|
254
|
-
|
|
255
|
-
type: "
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
251
|
+
structure: {
|
|
252
|
+
type: "object",
|
|
253
|
+
description: "Contract structure breakdown",
|
|
254
|
+
properties: {
|
|
255
|
+
imports: { type: "array", items: { type: "string" } },
|
|
256
|
+
exports: { type: "array", items: { type: "string" } },
|
|
257
|
+
ledger: {
|
|
258
|
+
type: "array",
|
|
259
|
+
description: "Ledger state fields",
|
|
260
|
+
items: {
|
|
261
|
+
type: "object",
|
|
262
|
+
properties: {
|
|
263
|
+
name: { type: "string" },
|
|
264
|
+
type: { type: "string" },
|
|
265
|
+
isPrivate: { type: "boolean" },
|
|
266
|
+
},
|
|
267
|
+
},
|
|
261
268
|
},
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
269
|
+
circuits: {
|
|
270
|
+
type: "array",
|
|
271
|
+
description: "Circuit definitions",
|
|
272
|
+
items: {
|
|
273
|
+
type: "object",
|
|
274
|
+
properties: {
|
|
275
|
+
name: { type: "string" },
|
|
276
|
+
isPublic: { type: "boolean" },
|
|
277
|
+
parameters: { type: "array", items: { type: "object" } },
|
|
278
|
+
returnType: { type: "string" },
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
witnesses: {
|
|
283
|
+
type: "array",
|
|
284
|
+
description: "Witness functions",
|
|
285
|
+
items: {
|
|
286
|
+
type: "object",
|
|
287
|
+
properties: {
|
|
288
|
+
name: { type: "string" },
|
|
289
|
+
parameters: { type: "array", items: { type: "object" } },
|
|
290
|
+
returnType: { type: "string" },
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
types: {
|
|
295
|
+
type: "array",
|
|
296
|
+
description: "Type definitions",
|
|
297
|
+
items: {
|
|
298
|
+
type: "object",
|
|
299
|
+
properties: {
|
|
300
|
+
name: { type: "string" },
|
|
301
|
+
definition: { type: "string" },
|
|
302
|
+
},
|
|
303
|
+
},
|
|
273
304
|
},
|
|
274
305
|
},
|
|
275
306
|
},
|
|
@@ -294,31 +325,14 @@ const analyzeContractOutputSchema = {
|
|
|
294
325
|
description: "Recommendations for improvement",
|
|
295
326
|
},
|
|
296
327
|
},
|
|
297
|
-
required: ["summary", "
|
|
328
|
+
required: ["summary", "structure", "securityFindings", "recommendations"],
|
|
298
329
|
description: "Detailed contract analysis with security findings",
|
|
299
330
|
};
|
|
300
331
|
const explainCircuitOutputSchema = {
|
|
301
332
|
type: "object",
|
|
302
333
|
properties: {
|
|
303
|
-
|
|
304
|
-
type: {
|
|
305
|
-
type: "string",
|
|
306
|
-
description: "Type: circuit or witness",
|
|
307
|
-
},
|
|
334
|
+
circuitName: { type: "string", description: "Circuit name" },
|
|
308
335
|
isPublic: { type: "boolean", description: "Whether it's exported" },
|
|
309
|
-
plainEnglishExplanation: {
|
|
310
|
-
type: "string",
|
|
311
|
-
description: "Plain language explanation",
|
|
312
|
-
},
|
|
313
|
-
zkProofImplications: {
|
|
314
|
-
type: "string",
|
|
315
|
-
description: "Zero-knowledge proof implications",
|
|
316
|
-
},
|
|
317
|
-
privacyConsiderations: {
|
|
318
|
-
type: "array",
|
|
319
|
-
items: { type: "string" },
|
|
320
|
-
description: "Privacy-related considerations",
|
|
321
|
-
},
|
|
322
336
|
parameters: {
|
|
323
337
|
type: "array",
|
|
324
338
|
items: {
|
|
@@ -326,13 +340,37 @@ const explainCircuitOutputSchema = {
|
|
|
326
340
|
properties: {
|
|
327
341
|
name: { type: "string" },
|
|
328
342
|
type: { type: "string" },
|
|
329
|
-
description: { type: "string" },
|
|
330
343
|
},
|
|
331
344
|
},
|
|
345
|
+
description: "Circuit parameters",
|
|
346
|
+
},
|
|
347
|
+
returnType: { type: "string", description: "Return type" },
|
|
348
|
+
explanation: {
|
|
349
|
+
type: "string",
|
|
350
|
+
description: "Plain language explanation",
|
|
351
|
+
},
|
|
352
|
+
operations: {
|
|
353
|
+
type: "array",
|
|
354
|
+
items: { type: "string" },
|
|
355
|
+
description: "Operations performed by the circuit",
|
|
356
|
+
},
|
|
357
|
+
zkImplications: {
|
|
358
|
+
type: "array",
|
|
359
|
+
items: { type: "string" },
|
|
360
|
+
description: "Zero-knowledge proof implications",
|
|
361
|
+
},
|
|
362
|
+
privacyConsiderations: {
|
|
363
|
+
type: "array",
|
|
364
|
+
items: { type: "string" },
|
|
365
|
+
description: "Privacy-related considerations",
|
|
332
366
|
},
|
|
333
|
-
returnType: { type: "string" },
|
|
334
367
|
},
|
|
335
|
-
required: [
|
|
368
|
+
required: [
|
|
369
|
+
"circuitName",
|
|
370
|
+
"explanation",
|
|
371
|
+
"zkImplications",
|
|
372
|
+
"privacyConsiderations",
|
|
373
|
+
],
|
|
336
374
|
description: "Detailed circuit explanation with privacy analysis",
|
|
337
375
|
};
|
|
338
376
|
// Tool definitions for MCP
|