Euclid-MCP
Euclid-MCP is a deterministic logical reasoning server that performs verifiable inference on a knowledge base and returns structured solutions with full proof trees.
Core capability: A reason tool that accepts facts, rules, and a query in a human-readable intermediate language (Euclid-IR), backed by a Prolog engine — no Prolog syntax required.
What you can do:
Define facts and rules in a declarative style (e.g.,
mortal($x) IF human($x)) supporting variables, implication (IF), conjunction (AND), negation (NOT), and arithmetic comparisons (>,>=,<,=<,=:=,=\=,is)Query the knowledge base with pattern variables (e.g.,
? ancestor(tom, $who)) or combine predicates in conjunctive queriesGet structured proof trees for every solution, explaining why each answer is correct
Control result scope via
max_solutions(default: 5) andmax_depth(default: 30)Offload complex multi-step reasoning from LLMs to a deterministic engine for explainability and verification
Practical use cases: Role-based access control (RBAC), compliance auditing, loan eligibility, IT security policy enforcement, dependency analysis, genealogy/recursive relationships, and business rule validation.
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-MCPProve that Socrates is mortal given all men are mortal."
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
MCP server for logical reasoning — turns facts into formal proofs.
Euclid-MCP is a hybrid cognitive architecture: a lightweight LLM describes the world in facts, and a deterministic engine performs the actual deduction. The LLM never needs to reason — it only needs to describe.
With Euclid-MCP, an 8B model can solve reasoning tasks that stump even 400B+ cloud models — because the engine handles deduction deterministically. Every answer comes with a proof tree, so you can trace why a conclusion holds, not just what it is. Use it to enforce RBAC policies, audit cloud compliance, validate loan eligibility rules, or reason over any domain where answers must be explainable and verifiable.
Euclid-MCP is written in Python and uses Euclid-IR, a human-readable intermediate language designed for both AI agents and humans. It uses SWI-Prolog as its primary inference engine — and, where SWI-Prolog is not available (e.g. minimal containers), a pure-Python native engine that interprets Euclid-IR directly (see docs/NATIVE_ENGINE.md).
It can be consumed in multiple ways: via MCP by AI agents (OpenCode, Claude, Cursor), via HTTP by tools and automation platforms (n8n, Zapier, Make), and via Python API for direct integration. Euclid-IR rules can also be used to augment RAG pipelines with deterministic policy enforcement.
How it works
┌──────────────┐ ┌──────────────────┐ ┌──────────────┐ ┌─────────────────┐
│ LLM/Agent │────▶│ Euclid-MCP │────▶│ Translator │────▶│ SWI-Prolog │
│ (MCP Client)│◀────│ (MCPServer) │◀────│ + Meta-IP │◀────│ (persistent) │
└──────────────┘ └──────────────────┘ └──────────────┘ └─────────────────┘Receive facts, rules, and a query in a simple intermediate language
Translate into Prolog with a meta-interpreter for proof tree capture
Execute via a persistent SWI-Prolog engine process (JSON-lines protocol on stdin/stdout; the workspace is reloaded per call, no process spawn overhead)
Return solutions + proof trees as structured JSON
Additional tools (explain, diagnose, what_if, check_kb) extend this core flow with natural-language explanations, analysis, scenario testing, and validation.
LLMs describe. Euclid MCP proves.
Knowledge Base
For small knowledge bases, facts and rules can be provided with each request.
A knowledge base can be loaded at server startup and reused across calls, so agents only pass the session-specific facts for the current query. This minimizes token usage, improves performance, and allows small LLMs to reason over large rule sets without reconstructing the entire knowledge base for every request.
Related MCP server: Pyke MCP Server
Intermediate Language
Even if currently Euclid-MCP uses a Prolog Engine, no Prolog syntax is required.
Euclid-IR (Intermediate Representation) is a declarative intermediate representation for logical inference.
Variables use $name, implication is IF, conjunction is AND.
Text format:
human(socrates)
mortal($x) IF human($x)
? mortal($who)YAML format:
facts:
- parent(tom, bob)
- parent(bob, ann)
- parent(tom, liz)
rules:
- ancestor($x, $y) IF parent($x, $y)
- ancestor($x, $y) IF parent($x, $z) AND ancestor($z, $y)
query: ancestor(tom, $who)Full language reference: docs/EUCLID_IR.md
Euclid-IR Syntax Reference
Element | Syntax | Example |
Facts |
|
|
Variables |
|
|
Implication |
|
|
Conjunction |
|
|
Negation |
|
|
Boolean literals |
|
|
Query |
|
|
String literals |
|
|
Multi-line rules | Body on next line |
|
Arithmetic Comparisons
Rules support arithmetic comparisons that are evaluated during deduction:
# Stale access: users who haven't logged in for 90+ days
stale_access($user) IF
user($user) AND last_login_days($user, $days) AND $days > 90
# Excessive permissions: more than 15 direct permissions
excessive_permissions($user, $count) IF
user($user) AND permission_count($user, $count) AND $count > 15
# Clearance check: user clearance >= resource classification
can_access($user, $resource) IF
user($user) AND resource($resource, _, _, _, _, $cls) AND
classification($cls, $cls_level, _) AND
user_clearance($user, $user_level) AND $user_level >= $cls_levelSupported operators: >, >=, <, <=, ==, is, !=
Multi-line Rules
Rules can span multiple lines for readability:
can_deploy($user, $env) IF
user($user) AND
has_role($user, $role) AND
deploy_requires_level($env, $min) AND
deploy_role_level($role, $level) AND
$level >= $min AND
user_has_permission($user, deploy_code)Conjunctions in Queries
Queries can combine multiple predicates:
? can_access_resource($who, $res) AND resource($res, _, _, _, _, secret)This returns solutions where both conditions are satisfied simultaneously.
Why External Inference?
The external inference gives several advantages:
deterministic
explainable
verifiable
inexpensive
replaceable backend
In the current implementation Euclid-MCP uses Prolog.
Prolog is a 50-year-old battle-tested logic engine. Using it as a "deduction coprocessor" lets small LLMs perform complex multi-step reasoning without needing larger, more expensive models. The intermediate language strips away Prolog's syntax quirks while keeping its logical core.
A specific benchmark demonstrate the difference: with 1 000+ facts, LLMs alone score 2/5 while Euclid-MCP scores 5/5 — and runs 7× faster while outputting 14× fewer tokens.
Tools
Euclid-MCP exposes 8 tools, each with a specific purpose:
Tool | Purpose |
| Main deduction — get solutions + proof trees |
| Readable, natural-language reasoning steps |
| Understand why a query succeeds or fails |
| Test modifications before applying them |
| Validate KB consistency before reasoning |
| Register a named KB under a |
| Remove a named KB from the registry |
| List registered named KBs (metadata) |
reason
Main tool for verifiable deterministic reasoning.
Parameter | Type | Default | Description |
|
| — | Facts & rules in text or YAML format |
|
| — | Reference a KB registered via |
|
| — | Session-specific facts appended to the |
|
| — | Override query (optional) |
|
|
| Max solutions to return |
|
|
| Max proof tree depth |
Returns ReasonResult with solutions[] — each containing variable bindings and a proof tree.
explain
Deterministic proof-tree → natural-language reasoning steps. No LLM involved: it
walks the proof tree of each solution and renders every step in plain language,
citing the rule ID (# RULE: <id>) when a rule has one. Use it to turn a proof
into an auditable, human-readable explanation.
Parameter | Type | Default | Description |
|
| — | Facts & rules in text or YAML format |
|
| — | Reference a KB registered via |
|
| — | Session-specific facts appended to the |
|
| — | Override query (optional) |
|
|
| Max solutions to return |
|
|
| Max proof tree depth |
Returns ExplanationResult with explanations[] — each containing variable
bindings, an ordered list of natural-language steps, and language-independent
structured_steps (typed kind/goal/rule_id/body, ready for localized
rendering in a UI).
diagnose
Query analysis — understand why a query succeeds or fails.
Parameter | Type | Default | Description |
|
| — | Facts & rules in text or YAML format |
|
| — | Reference a KB registered via |
|
| — | Session-specific facts appended to the |
|
| — | Query to diagnose |
|
|
| One of: |
|
|
| Max solutions to return |
|
|
| Max proof tree depth |
Modes:
why— explain why a query holds (or that it doesn't)why_not— explain why a query fails (missing facts/rules)what_needs— suggest what would make a false query true
Returns DiagnosisResult with holds, findings[], conclusion, and optionally proof.
what_if
Scenario analysis — apply modifications to a knowledge base and compare results.
Parameter | Type | Default | Description |
|
| — | Base facts & rules |
|
| — | Reference a KB registered via |
|
| — | Session-specific facts appended to the |
|
| — |
|
|
| — | Query to evaluate |
|
|
| Max solutions to return |
|
|
| Max proof tree depth |
Returns WhatIfResult with before_count, after_count, delta, solutions_before, solutions_after, conclusion.
check_kb
Knowledge base validator — check for consistency before running deduction.
Parameter | Type | Default | Description |
|
| — | Facts & rules in text or YAML format |
|
| — | Reference a KB registered via |
|
| — | Session-specific facts appended to the |
Returns KBCheckResult with valid, errors[], warnings[], facts_count, rules_count, predicates_count, and predicates[] — the predicate inventory (name → arities, facts, rules counts) that doubles as the contract for LLM extraction.
KB identity in results
Every tool result — ReasonResult, ExplanationResult, DiagnosisResult,
WhatIfResult, and KBCheckResult — carries two identity fields:
Field | Value |
| sha256 of the KB text payload (the exact source that was reasoned over) |
| the |
The fields are present on every return path, including error branches, so a
result can always be pinned to the exact KB it was computed from: anyone with
the .euclid text and Euclid-MCP can recompute the hash and verify it. This is
the foundation for KB versioning, signatures, and audit trails built on top of
the engine.
{
"query": "mortal($who)",
"solutions": [...],
"elapsed_ms": 12.4,
"content_hash": "a3f9c1e4b82d55f0…",
"version": "1.0"
}KB Preload
A knowledge base can be loaded once at server startup and reused across calls, so agents only pass the session-specific facts for the current query.
Preload a KB by file path, via the EUCLID_KB_PATH environment variable or a
--kb-path CLI flag:
# Environment variable
EUCLID_KB_PATH=/path/to/policies.euclid python3 -m euclid_mcp
# CLI flag (MCP stdio, console script, and HTTP API)
python3 -m euclid_mcp --kb-path /path/to/policies.euclid
python3 integrations/euclid_api.py --kb-path /path/to/policies.euclid --port 8080Behavior:
The file is validated with
check_kbat startup and the server fails fast with a clear message if the file is missing, unreadable, oversized, or invalid.knowledge/base_knowledgeonreason,explain,diagnose,what_if, andcheck_kbbecome optional: an explicit value always wins, an empty value falls back to the preloaded KB. With neither, tools return a clear "No knowledge provided" error.A markdown digest of the preloaded KB (fact/rule/predicate counts, predicate inventory, rules with their IDs) is appended to the server instructions, so agents can see what the KB covers without extra tool calls.
Backward compatible: passing knowledge explicitly behaves exactly as before.
Named KBs (kb_id + delta_knowledge)
A KB can also be registered once under a kb_id and then referenced on
every call without resending the text — the in-memory registry is per
server instance, so replicas re-register their KBs on startup (matching the
scale-out model of the HTTP API). Up to 32 KBs per instance; register_kb
overwrites an existing kb_id (update semantics for idempotency).
# Register once — validated with check_kb first
register_kb(kb_id="rbac-policy", knowledge="has_role(alice, admin) ...\n? $role ...")
# Reference it on every call
result = reason(kb_id="rbac-policy", query="can_deploy($user, prod)")
# Session-specific facts on top of the registered base (no re-registration):
result = reason(
kb_id="rbac-policy",
delta_knowledge="has_role(alice, dev)\nhas_env(dev, staging)",
query="can_deploy($user, staging)",
)register_kb(kb_id, knowledge)— validates thekb_id(allowlist[a-z0-9_-]{1,64}) and the KB (check_kb), then stores it. Returns the record:registered,kb_id,content_hash,version,facts,rules,predicates. Unknown ids are rejected; a full registry returns an error.unregister_kb(kb_id)— removes the KB; returnsremoved: true/false.list_kbs()— lists registered KBs (metadata only, no source text).
Resolution precedence on reason, explain, diagnose, what_if,
check_kb: explicit knowledge/base_knowledge wins → else kb_id
(unknown id → Unknown kb_id: <id>; delta_knowledge is concatenated to the
registered source) → else the EUCLID_KB_PATH preload → else a clear
"No knowledge provided" error. delta_knowledge without a kb_id is an
error. content_hash/version on a kb_id result are computed from the
effective source (base + delta), so a result can always be pinned to the
exact text reasoned over.
The HTTP API exposes the same flow as POST /register-kb,
POST /unregister-kb, and POST /list-kbs.
Installation
pip
# Prerequisite: Python ≥ 3.10
# SWI-Prolog (for better performances)
brew install swi-prolog
# Install
pip install euclid-mcpFrom source
git clone https://github.com/meob/Euclid-MCP
cd Euclid-MCP
python3 -m venv .venv && source .venv/bin/activate
pip install -e .Docker
No local SWI-Prolog installation needed — the image bundles everything.
# Build
docker build -t euclid-mcp .
# MCP stdio mode (for local MCP clients)
docker compose run --rm euclid-mcp
# HTTP API mode (for n8n, Zapier, remote access)
docker compose up euclid-api
# API available at http://localhost:8080See Docker in Integrations for full details.
Usage
Via MCP (OpenCode, Claude, etc.)
{
"mcpServers": {
"euclid-mcp": {
"command": "python3",
"args": ["-m", "euclid_mcp"],
"cwd": "/path/to/euclid-mcp"
}
}
}Via Python
from euclid_mcp.server import reason, explain, diagnose, what_if, check_kb
# Reasoning
result = reason(knowledge="""
human(socrates)
mortal($x) IF human($x)
? mortal($who)
""")
for sol in result.solutions:
print(sol.substitutions, sol.proof.type)
# Explanation — readable reasoning steps (cites rule IDs when present)
expl = explain(
knowledge="human(socrates)\nmortal($x) IF human($x) # RULE: BIO-001",
query="mortal($who)"
)
for e in expl.explanations:
print(e.substitutions, e.steps)
print(e.structured_steps) # typed, language-independent steps
# Diagnosis — why does a query fail?
diag = diagnose(
knowledge="human(socrates)\nmortal($x) IF human($x)",
query="mortal(plato)",
mode="why_not"
)
print(diag.conclusion)
# What-if — how does adding a fact change results?
scenario = what_if(
base_knowledge="human(socrates)\nmortal($x) IF human($x)",
modifications="+ human(plato)",
query="mortal($who)"
)
print(f"Before: {scenario.before_count}, After: {scenario.after_count}")
# KB validation
check = check_kb(knowledge="human(socrates)\nmortal($x) IF human($x)")
print(f"Valid: {check.valid}, Errors: {check.errors}")Via CLI
The euclid-cli command wraps the five reasoning tools (reason, explain,
diagnose, what_if, check_kb) for the terminal. It reads
the KB from a .euclid file (-f), inline (--knowledge), or falls back to
EUCLID_KB_PATH/preload, and selects the backend with --backend
(auto | prolog | native). Queries come from --query or from the ?
lines inside the KB file.
Run with no subcommand to open an interactive Euclid-IR REPL — type
facts, rules and ? query lines directly, like you would in swipl or
psql. The session knowledge base accumulates across queries.
$ euclid-cli
Euclid-MCP REPL — type facts and rules in Euclid-IR, then `? query`.
Commands: :help :check :kb :load :explain :diagnose :what-if :reset :quit
euclid > human(socrates)
euclid > mortal($x) IF human($x)
euclid > ? mortal($who)
Query: mortal($who)
Solution 1:
who: socrates
mortal(socrates) [rule]
human(socrates) [fact]
euclid > :what-if + human(plato)
Solutions: 1 -> 2 (delta: more)
euclid > :quitREPL meta-commands: :check, :kb, :load <file>, :explain [query],
:diagnose <query> [why|why_not|what_needs], :what-if <mods>, :reset,
:quit. Multi-line rules continue after IF/AND (prompt becomes ... >).
Piped input runs the same loop as a batch script without prompts:
printf 'human(socrates)\nmortal($x) IF human($x)\n? mortal($who)\n' | euclid-cli# Validate a knowledge base
euclid-cli check -f policies.euclid
# Run a deduction (query taken from the ? line in the file)
euclid-cli reason -f policies.euclid
# Explicit query + limits
euclid-cli reason -f policies.euclid --query "can_deploy($user, prod)" \
--max-solutions 10 --max-depth 40
# Inline KB (no file)
euclid-cli reason --knowledge "human(socrates)
mortal(\$x) IF human(\$x)
? mortal(\$who)"
# Readable reasoning steps
euclid-cli explain -f policies.euclid
# Why does a query fail?
euclid-cli diagnose -f policies.euclid --query "can_deploy(bob, prod)" \
--mode why_not
# What-if: how does adding a fact change the answer?
euclid-cli what-if -f policies.euclid \
--modifications "+ has_role(bob, deployer)" --query "can_deploy(bob, prod)"
# Force the pure-Python native engine (no SWI-Prolog)
euclid-cli --backend native reason -f policies.euclid
# Machine-readable output
euclid-cli reason -f policies.euclid --jsonExit codes: 0 on success, 1 when the tool reports an error (including an
invalid KB from check), 2 on usage errors.
Full CLI reference (all flags, backends, JSON output): docs/CLI.md
Example output
{
"query": "ancestor(tom, $who)",
"solutions": [
{
"substitutions": {"who": "bob"},
"proof": {
"type": "rule",
"goal": "ancestor(tom, bob)",
"body": "parent(tom, bob)",
"rule_id": "GEN-1",
"subproof": {"type": "fact", "goal": "parent(tom, bob)"}
}
},
{
"substitutions": {"who": "ann"},
"proof": {
"type": "rule",
"goal": "ancestor(tom, ann)",
"body": "parent(tom, bob), ancestor(bob, ann)",
"rule_id": "GEN-2",
"subproof": {
"type": "and",
"left": {"type": "fact", "goal": "parent(tom, bob)"},
"right": {
"type": "rule",
"goal": "ancestor(bob, ann)",
"body": "parent(bob, ann)",
"rule_id": "GEN-1",
"subproof": {"type": "fact", "goal": "parent(bob, ann)"}
}
}
}
}
]
}Rules can carry an audit-trail ID via a trailing # RULE: <id> comment; the ID
is surfaced as rule_id on the rule nodes of the proof tree, so a decision
can be cited ("this derives from rule GEN-2").
Diagnose output
{
"query": "mortal(plato)",
"mode": "why_not",
"holds": false,
"findings": [
{
"type": "satisfied",
"predicate": "human",
"detail": "Facts exist for 'human' (1 facts)"
}
],
"conclusion": "The query fails. Check rule conditions."
}What-if output
{
"query": "mortal($who)",
"modifications": "+ human(plato)",
"before_count": 1,
"after_count": 2,
"delta": "more",
"solutions_before": [{"substitutions": {"who": "socrates"}}],
"solutions_after": [
{"substitutions": {"who": "plato"}},
{"substitutions": {"who": "socrates"}}
],
"conclusion": "Solutions increased: 1 -> 2."
}Explain output
{
"query": "mortal($who)",
"explanations": [
{
"substitutions": {"who": "socrates"},
"steps": [
"mortal(socrates) is derived by rule BIO-001 from: human(socrates).",
"human(socrates) is asserted as a fact in the knowledge base."
]
}
]
}Use cases
Small LLM reasoning: Offload deduction from LLMs (3-8B) to a deterministic engine
Explainable decisions: Every answer comes with a proof tree which allows explanation, reasoning trace, and justification
Business rules: Validate logic chains (permissions, workflows, compliance)
Dependency analysis: Circular dependency detection, topological ordering
Education: Interactive logic tutoring with visible proof chains (see
docs/DIDACTIC.md, a step-by-step teaching guide built around theeuclid-cliREPL)Knowledge preload: Complex business rules can be loaded in Euclid instead of using a vector database
Query diagnosis: Understand why queries fail and what facts/rules are missing
Scenario analysis: Test "what-if" modifications before applying them to production
KB validation: Check knowledge bases for consistency before reasoning
Real-world examples
There are several examples provided as samples: Genealogy, RBAC, Classification, Loan Eligibility, Cluedo Detective, IT Security & Compliance, LLM vs Euclid-MCP, ... Most interesting ones are the IT Security & Compliance (with CIS, AWS, IAM Standards enforcement, Company Policies implementation, hundreds of Data Facts) and side-by-side LLM vs Euclid-MCP.
Examples full description: docs/EXAMPLES.md
Integrations
OpenCode
Euclid-MCP includes a pre-configured agent in .opencode.json:
{
"mcpServers": {
"euclid-mcp": {
"command": "python3",
"args": ["-m", "euclid_mcp"],
"cwd": "."
}
},
"agents": {
"reasoning-engine": {
"description": "Deterministic logic engine",
"instructions": "Write facts in Euclid IR, use the reason tool...",
"mcpServers": ["euclid-mcp"]
}
}
}n8n / Zapier / Make
Run the HTTP API:
python3 integrations/euclid_api.py --port 8080Endpoint | Method | Purpose |
| POST | Deduction with proof trees |
| POST | Natural-language reasoning steps |
| POST | Query failure analysis |
| POST | Scenario testing |
| POST | KB validation |
| POST | Register a named KB ( |
| POST | Remove a named KB |
| POST | List registered named KBs |
| GET | Health check (deep: pings the engine; 503 only when wedged) |
| GET | Prometheus metrics (open, read-only, never KB content) |
# Reasoning
curl -X POST http://localhost:8080/reason \
-H "Content-Type: application/json" \
-d '{"knowledge": "human(socrates)\nmortal($x) IF human($x)\n? mortal($who)"}'
# Explanation
curl -X POST http://localhost:8080/explain \
-H "Content-Type: application/json" \
-d '{"knowledge": "human(socrates)\nmortal($x) IF human($x)\n? mortal($who)"}'
# Diagnosis
curl -X POST http://localhost:8080/diagnose \
-H "Content-Type: application/json" \
-d '{"knowledge": "human(socrates)\nmortal($x) IF human($x)", "query": "mortal(plato)", "mode": "why_not"}'
# What-if
curl -X POST http://localhost:8080/what-if \
-H "Content-Type: application/json" \
-d '{"base_knowledge": "human(socrates)\nmortal($x) IF human($x)", "modifications": "+ human(plato)", "query": "mortal($who)"}'
# KB validation
curl -X POST http://localhost:8080/check-kb \
-H "Content-Type: application/json" \
-d '{"knowledge": "human(socrates)\nmortal($x) IF human($x)"}'
# Register a named KB once, then reference it by kb_id
curl -X POST http://localhost:8080/register-kb \
-H "Content-Type: application/json" \
-d '{"kb_id": "rbac", "knowledge": "human(socrates)\nmortal($x) IF human($x)"}'
curl -X POST http://localhost:8080/reason \
-H "Content-Type: application/json" \
-d '{"kb_id": "rbac", "delta_knowledge": "human(plato)", "query": "mortal($who)"}'
curl -X POST http://localhost:8080/list-kbs \
-H "Content-Type: application/json" \
-d '{}'
curl -X POST http://localhost:8080/unregister-kb \
-H "Content-Type: application/json" \
-d '{"kb_id": "rbac"}'Docker
The Docker image bundles SWI-Prolog + Python, so no local prerequisites are needed.
Base image: swipl:stable (Debian Bookworm).
Two modes via docker-compose:
# MCP stdio — pipe to a local MCP client
docker compose run --rm euclid-mcp
# HTTP API — expose REST endpoints on port 8080
docker compose up euclid-apiStandalone usage:
# Build
docker build -t euclid-mcp .
# Run HTTP API
docker run --rm -p 8080:8080 euclid-mcp \
python3 integrations/euclid_api.py --port 8080
# Run MCP stdio (interactive)
docker run --rm -i euclid-mcp
# Quick test — reason directly from CLI
docker run --rm euclid-mcp python3 -c "
from euclid_mcp.server import reason
r = reason(knowledge='human(socrates)\nmortal(\$x) IF human(\$x)\n? mortal(\$who)')
print(r.solutions[0].substitutions)
"Docker image size: ~370 MB (SWI-Prolog + Python 3.11 + dependencies).
Native-only (slim): a smaller image with the pure-Python Euclid-IR engine
and no SWI-Prolog (EUCLID_BACKEND=native). Best for containers with limited
space or as the default for small knowledge bases.
# Build
docker build -f Dockerfile.native -t euclid-mcp-native .
# Run MCP stdio (interactive)
docker compose run --rm euclid-mcp-native
# Run HTTP API
docker run --rm -p 8080:8080 euclid-mcp-native \
python3 integrations/euclid_api.py --port 8080
# Quick test — reason directly from CLI
docker run --rm euclid-mcp-native python3 -c "
from euclid_mcp.server import reason
r = reason(knowledge='human(socrates)\nmortal(\$x) IF human(\$x)\n? mortal(\$who)')
print(r.solutions[0].substitutions)
"Base image: python:3.12-slim.
CLI pipeline
echo '{"knowledge": "red(apple)\\n? red($x)"}' | python3 integrations/euclid_cli.pySee integrations/README.md for full details.
Scalability
Euclid-MCP engine is persistent: a single long-lived SWI-Prolog process per server instance, reloaded per request over a JSON-lines pipe instead of booting Prolog for every call. A single instance handles one request at a time. Requests stay stateless: each one brings its own knowledge base (or uses the preloaded one), so instances share nothing.
This makes Euclid-MCP horizontally scalable:
HTTP API — run any number of instances behind a load balancer (nginx, a Kubernetes Service, …). No session affinity needed: any instance can serve any request.
MCP stdio — each MCP client spawns its own instance by design, giving natural isolation and parallelism across clients.
Resource footprint — one
swiplprocess per instance (~tens of MB) instead of one short-lived process per request, so a single instance serves many requests cheaply.
Reference production architecture — load balancing, resource limits, security
hardening, and monitoring for a replica battery behind HAProxy:
docs/PRODUCTION.md.
Development
Requirements: Python ≥ 3.10, SWI-Prolog.
# Install in editable mode with dev dependencies
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
# Lint
ruff check .
# Type check
mypy euclid_mcp integrations
# Tests with coverage
pytest --cov=euclid_mcp --cov=integrationsThe CI workflow (.github/workflows/ci.yml) runs these
same checks on push and pull request, across Python 3.10–3.14.
Logging & tracing
Every tool call is logged with its name, elapsed time, and outcome. Enable
structured logs by setting EUCLID_LOG_LEVEL (one of DEBUG, INFO,
WARNING, ERROR, CRITICAL) — e.g. EUCLID_LOG_LEVEL=INFO. Without the
variable, only warnings and errors are emitted.
The HTTP API also supports request tracing: send an X-Request-Id header and
it is echoed back on the response and included in the access logs.
Monitoring & metrics
The HTTP API exposes Prometheus metrics on GET /metrics (open, read-only,
never carries KB content): per-tool call/error counters and latency
histograms, engine requests/restarts/timeouts, HTTP traffic, solutions
returned, auth failures and process uptime — always on, zero dependencies
(euclid_mcp/metrics.py). GET /health is a deep check that pings the
engine and reports its workspace stats (503 only when a wedged engine exists).
curl -s localhost:8080/metricsFor a full stack (Prometheus + Grafana + cAdvisor, dashboard and alert rules
included): monitoring/README.md.
What is Prolog?
Prolog (from PROgrammation en LOGique) is a declarative logic programming language: instead of telling the machine how to compute an answer, you state facts and rules and let it find what follows from them, using unification and backtracking. Born in the early 1970s, it remains one of the most battle-tested tools for symbolic reasoning.

Euclid-MCP uses SWI-Prolog as its inference engine. SWI-Prolog is a mature open-source implementation — continuously developed and freely available since 1987 — widely used in industry, academia, and research. You write your rules in Euclid-IR; the translator compiles them to Prolog, and SWI-Prolog performs the deduction and produces the proof trees that make every Euclid-MCP answer verifiable.
How is Euclid?
Euclid was an ancient Greek mathematician. Living and teaching in Alexandria, he built the foundations of geometry and number theory using rigorous logical proofs.
Euclid-MCP is not:
an LLM
a knowledge base
a vector database
an agent framework
a planner
Euclid-MCP is a deterministic inference engine that can be used by any of them.
Euclid-MCP allows deterministic and explainable replies from small LLMs on Edge hardware too.
License
Apache 2.0
Available Tools
8 toolscheck_kbC
Check a knowledge base for consistency: syntax errors, undefined predicates, circular rules, duplicates.
| Name | Required | Description | Default |
|---|---|---|---|
| kb_id | No | ||
| knowledge | No | ||
| delta_knowledge | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | |
| valid | No | |
| errors | No | |
| version | No | |
| warnings | No | |
| elapsed_ms | No | |
| predicates | No | |
| facts_count | No | |
| rules_count | No | |
| content_hash | No | |
| predicates_count | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It mentions the checks performed but does not disclose whether the tool modifies anything (likely read-only), what happens on failure, or whether it requires an existing KB vs. inline knowledge. It does not contradict annotations (none exist), but it is thin on behavioral details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence, concise and front-loaded with the main purpose. It lists specific checks efficiently. However, it could be slightly more structured (e.g., separating purpose from usage), but it is not verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 3 parameters with 0% schema coverage, no annotations, and an output schema (not described), the description is incomplete. It does not explain the parameters, the output format, or the context of use (e.g., when to use delta_knowledge). The description is adequate for a simple check but lacks essential details for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description does not explain the three parameters (kb_id, knowledge, delta_knowledge). It does not clarify how they relate (e.g., whether kb_id is required, or how knowledge and delta_knowledge are used). The description adds no meaning beyond the schema's property names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: checking a knowledge base for consistency, listing specific checks (syntax errors, undefined predicates, circular rules, duplicates). It distinguishes from siblings like diagnose or explain by focusing on consistency checks, though it doesn't explicitly name alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for validating a knowledge base but does not specify when to use this over siblings like diagnose or what_if. It lacks explicit guidance on when to use this tool versus alternatives, and does not mention prerequisites or context (e.g., whether kb_id or knowledge must be provided).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
diagnoseC
Diagnose why a query succeeds or fails. Modes: 'why' (explain success), 'why_not' (explain failure), 'what_needs' (what would make it succeed)
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | why | |
| kb_id | No | ||
| query | No | ||
| knowledge | No | ||
| max_depth | No | ||
| max_solutions | No | ||
| delta_knowledge | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | No | |
| error | No | |
| holds | No | |
| proof | No | |
| query | No | |
| version | No | |
| findings | No | |
| solutions | No | |
| conclusion | No | |
| elapsed_ms | No | |
| content_hash | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description must disclose behavioral aspects itself. It only mentions the diagnostic purpose and modes, but omits any side effects, resource implications, authentication needs, or what the output contains. This is a significant gap for a diagnostic tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely short (one sentence), but it omits critical parameter explanations. While concise, it under-specifies the tool's usage, making it ineffective. The structure lacks a clear breakdown of modes and parameters, so it does not serve as a useful guide.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 7 parameters, no annotations, and no schema descriptions, the description is grossly incomplete. It fails to explain what each parameter does, what the output contains, or how the tool behaves in different contexts. The presence of an output schema does not compensate for missing parameter semantics.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 0% description coverage Dominic, and the description does not explain any of the 7 parameters except 'mode' implicitly. Parameters like kb_id, query, knowledge, max_depth, max_solutions, and delta_knowledge are left undefined, making it impossible to use the tool correctly without external knowledge.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's action ('Diagnose') and resource ('why a query succeeds or fails'), and lists specific modes that further clarify purpose. However, it does not explicitly differentiate from sibling tools like 'explain' or 'what_if', so it loses some points on distinction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description lists modes but provides no explicit guidance on when to use this tool versus alternatives like 'explain' or 'what_if'. It does not state prerequisites, typical scenarios, or exclusions, leaving the agent without clear selection criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
explainA
Explain, in natural language, how a query is proven: walk the proof tree of each solution and return readable reasoning steps. Rule IDs are cited when present.
| Name | Required | Description | Default |
|---|---|---|---|
| kb_id | No | ||
| query | No | ||
| knowledge | No | ||
| max_depth | No | ||
| max_solutions | No | ||
| delta_knowledge | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | |
| query | No | |
| version | No | |
| elapsed_ms | No | |
| content_hash | No | |
| explanations | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations available, the description carries the full burden. It accurately discloses the core behavior—walking proof trees, producing natural-language steps, and citing rule IDs when present. It does not contradict any annotations (there are none). Missing details include side effects (likely none, but unstated) and behavior when there are no solutions, but the description gives a strong sense of what happens internally.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the verb and purpose, and every phrase adds value. There is no redundancy or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given there are 6 parameters, no annotations, and an output schema exists, the description is adequate for understanding the tool's primary purpose and output, but incomplete regarding parameter roles and usage context (e.g., how kb_id relates to knowledge, when to vary max_depth vs. max_solutions). The output schema covers return values, so that is not a gap, but the parameter and selection guidance are thin.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for parameter meaning. It adds context for 'query', implicitly for 'max_depth' and 'max_solutions' via 'walk the proof tree of each solution', but leaves 'kb_id', 'knowledge', and especially 'delta_knowledge' undefined. The description does not explain the relationship between these parameters or how they affect the explanation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Explain'), names the resource ('how a query is proven'), and specifies the method and output ('walk the proof tree of each solution and return readable reasoning steps'). It clearly distinguishes this from siblings like 'reason' (likely performs reasoning) and 'diagnose' (likely investigates problems) by focusing on natural-language explanation of proofs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly implies the use case: when a user needs a human-readable explanation or proof trace for a query. However, it does not explicitly name alternatives or state when not to use this tool (e.g., when one actually wants to run a query vs. understand its derivation).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_kbsA
List the registered named knowledge bases (metadata only: kb_id, content_hash, version, counts).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must fully disclose behavior. It adds 'metadata only,' which clarifies the return type (no content), but it does not mention side effects, permissions, or other behavioral aspects. It's adequate but not comprehensive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence that conveys all essential information with zero fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list operation with no parameters and no output schema, the description adequately covers what it does and what it returns (metadata fields). It doesn't need more, though it could mention that it returns all KBs or ordering, but that's minor.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters (0 params), so per rubric the baseline is 4. The description provides no parameter-specific details, but none are needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('List') and the resource ('registered named knowledge bases'), and specifies the scope (metadata only), which distinguishes it from siblings like register_kb and unregister_kb.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies a read-only listing operation, which contrasts with mutating siblings like register_kb and unregister_kb. However, it doesn't explicitly state when to use it vs alternatives or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reasonC
Perform logical deduction on a knowledge base and return solutions with proof trees for each result
| Name | Required | Description | Default |
|---|---|---|---|
| kb_id | No | ||
| query | No | ||
| knowledge | No | ||
| max_depth | No | ||
| max_solutions | No | ||
| delta_knowledge | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | |
| query | No | |
| version | No | |
| solutions | No | |
| elapsed_ms | No | |
| content_hash | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of disclosing behavioral traits. It only mentions that it returns proof trees but does not indicate side effects, performance costs, or whether it modifies the knowledge base. The description is too sparse to inform the agent about potential impacts.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no redundancy. It efficiently conveys the main action and result format. However, its brevity veers toward under-specification for a complex tool, though this is more a completeness concern than conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has six parameters, no annotations, and an output schema, the description is far from complete. It does not mention what inputs are required, how the reasoning process works, or any constraints. Even though an output schema exists, the description leaves the tool's usage and behavior largely unexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has zero description coverage, and the description does not explain any of the six parameters (kb_id, query, knowledge, max_depth, max_solutions, delta_knowledge). Without any parameter explanation, the agent cannot understand how to construct a valid call, so the description fails to compensate for the lack of schema details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: performing logical deduction on a knowledge base and returning solutions with proof trees. This is specific and distinct from sibling tools like explain, diagnose, and what_if, which likely cover other analytical tasks.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives, nor any prerequisites or exclusions. It does not mention how this differs from diagnose or what_if in terms of use cases, leaving the agent without context for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
register_kbA
Register a named knowledge base under a kb_id so later calls can reference it instead of resending the KB text. Overwrites an existing kb_id. The KB is validated with check_kb first.
| Name | Required | Description | Default |
|---|---|---|---|
| kb_id | Yes | ||
| knowledge | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral disclosure burden. It honestly discloses that registration 'Overwrites an existing kb_id' and that the KB is validated with check_kb first. However, it does not mention failure modes, return values, or permissions, leaving some behavioral gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is exactly two sentences, both dense with information: the purpose/reference benefit and the overwrite/validation behavior. No filler or redundancy, and the most important verb and resource appear first.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a simple two-parameter schema and no output schema, the description covers the essential aspects: naming/registering, overwriting, and validation. It lacks details on error handling if check_kb fails, but for a low-complexity registration tool, it is sufficiently complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It clarifies that kb_id is a reference name and knowledge is the KB text, mapping to the two schema properties. It does not provide format, length, or additional constraints, but it does add meaning beyond the bare titles.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Register a named knowledge base under a kb_id' with the specific benefit of allowing later references instead of resending KB text. It also distinguishes itself from siblings by noting overwrite behavior and the relationship to check_kb, differentiating it from unregister_kb, list_kbs, and check_kb.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit usage context: 'so later calls can reference it instead of resending the KB text' and mentions the prerequisite validation via check_kb first. It does not explicitly name alternative tools or state when not to use, but the purpose and precondition provide clear guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unregister_kbA
Remove a named knowledge base from the registry. Returns 'removed': false when the kb_id is not registered.
| Name | Required | Description | Default |
|---|---|---|---|
| kb_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It does disclose the behavior when the kb_id is not registered (returns 'removed': false), which is useful. However, it omits details like whether removal is permanent, requires permissions, or has irreversible effects beyond the name.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence, immediately states the purpose, and includes the key return behavior. There is no wasted wording or redundant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter removal tool, the description adequately covers the core action and a key edge case (missing kb). It could mention side effects or prerequisites, but given no output schema and simple behavior, it is reasonably complete for the sibling context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It adds minimal semantics by calling it a 'named knowledge base', implying kb_id is a name, but it doesn't explain the format, constraints, or how to find valid values. The description offers little beyond the raw schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Remove') and the resource ('named knowledge base from the registry'). It distinguishes from siblings like register_kb, list_kbs, and check_kb by specifying the unregister action.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description offers no guidance on when to use this tool versus alternatives, such as when to call unregister_kb instead of check_kb or register_kb. No context or exclusions are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
what_ifC
What-if analysis: apply modifications to a knowledge base and see how they affect query results. Use + prefix to add facts, - prefix to remove facts.
| Name | Required | Description | Default |
|---|---|---|---|
| kb_id | No | ||
| query | No | ||
| max_depth | No | ||
| max_solutions | No | ||
| modifications | No | ||
| base_knowledge | No | ||
| delta_knowledge | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| delta | No | |
| error | No | |
| query | No | |
| version | No | |
| conclusion | No | |
| elapsed_ms | No | |
| after_count | No | |
| before_count | No | |
| content_hash | No | |
| modifications | No | |
| solutions_after | No | |
| solutions_before | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden for behavioral disclosure. It explains the +/− syntax but does not say whether changes are permanent, what happens to the KB, or what output to expect beyond 'see how they affect query results.'
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded, with the core purpose in the first phrase and useful syntax guidance in the second sentence. It contains no filler, though it could have been longer to cover more behavioral detail without harming structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 7 parameters, no annotations, and minimal schema descriptions, the description is too sparse for reliable invocation. It gives one hint about modifications but leaves the roles of other parameters and the non-obvious semantics of the tool largely unexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 7 parameters with 0% description coverage, and the description only clarifies the modifications parameter via the +/− syntax. Parameters like base_knowledge, delta_knowledge, max_depth, and max_solutions receive no semantic explanation beyond their names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: applying modifications to a knowledge base to see effects on query results. It is distinct enough from siblings like reason and explain, though it does not explicitly name or contrast them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'What-if analysis' implies hypothetical exploration, and the +/− prefix instructions signal how to use it. However, there is no explicit guidance on when to use this tool versus siblings, nor when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Several tools overlap in purpose: reason, explain, and diagnose all deal with explaining or producing query outcomes, making it hard to know which to call. diagnose even includes a 'why' mode that duplicates explain. The KB management tools are clear, but the reasoning tools blur together.
Naming is mixed: some tools use bare verbs (reason, explain, diagnose), some use snake_case verb_noun (register_kb, unregister_kb, list_kbs, check_kb), and what_if deviates entirely from the pattern. The style is inconsistent across the tool set.
Eight tools is a well-scoped size for a knowledge-base reasoning server. Each tool contributes to either KB lifecycle management or query/reasoning workflows without feeling padded or sparse.
The KB lifecycle is covered well: register, unregister, list, and check. Reasoning coverage includes query, explanation, diagnosis, and what-if analysis. Minor gap: there is no way to retrieve the actual content of a registered KB, only metadata, which agents may need for inspection.
Maintenance
Related MCP Connectors
MCP server for building and testing AI agents with multi-model experimentation and insights.
MCP server unifying ERPs, CRMs, APIs and knowledge base for Claude, ChatGPT and Gemini.
MCP server for generating rough-draft project plans from natural-language prompts.
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceMCP-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.46MIT
- AlicenseNot gradedqualityCmaintenanceAn 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.MIT
- AlicenseNot gradedqualityBmaintenanceMCP 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.79210Apache 2.0
- FlicenseAqualityCmaintenanceMCP server wrapping SWI-Prolog for symbolic reasoning, enabling coding agents to assert facts and query rules deterministically.77
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/Euclid-BG/Euclid-MCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server