Euclid-MCP
Allows integration with Make to automate reasoning, diagnosis, what-if analysis, and knowledge base validation using the Euclid-MCP REST API.
Allows integration with n8n to automate reasoning, diagnosis, what-if analysis, and knowledge base validation using the Euclid-MCP REST API.
Allows integration with Zapier to automate reasoning, diagnosis, what-if analysis, and knowledge base validation using the Euclid-MCP REST API.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Euclid-MCPFind all ancestors of Tom in family tree"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Euclid-MCP
Deterministic logical reasoning for MCP clients, with proof trees.
Reference implementation of Euclid-MCP: A Model Context Protocol Server for Deterministic Logical Reasoning via Prolog (Bogliolo, arXiv:2607.21412v1).
An LLM is good at describing a world and bad at deducing over it. Euclid-MCP splits those jobs: the model writes facts, rules and a query in a small declarative language (Euclid-IR); the server compiles that to Prolog, runs it in a sandboxed subprocess, and returns exact answers with a derivation for every one of them. On a 1,000-user RBAC knowledge base where natural-language reasoning hallucinates counts, this returns 31 and 103 — every time, with the proof attached.
┌────────────┐ Euclid-IR ┌──────────────────────────────┐ Prolog ┌────────────┐
│ LLM client │ ─────────────▶ │ Euclid-MCP server │ ──────────▶ │ SWI-Prolog │
│ (MCP) │ │ parse → lower → sanitize → │ (subproc) │ (deduce) │
│ │ ◀───────────── │ run → parse JSON → typed │ ◀────────── │ │
└────────────┘ solutions + │ result │ JSON └────────────┘
proof trees └──────────────────────────────┘Install
pip install euclid-mcpSWI-Prolog is a system dependency, not a pip dependency. You need swipl
9.0 or later on PATH:
Platform | Command |
Debian/Ubuntu |
|
macOS |
|
Fedora |
|
Windows |
Check that the backend is visible:
python -m euclid_mcp --check
# euclid-mcp 0.1.0
# backend: SWI-Prolog version 9.0.4 for x86_64-linuxOr skip the install entirely and use the Docker image, which bundles SWI-Prolog:
docker build -t euclid-mcp .
docker run --rm -p 8000:8000 euclid-mcp
curl -s localhost:8000/healthRelated MCP server: Pyke MCP Server
Connect an MCP client
python -m euclid_mcp speaks MCP over stdio. For Claude Desktop, Cursor, or any
other MCP client, add:
{
"mcpServers": {
"euclid": {
"command": "python",
"args": ["-m", "euclid_mcp"]
}
}
}Euclid-IR in one screen
One logical item per line. Predicates and constants are lowercase; variables
start with $.
@version 1.0 # optional directive
parent(tom, bob) # a fact - must be ground
parent(bob, ann)
mortal($x) IF human($x) # a rule
ancestor($x, $y) IF parent($x, $y)
ancestor($x, $y) IF parent($x, $z) AND # continues: line ends in AND
ancestor($z, $y)
blocked($u) IF NOT active($u) # closed-world negation
stale($u) IF last_login($u, $d) AND $d > 90 # arithmetic comparison
resource(apple, $color, _, _, _, _) # _ is a wildcard
? ancestor(tom, $who) # a queryComparison operators: > >= < =< =:= =\= is.
Comments: # or //, whole-line or inline.
There is also an equivalent YAML form; both load into the same AST.
version: "1.0"
facts:
- parent(tom, bob)
rules:
- head: ancestor($x, $y)
body: [ parent($x, $y) ]
queries:
- ? ancestor(tom, $who)Deliberately not supported
Not supported | Do this instead |
disjunction ( | write several rules with the same head |
lists | model a collection as several facts |
strings | use lowercase atoms |
cut | nothing — proofs are always complete |
| precompute counts as facts ( |
runtime | use the |
modules | — |
These restrictions are the point: they keep every proof finite, traceable and reproducible, and they keep the language portable to a second backend. Each one is rejected at parse time with a message that names the construct and the workaround.
The four tools
All four are stateless and read-only: knowledge in, typed result out.
Tool | Purpose |
| Prove a goal; return every solution with its proof tree |
| Explain a result: |
| Apply |
| Static validation — syntax, undefined predicates, cycles, duplicates |
They are designed around a translate-run-inspect-repair loop:
Validate —
check_kbconfirms the knowledge base is well-formed (no backend needed, so it is cheap).Translate — the client emits Euclid-IR: facts, rules, query.
Run —
reasonreturns answers plus derivations.Inspect — on a surprising result,
diagnosewithwhyorwhy_not.Repair — refine the knowledge base from the diagnosis; re-run.
Explore —
what_iftests a hypothetical change before committing to it.
Every failure — a parse error, an unsupported construct, an oversized payload, a
timeout — comes back as ok: false with an actionable message rather than an
exception, so the client can correct itself and retry.
reason
reason(knowledge="""
parent(tom, bob)
parent(bob, ann)
ancestor($x, $y) IF parent($x, $y)
ancestor($x, $y) IF parent($x, $z) AND ancestor($z, $y)
""", query="ancestor(tom, $who)")solution_count: 2, truncated: false
$who = ann
ancestor(tom, ann) [rule]
parent(tom, bob) [fact]
ancestor(bob, ann) [rule]
parent(bob, ann) [fact]
$who = bob
ancestor(tom, bob) [rule]
parent(tom, bob) [fact]An empty solutions list with ok: true is a real answer: under closed-world
semantics the knowledge base does not entail the goal.
diagnose
diagnose(knowledge="human(socrates)", query="mortal(plato)", mode="why_not")
# holds: false
# findings: ["No facts or rules defined for 'mortal'"]
# conclusion: The knowledge base defines nothing for `mortal`, so any goal that
# depends on it fails. Add the missing facts or a rule whose head uses it.what_needs goes further and abduces the repair: given mortal($x) IF human($x)
it answers that adding human(plato) would make the goal hold.
what_if
what_if(base_knowledge=rbac_kb,
modifications="- has_role(eng_0002, intern)\n+ has_role(eng_0002, senior_dev)",
query="user_has_permission(eng_0002, deploy_code)")
# before_count: 0, after_count: 1, delta: 1A - line that matches no existing fact is an error, not a silent no-op: a
scenario built on a false premise would give a misleading answer.
REST API
For automation platforms (n8n, Zapier, Make) and remote access. The endpoints call the same tool functions with the same Pydantic models — one schema, two surfaces.
python -m euclid_mcp --http --host 0.0.0.0 --port 8000Method | Path | Body | Response |
POST |
|
|
|
POST |
|
|
|
POST |
|
|
|
POST |
|
|
|
GET |
| — |
|
OpenAPI docs are at /docs. CORS is off by default; set
EUCLID_MCP_CORS_ORIGINS to a comma-separated origin list (or *) to enable it
for browser clients.
Do not expose this API to an untrusted network as-is. There is no authentication, authorization or rate limiting, and nothing caps concurrent work. Every request spawns a reasoning subprocess that may run for the full 30 s timeout — and
what_ifanddiagnoseeach run the backend twice, so one request can buy ~60 s of CPU. A handful of small requests will saturate every core. The CLI binds loopback by default; the container image binds0.0.0.0.Put a reverse proxy in front of it providing auth, rate limiting and a concurrency cap, or keep it on a trusted network. See
THREATMODEL.mdfinding F4.
Safety
The LLM cannot make the backend do anything but deduce.
Size cap —
knowledgeover 500 KB is rejected before parsing.Time bound — every program runs under a 30 s wall clock, enforced both by the subprocess and by
call_with_time_limit/2inside Prolog.Allow-list — only constructors reachable from the grammar can be emitted. File I/O, network, shell,
consult,use_moduleand runtimeassert/retractare unreachable from Euclid-IR and rejected if they somehow appear.Generated-text audit — the lowered program is scanned for denied built-ins before it runs, so a lowering bug cannot smuggle one through.
In-Prolog verification — before executing anything, the harness walks every clause body and refuses to run if it finds a goal that is not a declared knowledge-base predicate, a comparison, or a negation of those.
No
shell=True, argv lists only, temp files removed in afinally.
What is not defended
Read THREATMODEL.md before deploying. In short:
Soundness is relative to the encoded rules, not to reality. The model writes the knowledge base; wrong premises yield wrong conclusions with valid proofs. The proof tree is what makes that auditable — treat the knowledge base as the security-relevant artefact and review it.
A zero-solution answer can mean "search depth exhausted", not "false" — the two are currently indistinguishable, and the answer can flip when
max_depthrises (finding F1).solution_countis what was returned, not what exists. Always checktruncatedbefore treating it as a total (F2).The REST API is unauthenticated with no rate limiting (F4, above).
Memory is not bounded — only wall-clock time is (F5).
Determinism
Same knowledge + same query ⇒ byte-identical solution set, every run.
Clauses are emitted in source order, solutions are sorted by a total order over
their bindings and proofs, and nothing is seeded randomly.
Examples and benchmarks
examples/07_it_security_compliance/ is a three-layer IT-security and compliance
knowledge base — CIS controls, a role hierarchy and environment/classification
policy, then generated user and resource data — in a small (~30 users) and a
large (~200 users) variant, so the same rules can be seen to scale unchanged.
python benchmarks/run_benchmarks.py # accuracy + latency, exits non-zero on a miss
python benchmarks/generate_large_rbac.py # regenerate the 1,000-user RBAC KBevals/evaluation.xml holds ten verified question/answer pairs for MCP
evaluation harnesses.
Architecture notes
The backend is a tactical choice, not an architectural dependency.
ir/, tools/ and the MCP surface never mention Prolog; only lowering/ does.
A Datalog or SMT backend would slot in behind the same LoweredProgram and
EngineResult types.
Reasoning runs as a subprocess rather than through FFI (pyswip/MQI) for
portability: no compiled extension, no persistent process, trivial to
containerize. The cost is one process launch per call, roughly 30-60 ms. If that
ever dominates the sub-second budget, engine/runner.py can be swapped for an
MQI-backed runner behind the same signature without touching anything else.
Development
pip install -e ".[dev]"
ruff check . && ruff format --check .
mypy --strict src
pytest # add -m "not requires_swipl" to skip backend testsLayout, conventions and the milestone plan are in SPEC.md,
CLAUDE.md and specs/.
License
MIT. See LICENSE.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityBmaintenanceMCP-Logic is a server that provides AI systems with automated reasoning capabilities, enabling logical theorem proving and model verification using Prover9/Mace4 through a clean MCP interface.Last updated45MIT
- Alicense-qualityCmaintenanceAn MCP server for the Pyke logic programming engine that enables LLMs to perform logical reasoning using knowledge bases with facts, rules, and queries. It supports session management, forward chaining inference, and bulk loading of programs in Logic-LLM format.Last updatedMIT
- Alicense-qualityBmaintenanceMCP server that gives LLMs access to formal verification via Z3 and SWI-Prolog, plus tree-sitter-based source code analysis. Translates natural language problems into formal logic using a template-based pipeline, verifies results with mathematical certainty, and analyzes call graphs for reachability, dead code, and impact analysis.Last updated82202Apache 2.0
- AlicenseAqualityDmaintenanceStructured reasoning MCP server that decomposes problems into atomic steps (premise, reasoning, hypothesis, verification, conclusion) with confidence scoring, live visualization, and approval feedback.Last updated365MIT
Related MCP Connectors
A paid remote MCP for ZeroLang, built to return verdicts, receipts, usage logs, and audit-ready JSON
MCP server for generating rough-draft project plans from natural-language prompts.
AI Reasoning Cache & Consensus Layer with 11 MCP tools via Streamable HTTP.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/snegi26/euclidMCPPaper'
If you have feedback or need assistance with the MCP directory API, please join our Discord server