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 CHANGED
@@ -26,7 +26,7 @@ Add to your `claude_desktop_config.json`:
26
26
  ```
27
27
 
28
28
  <details>
29
- <summary><strong>📍 Config file locations</strong></summary>
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
+ [![Install MCP Server](https://cursor.com/deeplink/mcp-install-dark.svg)](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
- - **Zero configuration** — just install and use
91
- - **Semantic search** works immediately
92
- - **No API keys** needed
99
+ - **Zero configuration** — just install and use
100
+ - **Semantic search** works immediately
101
+ - **No API keys** needed
93
102
 
94
- > **📊 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.
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`| AI-generate contracts from natural language |
147
- | `midnight-review-contract`| AI-powered security review of contracts |
148
- | `midnight-document-contract`| AI-generate documentation for contracts |
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
- > **✨ New 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.
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
@@ -1,4 +1,8 @@
1
1
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ /**
3
+ * Clear all subscriptions (useful for server restart/testing)
4
+ */
5
+ export declare function clearSubscriptions(): void;
2
6
  /**
3
7
  * Create and configure the MCP server
4
8
  */
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
- return {};
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) => 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
- return JSON.parse(jsonMatch[0]);
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,
@@ -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
- name: { type: "string", description: "Contract name" },
238
- summary: { type: "string", description: "Brief contract summary" },
239
- ledgerState: {
240
- type: "array",
241
- description: "Ledger state fields",
242
- items: {
243
- type: "object",
244
- properties: {
245
- name: { type: "string" },
246
- type: { type: "string" },
247
- isPrivate: { type: "boolean" },
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
- circuits: {
252
- type: "array",
253
- description: "Circuit definitions",
254
- items: {
255
- type: "object",
256
- properties: {
257
- name: { type: "string" },
258
- isPublic: { type: "boolean" },
259
- parameters: { type: "array", items: { type: "object" } },
260
- purpose: { type: "string" },
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
- witnesses: {
265
- type: "array",
266
- description: "Witness functions",
267
- items: {
268
- type: "object",
269
- properties: {
270
- name: { type: "string" },
271
- returnType: { type: "string" },
272
- purpose: { type: "string" },
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", "circuits"],
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
- name: { type: "string", description: "Circuit name" },
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: ["name", "plainEnglishExplanation"],
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "midnight-mcp",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Model Context Protocol Server for Midnight Blockchain Development",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",