Haskell Dev Tools
БесплатноНе проверенMCP server providing 36 Haskell development tools with an in-process GHC session for correct Haskell code generation.
Описание
MCP server providing 36 Haskell development tools with an in-process GHC session for correct Haskell code generation.
README
🌀 haskell-flows
Property-first Haskell, driven by your AI agent.
An MCP server that turns "LLMs that write plausible Haskell" into "LLMs that write correct Haskell" — through QuickCheck laws, in-process GHC, and snapshot-verified refactors.
⚡ The 30-second story
Plug into Claude Code, Cursor, or any MCP host. Your agent gets 36 tools that share one in-process GHC session and one normative response envelope — every call answers with the same structured shape, every gate is honest, every refactor verifies-or-rolls-back.
ghc_project(create) ─▶ ghc_modules ─▶ ghc_load
│
├─▶ ghc_suggest ← multi-engine law proposer w/ confidence + sibling-aware
├─▶ ghc_quickcheck ← runs + auto-persists on pass; runs>=2 catches flakes
├─▶ ghc_property_store(run) ← replays the whole persisted set
├─▶ ghc_refactor ← snapshot + compile-verify + rollback on red
└─▶ ghc_gate ← regression + cabal test + cabal build, one call
📘 Full flows → docs/flows.md · 🚀 Install → docs/install.md · 🛡 Trust model → SECURITY.md
🎯 What makes it different
| 🧪 Property-first | ghc_suggest proposes laws from the function name — 8 engines (endomorphism, binary-op, list, roundtrip, evaluator-preservation, constant-folding, functor, sibling-aware) each with confidence + rationale. Low-confidence suggestions come with "this probably fails because…". |
| ⚙️ In-process GHC | No subprocess GHCi, no pipe framing, no prompt parsing. Every tool calls runGhc/compileExpr/exprType against the server's own HscEnv. Diagnostics arrive structured via LogAction hook. Any uncaught exception evicts the session; next call boots fresh. |
| 📦 Unified envelope | Every response: {status, result?, error?, warnings?, nextStep?}. Status is one of 7 closed values. Errors carry one of 26 closed ErrorKind constructors. The legacy success/error_kind booleans are gone — status is the discriminator. |
💡 Two bugs. One session. Zero tests written by hand.
Building a 5-module arithmetic-expression evaluator, ghc_suggest proposed two laws and ghc_quickcheck found two real bugs automatically:
Bug 1 — unsound zero-annihilator (case 245 of 300):
-- prop_semanticPreservation: ∀ e env. eval env (simplify e) == eval env e
-- counterexample found:
e = Mul (Lit 0) (Neg (Mul (Lit 0) (Var "a")))
eval env e = Left (UnboundVariable "a") -- correct
eval env (simplify e) = Right 0 -- WRONG: error silently swallowed
The rule 0 * x → 0 dropped the right operand without checking it evaluates successfully. Fix: restrict to Lit 0 * Lit _ → Lit 0 — never discard a subexpression that could fail.
Bug 2 — parser ambiguity (case 13 of 300):
-- prop_parsePrettyRoundtrip: ∀ e. parse (pretty e) == Just e
-- counterexample found:
e = Add (Lit (-8)) (Lit 0)
pretty e = "(-8 + 0)" -- looks fine
parse it = Nothing -- parser read "(-" as start of negation, not negative literal
Fix: change negation syntax from (-e) to (~ e) — lexically unambiguous with negative integer literals.
ghc_suggest + ghc_quickcheck caught what a type-checker alone never could: semantic soundness violations. These are the properties you forget to write; the MCP finds and runs them automatically.
🛠 The tool surface — 36 in 7 phases
| Phase | Tools | Marquee |
|---|---|---|
| 🏗 Scaffold | 4 | ghc_project(action=create) · ghc_modules · ghc_workflow · ghc_toolchain |
| 🔍 Inspect | 9 | ghc_load · ghc_browse · ghc_eval · ghc_hole · ghc_type · ghc_info · ghc_complete · ghc_goto · ghc_doc |
| 📚 Deps & scope | 5 | ghc_deps · ghc_add_import · ghc_apply_exports · ghc_imports · hoogle_search |
| 🧪 Property-first | 4 | ghc_suggest · ghc_quickcheck · ghc_property_store (list/run/export/audit) · ghc_arbitrary |
| 🛡 Gates | 7 | ghc_check_module · ghc_check_project · ghc_gate · ghc_lint · ghc_fix_warning · ghc_format · ghc_coverage |
| ✏️ Refactor | 1 | ghc_refactor — snapshot + compile-verify + rollback |
| 🧠 Advanced | 6 | ghc_lab · ghc_witness · ghc_explain_error · ghc_perf · ghc_batch · ghc_scratch |
Every response carries a nextStep pointer at the most-likely follow-up call, plus an optional multi-step chain your agent can ghc_batch in one round-trip.
ghc_scratch is the LLM's shared whiteboard — hypothesis code that persists between turns, type-checks in isolation, and can be promoted into a real module via ghc_refactor's snapshot-and-compile-verify when the idea is proven.
ghc_workflow(action=discover) ranks unused tools by relevance to the current session phase, so your agent doesn't get stuck in its 10 favourite tools. action=post-mortem delivers a session retro — what ran, what was missed, what properties are persisted. action=plan turns a natural-language goal into a concrete, batchable tool chain.
🚀 Install
# Pre-built binary (darwin-arm64 or linux-x64)
PLATFORM=darwin-arm64 VERSION=v0.1.0
curl -L "https://github.com/damian-rafael-lattenero/haskell-rules-and-mcp/releases/download/$VERSION/haskell-flows-mcp-$PLATFORM.tar.gz" \
| tar -xz -C "$HOME/.local/bin/"
Or build from source:
git clone https://github.com/damian-rafael-lattenero/haskell-rules-and-mcp
cd haskell-rules-and-mcp/mcp-server-haskell
cabal install exe:haskell-flows-mcp --installdir="$HOME/.local/bin" \
--install-method=copy --overwrite-policy=always
Point your MCP host at ~/.local/bin/haskell-flows-mcp. No rules file needed — the initialize.instructions handshake ships a situation→tool table dynamically derived from the live registry. If your host insists on a project-level rules file, run ghc_project(action="bootstrap", host="claude-code", write=true).
🏛 Architecture
┌──────────────────────────────────────────────────────────────────────┐
│ MCP client (Claude Code · Cursor · any JSON-RPC-over-stdio host) │
└──────────────────────────────┬───────────────────────────────────────┘
│ newline-delimited JSON-RPC 2.0
┌──────────────────────────────┴───────────────────────────────────────┐
│ Mcp.Server · 36-tool dispatch · 10-min outer timeout │
│ Mcp.Envelope · status × result × error × warnings × nextStep │
│ Mcp.NextStep · per-tool routing (envelope-aware, failure-path) │
│ Mcp.WorkflowState · session memory (ever-called set, call log) │
├──────────────────────────────────────────────────────────────────────┤
│ Tool handlers (36 modules, one per tool, all envelope-emitting) │
├──────────────────────────────────────────────────────────────────────┤
│ Ghc.ApiSession · MVar-guarded HscEnv · evict-on-exception │
│ · runGhc · compileExpr · exprType · getInfo │
│ · LogAction hook → structured diagnostics │
├──────────────────────────────────────────────────────────────────────┤
│ PropertyStore · MVar-locked JSON · per-project regression set │
│ Refactor · snapshot + compile-verify + rollback primitives │
│ Parsers · Error · Hole · Type · TypeSignature · QuickCheck │
└──────────────────────────────────────────────────────────────────────┘
~25,700 lines of Haskell (source). Single binary. No daemon, no IPC, no external state — just stdin/stdout + your project tree + ~/.haskell-flows/.
🛡 Security invariants — by construction, not by convention
| Invariant | Mechanism |
|---|---|
| Path traversal impossible | ModulePath smart-ctor rejects .. via segment split (not prefix check). Every user-supplied path routes through it. |
| No shell interpolation | Every subprocess (cabal, hlint, fourmolu) spawned argv-form via proc "cmd" [args]. Agent input never reaches sh. |
| Input sanitised | sanitizeExpression rejects newlines, framing sentinels, and inputs > 64 KiB before any compileExpr. |
| DoS caps | 64 KiB output cap on ghc_eval · 30 s inner per-eval timeout · 10-min outer per-tool ceiling. |
| Session liveness | Any uncaught exception evicts the HscEnv. Next call boots fresh. No poison carried forward. |
| Refactor atomicity | ghc_refactor snapshots + compile-verifies + rolls back on type-check failure. No broken intermediates on disk. |
.cabal integrity |
ghc_deps / ghc_modules re-parse after every write; refuse to persist a shape that disagrees with the verb. |
| Concurrent saves serialised | PropertyStore writes go through MVar lock — no torn JSON under parallel callers. |
One deliberate non-invariant:
ghc_evalis arbitrary code execution by design. Anything that can sendtools/callalready has ambient authority equivalent to a shell run by the user that launched the MCP. If your threat model needs a sandbox, run the MCP in one (container / VM / jail).
📊 Status
| 🏷 Release | v0.1.0 tagged; v0.2.0 unreleased on master — 36 tools, 47→36 consolidation + ghc_scratch + session intelligence |
| 🧪 Test coverage | 700+ unit-test functions across 80+ domain modules · 72 E2E scenarios · QuickCheck property fuzzing on all boundary validators |
| ✅ CI matrix | 4 cells: {ubuntu-latest, macos-latest} × {GHC 9.10.1, 9.12.2} |
| 🛡 Closed enum | ErrorKind is 26 constructors — every error path on the wire is enumerable; ToolName ADT gates all dispatch |
| 📜 Wire contract | #90 closed — single envelope, status discriminator, structured error.kind, nextStep on every success (and curated errors) |
| 🧠 Session intelligence | ghc_workflow(discover) ranks unused tools by phase · post-mortem retros the session · plan turns NL goals into batchable chains |
| 🏗 Platforms | darwin-arm64 ✅ · linux-x64 ✅ · darwin-x64 ⚠️ build-from-source · others ❌ untested |
Iterated with Claude Code following the spirit of the Haskell Compact for Responsible Use of AI Tools. Maintainer accountability via tests; commits with substantive AI-generated code carry Co-Authored-By: Claude trailers. Tagged vibecoded — provenance is on the record, not hidden.
Known limitations
ghc_evalis RCE-by-design — see security section. Layer your sandbox below the MCP.- Suggestion engines use regex on type strings — higher-rank, type-families, GADTs return zero suggestions.
- Not an HLS replacement.
ghc_goto/ghc_docare thin; keep your LSP for cross-module jump. - Bus factor of 1. Single maintainer, no SLA. See CONTRIBUTING.md.
📚 Resources
| 📘 Tool reference (PDF) | docs/haskell-flows-mcp.pdf |
| 🧭 Flow diagrams | docs/flows.md |
| 🗂 Tool taxonomy | docs/TOOL_TAXONOMY.md |
| 🚀 Install guide | docs/install.md |
| 📝 Changelog | CHANGELOG.md |
| 🤝 Contributing | CONTRIBUTING.md |
| 🛡 Security | SECURITY.md |
| 🗒 Dogfood — first session | docs/dogfood-2026-04-19.md |
| 🗒 Dogfood — full audit | docs/dogfood-2026-05-25-full-audit.md |
BSD-3-Clause · Copyright © 2026 Damián Rafael Lattenero · Releases · Issues · Discussions
from github.com/damian-rafael-lattenero/haskell-rules-and-mcp
Установка Haskell Dev Tools
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/damian-rafael-lattenero/haskell-rules-and-mcpFAQ
Haskell Dev Tools MCP бесплатный?
Да, Haskell Dev Tools MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для Haskell Dev Tools?
Нет, Haskell Dev Tools работает без API-ключей и переменных окружения.
Haskell Dev Tools — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить Haskell Dev Tools в Claude Desktop, Claude Code или Cursor?
Открой Haskell Dev Tools на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectCompare Haskell Dev Tools with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
