Using midnight-mcp for Contract Development with AI Assistants
If you've spent any time writing Compact contracts on Midnight, you've hit the same wall I did: the feedback loop is brutal. You write a contract, run the compiler, wait 10–30 seconds, get an error that points to the wrong line, and then go read docs in a separate tab for five minutes. Repeat until done.
midnight-mcp changes that loop entirely. It's a Model Context Protocol server that plugs directly into Claude Desktop, Cursor, or VS Code Copilot and gives your AI assistant real access to Midnight's compiler, contract analyzer, and indexed documentation — right inside your editor. No context switching. No tab juggling.
This is what building with Midnight should feel like.
What midnight-mcp Actually Does
Before jumping into setup, it's worth knowing what you're getting. midnight-mcp exposes 29 tools across several categories:
- Compilation: Real Compact compilation via a hosted service, with two modes — fast syntax validation (~1–2 seconds) and full ZK circuit generation (~10–30 seconds)
- Analysis: Static analysis that catches deprecated patterns, type errors, and security issues before you even compile
- Search: Semantic search across Midnight's 102+ indexed repositories — contracts, SDK references, documentation, examples
- Generation and Review: AI-powered contract generation and code review (when your client supports sampling)
The compilation tool is what genuinely surprised me. It's not a linter. It's talking to a real Midnight compiler service, which means it catches the semantic errors that no amount of static analysis can find — disclose rule violations, sealed field misuse, ZK circuit incompatibilities. Things that will silently wreck your contract if you don't find them early.
Installing and Configuring
You need Node.js 20+ first. Check with node --version. If you're under 20, update.
Claude Desktop
Open your config file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
Add this:
{
"mcpServers": {
"midnight": {
"command": "npx",
"args": ["-y", "midnight-mcp@latest"]
}
}
}
Restart Claude Desktop. That's it. No API keys. No configuration server. The @latest tag matters — without it you get a cached version that never updates, and this package ships fixes frequently.
One caveat: if you manage Node through nvm, Claude Desktop won't see your nvm-managed binary. Use this instead:
{
"mcpServers": {
"midnight": {
"command": "/bin/sh",
"args": [
"-c",
"source ~/.nvm/nvm.sh && nvm use 20 >/dev/null 2>&1 && npx -y midnight-mcp@latest"
]
}
}
}
I spent 20 minutes debugging this before I found that note in the README. Save yourself the trouble.
Cursor
Click the one-click install badge on the GitHub README, or add this to .cursor/mcp.json manually:
{
"mcpServers": {
"midnight": {
"command": "npx",
"args": ["-y", "midnight-mcp@latest"]
}
}
}
Restart Cursor. The MCP tools show up in the sidebar once the server connects.
Optional: GitHub Token
midnight-mcp searches across GitHub-hosted repositories. Without a token, you're limited to 60 GitHub API requests per hour. With one, it's 5,000. Add it to your config:
{
"mcpServers": {
"midnight": {
"command": "npx",
"args": ["-y", "midnight-mcp@latest"],
"env": {
"GITHUB_TOKEN": "ghp_your_token_here"
}
}
}
}
For casual use, the unauthenticated limit is fine. For heavy development sessions, get a token.
Searching Docs and Code Examples
Once midnight-mcp is running, your AI assistant gains access to the entire Midnight documentation and repository ecosystem. Here's what that looks like in practice.
Open Claude Desktop and ask: "How do I declare a ledger field in Compact?"
Without midnight-mcp, the assistant gives you a generic answer from its training data — which may be outdated. With midnight-mcp, it calls midnight-search-docs and midnight-search-compact against live, indexed content and returns current syntax with working examples pulled from real contracts.
The difference matters on Midnight more than most chains. Compact has gone through significant syntax changes — the old ledger { } block format is gone, pragma format changed in 0.16, Void is no longer a type. Documentation from six months ago will send you down wrong paths. midnight-mcp's indexed content stays current.
Try asking: "Show me an example of a token contract in Compact." The tool calls midnight-list-examples and midnight-get-file against the indexed repositories and returns actual, tested contract code — not a hallucinated approximation.
Using the Compilation Endpoint
This is the tool I use most. Here's the workflow.
You're writing a counter contract:
pragma language_version >= 0.16 && <= 0.21;
export ledger counter: Counter;
export ledger struct Counter {
value: Uint<32>;
}
export circuit increment(amount: Uint<32>): [] {
counter.value = counter.value + amount;
}
Ask your AI assistant: "Compile this Compact contract and check for errors."
The assistant calls midnight-compile-contract with skipZk: true for fast mode. Fast mode does syntax and semantic validation in 1–2 seconds — good enough for the inner development loop. When you're ready for a pre-deployment check, ask it to use full compilation mode, which runs ZK circuit generation and catches circuit-level constraints that fast mode skips.
A successful fast compilation looks like this in the tool response:
✅ Compilation successful (Compiler v0.29.0) in 1243ms
When something's wrong, you get structured error output that your AI assistant can reason about directly. This is the part that genuinely changes the workflow — the assistant sees the compiler error, understands the context of your contract, and explains what went wrong in plain English. Sometimes it fixes the code automatically before you even read the error.
The Bug Story: AI Catches a Real Error
Let me show you the moment this actually paid off for me.
I was writing a simple voting contract — a ledger that tracks votes per proposal, with a circuit to cast a vote. The contract compiled fine locally (or so I thought — I was using an older compiler version). I pasted it into Claude and asked for a review.
Here's the broken version:
pragma language_version >= 0.16 && <= 0.21;
module voting;
ledger votes: Map<Uint<32>, Uint<64>>;
export circuit cast_vote(proposal_id: Uint<32>): Void {
votes.set(proposal_id, votes.get(proposal_id, 0) + 1);
}
Before I could ask anything specific, midnight-mcp's static analysis tool (midnight-extract-contract-structure) flagged three issues:
-
P0 — deprecated_ledger_block: The
ledger votessyntax is wrong. Modern Compact usesexport ledger votes: Map<Uint<32>, Uint<64>>;at the module level. -
P0 — invalid_void_type:
Voidis not a valid Compact type. The return type for a circuit with no return value is[](empty tuple). - P0 — module_level_const: The module declaration syntax was wrong for this pragma version.
Three breaking errors. Zero indication from my local setup that anything was wrong.
The compilation endpoint confirmed the P0 errors immediately:
❌ Compilation failed (Compiler v0.29.0) in 891ms
Error: Type 'Void' is not defined. Did you mean '[]'?
at cast_vote return type declaration (line 8)
The assistant generated the corrected contract:
pragma language_version >= 0.16 && <= 0.21;
export ledger votes: Map<Uint<32>, Uint<64>>;
export circuit cast_vote(proposal_id: Uint<32>): [] {
votes.set(proposal_id, votes.get(proposal_id, 0) + 1);
}
Re-compile:
✅ Compilation successful (Compiler v0.29.0) in 1104ms
This is where most people get it wrong when they evaluate AI coding assistants: they assume the value is code generation. It's not. The value is grounding the AI in real, current compiler feedback. An AI without midnight-mcp will tell you Void is a valid type because it was, once, in some version of the language. With midnight-mcp, it knows the actual current compiler says otherwise.
Running Contract Analysis for Security Patterns
Beyond compilation, midnight-analyze-contract does a security-focused pass over your Compact code. It checks for patterns that compile successfully but create vulnerabilities or unexpected behavior.
Give it any contract and ask: "Analyze this contract for security issues."
The tool checks for:
-
Overflow risks in arithmetic on bounded types —
Uint<32>wraps silently if you're not careful - Division by zero paths that can halt circuit execution
- Assertion patterns that may not behave as expected in ZK circuits
- Unexported enums that will compile fine but won't be accessible from TypeScript SDK code
- Disclose rule violations that might leak data you intended to keep private
The privacy angle is the one I find most valuable. Midnight's whole value proposition is selective disclosure of private data — ZK proofs let you verify a claim without revealing the underlying information. But if you accidentally add a disclose where you shouldn't, or structure your circuit in a way that leaks a commitment, you've undermined the entire security model. The analyzer catches the obvious cases.
It's not a formal verification tool. Don't treat it like one. But it catches the mistakes that are easy to make when you're moving fast, and it explains why each finding matters. That's the right role for a static analysis pass.
Full Mode for Pre-Deployment Checks
One more thing worth knowing: when you're serious about deploying a contract, run full compilation mode. Fast mode skips ZK circuit generation, which means it won't catch constraints that only manifest at the circuit level. Ask your assistant to compile with fullCompile: true:
✅ Full compilation successful (Compiler v0.29.0) in 18340ms
ZK circuit generated: 2,847 constraints
Proof size: 1.2KB
The 10–30 second wait is real. Don't use full mode for every iteration — that's what fast mode is for. But before you deploy, do the full pass. It's caught issues for me that fast mode cleared.
Putting It Together
Here's the development workflow I've settled into with midnight-mcp:
- Start a new contract — ask the AI to scaffold it using
midnight-generate-contractwith a description of what you want - Iterate on the logic — use fast compilation on each meaningful change
- When the logic feels right — run
midnight-analyze-contractfor a security pass - Search for similar examples —
midnight-search-compactacross the indexed ecosystem to see if there's a better pattern - Final check — full compilation before deployment
The inner loop is genuinely faster. The outer loop catches things I would have missed. That's the combination that makes midnight-mcp worth adding to your setup.
The ecosystem around Midnight is moving quickly — new compiler versions, syntax changes, new SDK APIs. Having an AI assistant that's grounded in current indexed content rather than training data snapshots isn't a nice-to-have. On a chain where the language is still evolving, it's how you stay out of trouble.
Install it. The 10-second config edit is worth it.
midnight-mcp is open source under MIT: github.com/Olanetsoft/midnight-mcp
Midnight developer docs: docs.midnight.network
Top comments (0)