midnight-mcp 0.1.7 → 0.1.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 CHANGED
@@ -10,97 +10,86 @@ MCP server that gives AI assistants access to Midnight blockchain—search contr
10
10
 
11
11
  ## Quick Start
12
12
 
13
- ### Claude Desktop
14
-
15
- Add to your `claude_desktop_config.json`:
13
+ **Claude Desktop** — Add to `claude_desktop_config.json`:
16
14
 
17
15
  ```json
18
16
  {
19
17
  "mcpServers": {
20
- "midnight": {
21
- "command": "npx",
22
- "args": ["-y", "midnight-mcp"]
23
- }
18
+ "midnight": { "command": "npx", "args": ["-y", "midnight-mcp"] }
24
19
  }
25
20
  }
26
21
  ```
27
22
 
28
- <details>
29
- <summary><strong>Config file locations</strong></summary>
30
-
31
- - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
32
- - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
33
- - **Linux**: `~/.config/Claude/claude_desktop_config.json`
34
-
35
- </details>
36
-
37
- ### Cursor
38
-
39
- **Click the button to auto install the MCP for Cursor**
23
+ **Cursor** — One-click install:
40
24
 
41
25
  [![Install MCP Server](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=midnight&config=eyJjb21tYW5kIjoibnB4IC15IG1pZG5pZ2h0LW1jcCJ9)
42
26
 
43
- ---
44
- **Manual setup instructions are below if you need them:**
27
+ <details>
28
+ <summary><strong>Other Editors (Windsurf, VS Code Copilot, Manual Setup)</strong></summary>
45
29
 
46
- Add to Cursor's MCP settings (Settings → MCP → Add Server):
30
+ **Windsurf** — Add to `~/.codeium/windsurf/mcp_config.json`:
47
31
 
48
32
  ```json
49
33
  {
50
34
  "mcpServers": {
51
- "midnight": {
52
- "command": "npx",
53
- "args": ["-y", "midnight-mcp"]
54
- }
35
+ "midnight": { "command": "npx", "args": ["-y", "midnight-mcp"] }
55
36
  }
56
37
  }
57
38
  ```
58
39
 
59
- Or add to `.cursor/mcp.json` in your project:
40
+ **VS Code Copilot** — Add to `.vscode/mcp.json` or use Command Palette: `MCP: Add Server` → "command (stdio)" → `npx -y midnight-mcp`
60
41
 
61
42
  ```json
62
43
  {
63
44
  "mcpServers": {
64
- "midnight": {
65
- "command": "npx",
66
- "args": ["-y", "midnight-mcp"]
67
- }
45
+ "midnight": { "command": "npx", "args": ["-y", "midnight-mcp"] }
68
46
  }
69
47
  }
70
48
  ```
71
49
 
72
-
73
-
74
- ### Windsurf
75
-
76
- Add to `~/.codeium/windsurf/mcp_config.json`:
50
+ **Cursor Manual** — Settings → MCP → Add Server, or add to `.cursor/mcp.json`:
77
51
 
78
52
  ```json
79
53
  {
80
54
  "mcpServers": {
81
- "midnight": {
82
- "command": "npx",
83
- "args": ["-y", "midnight-mcp"]
84
- }
55
+ "midnight": { "command": "npx", "args": ["-y", "midnight-mcp"] }
85
56
  }
86
57
  }
87
58
  ```
88
59
 
89
- ---
60
+ **Config file locations (Claude Desktop):**
90
61
 
91
- Restart your editor after adding the config. All features work out of the box—no API keys or setup required.
62
+ - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
63
+ - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
64
+ - Linux: `~/.config/Claude/claude_desktop_config.json`
65
+
66
+ </details>
67
+
68
+ Restart your editor after adding the config. **No API keys required.**
69
+
70
+ > **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.
92
71
 
93
72
  ---
94
73
 
95
- ## How It Works
74
+ ## Features
96
75
 
97
- By default, the MCP uses a **hosted API** for semantic search:
76
+ **19 Tools** Search, analyze, version tracking, AI generation
98
77
 
99
- - **Zero configuration** — just install and use
100
- - **Semantic search** works immediately
101
- - **No API keys** needed
78
+ | Category | Tools |
79
+ | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
80
+ | Search | `midnight-search-compact`, `midnight-search-typescript`, `midnight-search-docs` |
81
+ | Analysis | `midnight-analyze-contract`, `midnight-explain-circuit` |
82
+ | Repository | `midnight-get-file`, `midnight-list-examples`, `midnight-get-latest-updates` |
83
+ | Versioning | `midnight-get-version-info`, `midnight-check-breaking-changes`, `midnight-get-migration-guide`, `midnight-get-file-at-version`, `midnight-compare-syntax`, `midnight-get-latest-syntax` |
84
+ | AI Generation | `midnight-generate-contract`, `midnight-review-contract`, `midnight-document-contract` |
85
+ | Status | `midnight-health-check`, `midnight-get-status` |
102
86
 
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.
87
+ **9 Embedded Resources** Quick references available offline: Compact syntax, SDK API, OpenZeppelin contracts, tokenomics, wallet integration, common errors
88
+
89
+ **5 Prompts** — `create-contract`, `review-contract`, `explain-concept`, `compare-approaches`, `debug-contract`
90
+
91
+ <details>
92
+ <summary><strong>Advanced Configuration</strong></summary>
104
93
 
105
94
  ### Local Mode (Optional)
106
95
 
@@ -122,117 +111,58 @@ Run everything locally for privacy or offline use:
122
111
  }
123
112
  ```
124
113
 
125
- Local mode requires ChromaDB (`docker run -d -p 8000:8000 chromadb/chroma`) and an OpenAI API key.
114
+ Requires ChromaDB (`docker run -d -p 8000:8000 chromadb/chroma`) and OpenAI API key.
126
115
 
127
116
  ### GitHub Token (Optional)
128
117
 
129
118
  Add `"GITHUB_TOKEN": "ghp_..."` for higher GitHub API rate limits (60 → 5000 requests/hour).
130
119
 
120
+ </details>
121
+
131
122
  ---
132
123
 
133
- ## Features
124
+ ## Indexed Repositories
125
+
126
+ The API indexes **22+ Midnight repositories**:
134
127
 
135
- ### Tools (19)
136
-
137
- | Tool | Description |
138
- | --------------------------------- | ------------------------------------------- |
139
- | `midnight-search-compact` | Search Compact contract code |
140
- | `midnight-search-typescript` | Search TypeScript SDK |
141
- | `midnight-search-docs` | Search documentation |
142
- | `midnight-analyze-contract` | Analyze contract structure and security |
143
- | `midnight-explain-circuit` | Explain circuits in plain language |
144
- | `midnight-get-file` | Get files from Midnight repos |
145
- | `midnight-list-examples` | List example contracts |
146
- | `midnight-get-latest-updates` | Recent repo changes |
147
- | `midnight-get-version-info` | Get version and release info |
148
- | `midnight-check-breaking-changes` | Check for breaking changes |
149
- | `midnight-get-migration-guide` | Migration guides between versions |
150
- | `midnight-get-file-at-version` | Get file at specific version |
151
- | `midnight-compare-syntax` | Compare files between versions |
152
- | `midnight-get-latest-syntax` | Latest syntax reference |
153
- | `midnight-health-check` | Check server health status |
154
- | `midnight-get-status` | Get rate limits and cache stats |
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 |
158
-
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.
160
-
161
- ### Resource Templates (4)
162
-
163
- Dynamic access to any resource using URI templates:
164
-
165
- | Template | Description |
166
- | --------------------------------------- | ------------------------------ |
167
- | `midnight://code/{owner}/{repo}/{path}` | Any code file from any repo |
168
- | `midnight://docs/{section}/{topic}` | Documentation by section/topic |
169
- | `midnight://examples/{category}/{name}` | Example contracts by category |
170
- | `midnight://schema/{type}` | JSON schemas (AST, tx, proofs) |
171
-
172
- ### Resources (20)
173
-
174
- - `midnight://docs/*` — Documentation (Compact reference, SDK API, ZK concepts)
175
- - `midnight://code/*` — Examples, patterns, and templates
176
- - `midnight://schema/*` — AST, transaction, and proof schemas
177
-
178
- ### Prompts (5)
179
-
180
- - `midnight:create-contract` — Create new contracts
181
- - `midnight:review-contract` — Security review
182
- - `midnight:explain-concept` — Learn Midnight concepts
183
- - `midnight:compare-approaches` — Compare implementation approaches
184
- - `midnight:debug-contract` — Debug issues
128
+ | Category | Repositories |
129
+ | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
130
+ | Core | `compact`, `midnight-js`, `midnight-wallet`, `midnight-docs` |
131
+ | Examples | `example-counter`, `example-bboard`, `example-dex`, `create-mn-app` |
132
+ | Infrastructure | `midnight-indexer`, `midnight-node-docker`, `midnight-dapp-connector-api` |
133
+ | Partner Libraries | `OpenZeppelin/compact-contracts`, `OpenZeppelin/midnight-apps` |
134
+ | Official Partners | `bricktowers/midnight-seabattle`, `bricktowers/midnight-identity`, `bricktowers/midnight-rwa`, `MeshJS/midnight-starter-template`, `midnames/core` |
185
135
 
186
136
  ---
187
137
 
188
138
  ## Developer Setup
189
139
 
190
- For contributors:
191
-
192
140
  ```bash
193
- git clone https://github.com/Olanetsoft/midnight-mcp.git
194
- cd midnight-mcp
195
- npm install
196
- npm run build
197
- npm test
141
+ git clone https://github.com/Olanetsoft/midnight-mcp.git && cd midnight-mcp
142
+ npm install && npm run build && npm test
198
143
  ```
199
144
 
200
- ### Testing with Local API
145
+ <details>
146
+ <summary><strong>API Backend & Local Development</strong></summary>
147
+
148
+ The hosted API runs on Cloudflare Workers + Vectorize. See [api/README.md](./api/README.md).
201
149
 
202
- To test against a local API server instead of production:
150
+ **Testing with Local API:**
203
151
 
204
152
  ```bash
205
153
  # Terminal 1: Start local API
206
- cd api
207
- npm install
208
- npm run dev # Starts at http://localhost:8787
154
+ cd api && npm install && npm run dev
209
155
 
210
156
  # Terminal 2: Run MCP with local API
211
157
  MIDNIGHT_API_URL=http://localhost:8787 npm start
212
158
  ```
213
159
 
214
- ### API Backend
215
-
216
- The hosted API runs on Cloudflare Workers + Vectorize. See [api/README.md](./api/README.md) for deployment and development instructions.
217
-
218
- ### Search Quality
219
-
220
- The API indexes **25 Midnight repositories** including core infrastructure, SDK, examples, ZK libraries, and developer tools.
221
-
222
- Search quality techniques:
160
+ </details>
223
161
 
224
- - **Optimized chunking** — 1000-char chunks with 200-char overlap for precise, contextual results
225
- - **Hybrid search** — Combines vector similarity with keyword boosting (up to 20% boost for exact matches)
226
- - **Incremental indexing** — Daily updates via tarball download + batch embeddings (~5 min)
162
+ ## Links
227
163
 
228
- View live metrics at the [Dashboard](https://midnight-mcp-api.midnightmcp.workers.dev/dashboard).
164
+ - [Midnight Docs](https://docs.midnight.network) [MCP Spec](https://modelcontextprotocol.io) • [Midnight GitHub](https://github.com/midnightntwrk)
229
165
 
230
166
  ## License
231
167
 
232
168
  MIT
233
-
234
- ## Links
235
-
236
- - [Midnight Docs](https://docs.midnight.network)
237
- - [MCP Spec](https://modelcontextprotocol.io)
238
- - [Midnight GitHub](https://github.com/midnightntwrk)
@@ -60,6 +60,24 @@ export const REPO_ALIASES = {
60
60
  "compact-contracts": { owner: "OpenZeppelin", repo: "compact-contracts" },
61
61
  openzeppelin: { owner: "OpenZeppelin", repo: "compact-contracts" },
62
62
  oz: { owner: "OpenZeppelin", repo: "compact-contracts" },
63
+ "midnight-apps": { owner: "OpenZeppelin", repo: "midnight-apps" },
64
+ lunarswap: { owner: "OpenZeppelin", repo: "midnight-apps" },
65
+ // Official Partners (from awesome-dapps)
66
+ "midnight-seabattle": { owner: "bricktowers", repo: "midnight-seabattle" },
67
+ seabattle: { owner: "bricktowers", repo: "midnight-seabattle" },
68
+ battleship: { owner: "bricktowers", repo: "midnight-seabattle" },
69
+ "midnight-identity": { owner: "bricktowers", repo: "midnight-identity" },
70
+ identity: { owner: "bricktowers", repo: "midnight-identity" },
71
+ "midnight-rwa": { owner: "bricktowers", repo: "midnight-rwa" },
72
+ rwa: { owner: "bricktowers", repo: "midnight-rwa" },
73
+ "midnight-starter-template": {
74
+ owner: "MeshJS",
75
+ repo: "midnight-starter-template",
76
+ },
77
+ meshjs: { owner: "MeshJS", repo: "midnight-starter-template" },
78
+ starter: { owner: "MeshJS", repo: "midnight-starter-template" },
79
+ midnames: { owner: "midnames", repo: "core" },
80
+ did: { owner: "midnames", repo: "core" },
63
81
  };
64
82
  export const EXAMPLES = [
65
83
  {
@@ -141,8 +141,10 @@ export async function getLatestUpdates(input) {
141
141
  * Get version and release info for a repository
142
142
  */
143
143
  export async function getVersionInfo(input) {
144
- logger.debug("Getting version info", input);
145
- const resolved = resolveRepo(input.repo);
144
+ // Ensure repo defaults to compact if undefined/empty
145
+ const repoName = input?.repo || "compact";
146
+ logger.debug("Getting version info", { repo: repoName });
147
+ const resolved = resolveRepo(repoName);
146
148
  if (!resolved) {
147
149
  throw new Error(`Unknown repository: ${input.repo}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
148
150
  }
@@ -170,10 +172,15 @@ export async function getVersionInfo(input) {
170
172
  * Check for breaking changes since a specific version
171
173
  */
172
174
  export async function checkBreakingChanges(input) {
173
- logger.debug("Checking breaking changes", input);
174
- const resolved = resolveRepo(input.repo);
175
+ // Ensure repo defaults to compact if undefined/empty
176
+ const repoName = input?.repo || "compact";
177
+ logger.debug("Checking breaking changes", {
178
+ repo: repoName,
179
+ currentVersion: input.currentVersion,
180
+ });
181
+ const resolved = resolveRepo(repoName);
175
182
  if (!resolved) {
176
- throw new Error(`Unknown repository: ${input.repo}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
183
+ throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
177
184
  }
178
185
  const outdatedInfo = await releaseTracker.isOutdated(resolved.owner, resolved.repo, input.currentVersion);
179
186
  const breakingChanges = await releaseTracker.getBreakingChangesSince(resolved.owner, resolved.repo, input.currentVersion);
@@ -196,10 +203,16 @@ export async function checkBreakingChanges(input) {
196
203
  * Get migration guide between versions
197
204
  */
198
205
  export async function getMigrationGuide(input) {
199
- logger.debug("Getting migration guide", input);
200
- const resolved = resolveRepo(input.repo);
206
+ // Ensure repo defaults to compact if undefined/empty
207
+ const repoName = input?.repo || "compact";
208
+ logger.debug("Getting migration guide", {
209
+ repo: repoName,
210
+ fromVersion: input.fromVersion,
211
+ toVersion: input.toVersion,
212
+ });
213
+ const resolved = resolveRepo(repoName);
201
214
  if (!resolved) {
202
- throw new Error(`Unknown repository: ${input.repo}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
215
+ throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
203
216
  }
204
217
  const guide = await releaseTracker.getMigrationGuide(resolved.owner, resolved.repo, input.fromVersion, input.toVersion);
205
218
  return {
@@ -226,14 +239,20 @@ export async function getMigrationGuide(input) {
226
239
  * Get a file at a specific version - critical for version-accurate recommendations
227
240
  */
228
241
  export async function getFileAtVersion(input) {
229
- logger.debug("Getting file at version", input);
230
- const resolved = resolveRepo(input.repo);
242
+ // Ensure repo defaults to compact if undefined/empty
243
+ const repoName = input?.repo || "compact";
244
+ logger.debug("Getting file at version", {
245
+ repo: repoName,
246
+ path: input.path,
247
+ version: input.version,
248
+ });
249
+ const resolved = resolveRepo(repoName);
231
250
  if (!resolved) {
232
- throw new Error(`Unknown repository: ${input.repo}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
251
+ throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
233
252
  }
234
253
  const result = await releaseTracker.getFileAtVersion(resolved.owner, resolved.repo, input.path, input.version);
235
254
  if (!result) {
236
- throw new Error(`File not found: ${input.path} at version ${input.version} in ${input.repo}`);
255
+ throw new Error(`File not found: ${input.path} at version ${input.version} in ${repoName}`);
237
256
  }
238
257
  return {
239
258
  repository: `${resolved.owner}/${resolved.repo}`,
@@ -247,10 +266,16 @@ export async function getFileAtVersion(input) {
247
266
  * Compare syntax between two versions - shows what changed
248
267
  */
249
268
  export async function compareSyntax(input) {
250
- logger.debug("Comparing syntax between versions", input);
251
- const resolved = resolveRepo(input.repo);
269
+ // Ensure repo defaults to compact if undefined/empty
270
+ const repoName = input?.repo || "compact";
271
+ logger.debug("Comparing syntax between versions", {
272
+ repo: repoName,
273
+ oldVersion: input.oldVersion,
274
+ newVersion: input.newVersion,
275
+ });
276
+ const resolved = resolveRepo(repoName);
252
277
  if (!resolved) {
253
- throw new Error(`Unknown repository: ${input.repo}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
278
+ throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
254
279
  }
255
280
  // If no newVersion specified, get latest
256
281
  let newVersion = input.newVersion;
@@ -280,10 +305,12 @@ export async function compareSyntax(input) {
280
305
  * This is the source of truth for writing valid, compilable contracts
281
306
  */
282
307
  export async function getLatestSyntax(input) {
283
- logger.debug("Getting latest syntax reference", input);
284
- const resolved = resolveRepo(input.repo);
308
+ // Ensure repo defaults to compact if undefined/empty
309
+ const repoName = input?.repo || "compact";
310
+ logger.debug("Getting latest syntax reference", { repo: repoName });
311
+ const resolved = resolveRepo(repoName);
285
312
  if (!resolved) {
286
- throw new Error(`Unknown repository: ${input.repo}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
313
+ throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
287
314
  }
288
315
  const reference = await releaseTracker.getLatestSyntaxReference(resolved.owner, resolved.repo);
289
316
  if (!reference || reference.syntaxFiles.length === 0) {
@@ -173,7 +173,7 @@ export const DEFAULT_REPOSITORIES = [
173
173
  patterns: ["**/*.md"],
174
174
  exclude: [],
175
175
  },
176
- // Partner Libraries
176
+ // Partner Libraries (OpenZeppelin)
177
177
  {
178
178
  owner: "OpenZeppelin",
179
179
  repo: "compact-contracts",
@@ -181,5 +181,48 @@ export const DEFAULT_REPOSITORIES = [
181
181
  patterns: ["**/*.compact", "**/*.ts", "**/*.md"],
182
182
  exclude: ["node_modules/**", "dist/**"],
183
183
  },
184
+ {
185
+ owner: "OpenZeppelin",
186
+ repo: "midnight-apps",
187
+ branch: "main",
188
+ patterns: ["**/*.compact", "**/*.ts", "**/*.md"],
189
+ exclude: ["node_modules/**", "dist/**"],
190
+ },
191
+ // Official Partners (from awesome-dapps)
192
+ {
193
+ owner: "bricktowers",
194
+ repo: "midnight-seabattle",
195
+ branch: "main",
196
+ patterns: ["**/*.compact", "**/*.ts", "**/*.md"],
197
+ exclude: ["node_modules/**", "dist/**"],
198
+ },
199
+ {
200
+ owner: "bricktowers",
201
+ repo: "midnight-identity",
202
+ branch: "main",
203
+ patterns: ["**/*.compact", "**/*.ts", "**/*.md"],
204
+ exclude: ["node_modules/**", "dist/**"],
205
+ },
206
+ {
207
+ owner: "bricktowers",
208
+ repo: "midnight-rwa",
209
+ branch: "main",
210
+ patterns: ["**/*.compact", "**/*.ts", "**/*.md"],
211
+ exclude: ["node_modules/**", "dist/**"],
212
+ },
213
+ {
214
+ owner: "MeshJS",
215
+ repo: "midnight-starter-template",
216
+ branch: "main",
217
+ patterns: ["**/*.compact", "**/*.ts", "**/*.md"],
218
+ exclude: ["node_modules/**", "dist/**"],
219
+ },
220
+ {
221
+ owner: "midnames",
222
+ repo: "core",
223
+ branch: "main",
224
+ patterns: ["**/*.compact", "**/*.ts", "**/*.md"],
225
+ exclude: ["node_modules/**", "dist/**"],
226
+ },
184
227
  ];
185
228
  //# sourceMappingURL=config.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "midnight-mcp",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Model Context Protocol Server for Midnight Blockchain Development",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",