mcpField
E
Euclid-MCP

Euclid-MCP

本地服务
github.com/meobAI 与智能体77 周前更新

关于 Euclid-MCP

Euclid-MCP 是面向需要可验证推导的 Agent 和工具的逻辑推理服务。它使用确定性推理引擎处理 Euclid-IR 中的事实与规则,并返回带证明树的解。

主要功能

  1. 01根据事实和规则进行确定性推导
  2. 02支持 Euclid-IR 文本和 YAML 输入
  3. 03返回解及证明树
  4. 04解释并诊断查询结果
  5. 05测试假设情景
  6. 06验证和注册知识库

适用场景

  1. 01检查基于角色的访问规则
  2. 02审计合规条件
  3. 03测试贷款资格规则
  4. 04追溯逻辑结论成立的原因

MCP 相关

Euclid-MCP 向 MCP 客户端提供八种推理与知识库工具,涵盖演绎、解释、诊断、情景测试、验证和知识库管理。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"meob-euclid": {
"command": "uvx",
"args": [
"euclid-mcp"
]
}
}
}
启动命令uvx euclid-mcp

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypieuclid-mcp0.4.5

工具

8

收录的工具列表 · 更新于 2 周前

参数类型必填说明
kb_idany否
queryany否
knowledgeany否
max_depthinteger否
max_solutionsinteger否
delta_knowledgeany否

详细介绍

Euclid-MCP

Euclid-MCP MCP server PyPI version Python versions License CI Coverage

用于逻辑推理的 MCP 服务——将事实转化为形式化证明。

Euclid-MCP 是一种混合认知架构:轻量级大模型用事实描述世界,确定性引擎负责实际推演。大模型无需推理,只需进行描述。

借助 Euclid-MCP,8B 模型可以解决连 400B+ 云端模型都难以应对的推理任务,因为引擎会以确定性方式处理推演。每个答案都附带证明树,因此你可以追溯结论成立的原因,而不仅仅是结论是什么。你可以用它执行 RBAC 策略、审计云合规性、验证贷款资格规则,或推理任何要求答案可解释且可验证的领域。

Euclid-MCP 使用 Python 编写,并采用 Euclid-IR:一种面向 AI Agent 和人类设计的易读中间语言。它使用 SWI-Prolog 作为主要推理引擎;如果无法使用 SWI-Prolog(例如在精简容器中),则使用纯 Python 编写的 native engine,直接解释 Euclid-IR(参见 docs/NATIVE_ENGINE.md)。 它支持多种使用方式:AI Agent(OpenCode、Claude、Cursor)可通过 MCP 使用;工具和自动化平台(n8n、Zapier、Make)可通过 HTTP 使用;也可通过 Python API 直接集成。Euclid-IR 规则还可用于为 RAG 流水线提供增强,实现确定性的策略执行。

工作原理

┌──────────────┐     ┌──────────────────┐     ┌──────────────┐     ┌─────────────────┐
│  LLM/Agent   │────▶│  Euclid-MCP      │────▶│  Translator  │────▶│  SWI-Prolog     │
│  (MCP Client)│◀────│  (MCPServer)     │◀────│  + Meta-IP   │◀────│  (persistent)   │
└──────────────┘     └──────────────────┘     └──────────────┘     └─────────────────┘
  1. 使用简单的中间语言接收事实、规则和查询
  2. 转换为 Prolog,并使用元解释器捕获证明树
  3. 通过持久运行的 SWI-Prolog 引擎进程执行(使用 stdin/stdout 上的 JSON 行协议;每次调用都会重新加载工作区,无需承担启动进程的开销)
  4. 将解答和证明树作为结构化 JSON 返回

其他工具(explain、diagnose、what_if、check_kb)在此核心流程基础上提供自然语言解释、分析、场景测试和验证功能。

大模型负责描述。Euclid MCP 负责证明。

知识库

对于较小的知识库,可以在每次请求中提供事实和规则。

知识库可以在服务启动时加载,并在后续调用中重复使用,因此 Agent 只需传递当前查询所需的会话专属事实。 这可以最大限度地减少 token 使用量、提升性能,还能让小型大模型基于大型规则集进行推理,而无需在每次请求时重建整个知识库。

中间语言

尽管 Euclid-MCP 当前使用 Prolog 引擎,但无需使用 Prolog 语法。
Euclid-IR(中间表示)是一种用于逻辑推理的声明式中间表示。 变量使用 $name,蕴含使用 IF,合取使用 AND。

文本格式:

human(socrates)
mortal($x) IF human($x)

? mortal($who)

YAML 格式:

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)

完整语言参考:docs/EUCLID_IR.md

Euclid-IR 语法参考
元素语法示例
事实predicate(args)parent(tom, bob)
变量$name(小写)$who、$x、$count
蕴含IFmortal($x) IF human($x)
合取ANDp($x) AND q($x)
析取ORcan($u) IF is_admin($u) OR has_role($u, auditor)
分组(...)(is_admin($u) OR support($u)) AND active($u)
否定NOTNOT active($user)
布尔字面量规则体中的 true / falsemerchant($m) IF false
查询? predicate? ancestor(tom, $who)
字符串字面量"..." 或 '...'"[email protected]"
多行规则规则体位于下一行rule($x) IF\n body($x)
算术比较

规则支持在推导过程中求值的算术比较:

# 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_level

支持的运算符: >、>=、<、<=、==、is、!=

多行规则

规则可以跨多行编写,以提高可读性:

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)
查询中的合取

查询可以组合多个谓词:

? can_access_resource($who, $res) AND resource($res, _, _, _, _, secret)

当两个条件同时满足时,此查询会返回相应的解。

析取(OR)

规则体可以使用 OR 表示多个备选项。解析器会在加载时将每个备选项展开为独立的 Horn 子句,因此求解器始终只处理纯 Horn 子句:

# A user can deploy when they are an admin, OR a dev on an approved env
can_deploy($u, $env) IF
    is_admin($u) OR
    (has_role($u, dev) AND env_approved($u, $env))

AND 的优先级高于 OR;带括号的分组会以分配方式展开。 NOT 仅作用于单个目标。每个展开分支都会保留 # RULE: <id>,因此可以根据源规则审计证明。

为什么使用外部推理?

外部推理有多项优势:

  • 确定性
  • 可解释
  • 可验证
  • 成本低
  • 后端可替换

当前实现中,Euclid-MCP 使用 Prolog。
Prolog 是一款历经 50 年实战检验的逻辑引擎。将它用作“推导协处理器”,小型大模型便能执行复杂的多步推理,而无需使用更大、成本更高的模型。中间语言去除了 Prolog 的语法细节,同时保留其逻辑核心。

一项特定的基准测试展示了这种差异:在 1 000+ 个事实的情况下,大模型单独运行得分为 2/5,而 Euclid-MCP 得分为 5/5;同时速度快 7 倍,输出的 token 少 14 倍。

工具

Euclid-MCP 提供 8 个工具,各有特定用途:

工具用途
reason主要推导工具——获取解和证明树
explain以自然语言呈现的推理步骤
diagnose了解查询成功或失败的原因
what_if在应用修改前测试修改效果
check_kb推理前验证 KB 的一致性
register_kb在 kb_id 下注册一个命名 KB
unregister_kb从注册表中移除一个命名 KB
list_kbs列出已注册命名 KB 的元数据
reason

用于可验证、确定性推理的主要工具。

参数类型默认值描述
knowledgestring?—文本或 YAML 格式的事实和规则
kb_idstring?—引用通过 register_kb 注册的 KB
delta_knowledgestring?—会话专属事实,追加到 kb_id 的基础知识中
querystring?—覆盖查询(可选)
max_solutionsint5返回的最大解数
max_depthint30证明树的最大深度

返回值为 ReasonResult,其中包含 solutions[];每个解都包含变量绑定和证明树。

explain

将确定性证明树转换为自然语言推理步骤。不涉及大模型:它会遍历每个解的证明树,以通俗语言呈现每一步,并在规则有 ID 时引用规则 ID(# RULE: <id>)。可用于将证明转换为可审计、易于阅读的解释。

参数类型默认值描述
knowledgestring?—文本或 YAML 格式的事实和规则
kb_idstring?—引用通过 register_kb 注册的知识库
delta_knowledgestring?—追加到 kb_id 基础知识库的会话专属事实
querystring?—覆盖查询(可选)
max_solutionsint5返回的最大解数
max_depthint30最大证明树深度

返回 ExplanationResult,包含 explanations[]。每项都包含变量绑定、有序的自然语言 steps 列表,以及与语言无关的 structured_steps(类型化的 kind/goal/rule_id/body,可用于在 UI 中进行本地化呈现)。

diagnose

查询分析——了解查询为何成功或失败。

参数类型默认值描述
knowledgestring?—文本或 YAML 格式的事实和规则
kb_idstring?—引用通过 register_kb 注册的知识库
delta_knowledgestring?—追加到 kb_id 基础知识库的会话专属事实
querystring—要诊断的查询
modestringwhy可选值:why、why_not、what_needs
max_solutionsint5返回的最大解数
max_depthint30最大证明树深度

模式:

  • why — 解释查询为何成立(或不成立)
  • why_not — 解释查询为何失败(缺少事实或规则)
  • what_needs — 建议如何让错误的查询成立

返回 DiagnosisResult,包含 holds、findings[]、conclusion,以及可选的 proof。

what_if

场景分析——对知识库应用修改并比较结果。

参数类型默认值描述
base_knowledgestring?—基础事实和规则
kb_idstring?—引用通过 register_kb 注册的知识库
delta_knowledgestring?—追加到 kb_id 基础知识库的会话专属事实
modificationsstring—添加 + fact(...),移除 - fact(...)
querystring—要评估的查询
max_solutionsint5返回的最大解数
max_depthint30最大证明树深度

返回 WhatIfResult,包含 before_count、after_count、delta、solutions_before、solutions_after、conclusion。

check_kb

知识库验证器——在运行推理前检查一致性。

参数类型默认值描述
knowledgestring?—文本或 YAML 格式的事实和规则
kb_idstring?—引用通过 register_kb 注册的知识库
delta_knowledgestring?—追加到 kb_id 基础知识库的会话专属事实

返回 KBCheckResult,包含 valid、errors[]、warnings[]、facts_count、rules_count、predicates_count 和 predicates[]。其中 predicates[] 是谓词清单(名称 → 元数、事实数、规则数),也可作为大模型提取信息时的约定。

结果中的 KB 标识

每个工具结果——ReasonResult、ExplanationResult、DiagnosisResult、 WhatIfResult 和 KBCheckResult——都包含两个标识字段:

字段值
content_hashKB 文本载荷的 sha256(用于推理的确切来源)
versionKB 的 @version 指令;如果不存在,则为 null

这些字段存在于每条返回路径中,包括错误分支,因此结果始终可以追溯到其所依据的确切 KB:任何拥有 .euclid 文本和 Euclid-MCP 的人都可以重新计算哈希并验证。这是基于引擎构建 KB 版本管理、签名和审计跟踪的基础。

{
  "query": "mortal($who)",
  "solutions": [...],
  "elapsed_ms": 12.4,
  "content_hash": "a3f9c1e4b82d55f0…",
  "version": "1.0"
}
KB 预加载

知识库可以在服务器启动时加载一次,并在多次调用间重复使用,这样 Agent 只需传入当前查询特有的会话事实。

可通过 EUCLID_KB_PATH 环境变量或 --kb-path CLI 标志,按文件路径预加载 KB:

# 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 8080

行为:

  • 文件会在启动时通过 check_kb 验证;如果文件缺失、无法读取、超出大小限制或无效,服务器会立即失败并给出明确消息。
  • reason、explain、diagnose、what_if 和 check_kb 上的 knowledge/base_knowledge 变为可选:显式传入的值始终优先;传入空值时会回退到预加载的 KB。如果两者都没有,工具会返回明确的“No knowledge provided”错误。
  • 预加载 KB 的 Markdown 摘要(事实、规则和谓词的数量,谓词清单,以及包含 ID 的规则)会附加到服务器指令中,因此 Agent 无需额外调用工具即可了解 KB 覆盖的内容。

向后兼容:显式传入 knowledge 的行为与之前完全相同。

命名 KB(kb_id + delta_knowledge)

KB 也可以通过 kb_id 注册一次,之后每次调用都可以引用它,而无需重新发送文本——内存中的注册表按服务器实例隔离,因此各副本会在启动时重新注册自己的 KB(与 HTTP API 的横向扩展模型一致)。每个实例最多支持 32 个 KB;register_kb 会覆盖已有的 kb_id(用于幂等更新)。

# 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) — 验证 kb_id(允许列表为 [a-z0-9_-]{1,64})和 KB(check_kb),然后存储。返回记录:registered、kb_id、content_hash、version、facts、rules、predicates。未知 ID 会被拒绝;注册表已满时会返回错误。
  • unregister_kb(kb_id) — 移除 KB;返回 removed: true/false。
  • list_kbs() — 列出已注册的 KB(仅元数据,不含源文本)。

在 reason、explain、diagnose、what_if、check_kb 上的解析优先级为:显式传入的 knowledge/base_knowledge 优先 → 否则使用 kb_id(未知 ID → Unknown kb_id: <id>;delta_knowledge 会与已注册的源文本拼接)→ 否则使用 EUCLID_KB_PATH 预加载内容 → 否则返回明确的“No knowledge provided”错误。不带 kb_id 使用 delta_knowledge 会报错。kb_id 结果中的 content_hash/version 根据生效后的源文本(基础内容 + 增量内容)计算,因此结果始终可以追溯到实际用于推理的确切文本。

HTTP API 通过 POST /register-kb、POST /unregister-kb 和 POST /list-kbs 提供相同的流程。

安装

pip
# Prerequisite: Python ≥ 3.10

# SWI-Prolog (for better performances)
brew install swi-prolog

# Install
pip install euclid-mcp
从源码安装
git clone https://github.com/Euclid-BG/Euclid-MCP
cd Euclid-MCP
python3 -m venv .venv && source .venv/bin/activate
pip install -e .
Docker

无需在本地安装 SWI-Prolog——镜像已包含所有内容。

# 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:8080

完整详情请参阅集成中的 Docker。

使用

通过 MCP(OpenCode、Claude 等)
{
  "mcpServers": {
    "euclid-mcp": {
      "command": "python3",
      "args": ["-m", "euclid_mcp"],
      "cwd": "/path/to/euclid-mcp"
    }
  }
}
通过 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}")
通过 CLI

euclid-cli 命令可在终端中调用五种推理工具(reason、explain、 diagnose、what_if、check_kb)。它从 .euclid 文件(-f)或内联内容(--knowledge)中读取 KB;如果两者都没有,则使用 EUCLID_KB_PATH/预加载内容,并通过 --backend (auto | prolog | native)选择后端。查询来自 --query,或来自 KB 文件中的 ? 行。

不带子命令运行即可打开交互式 Euclid-IR REPL — 直接输入事实、规则和 ? query 行, 就像使用 swipl 或 psql 一样。会话知识库会在各次查询间累积。

$ 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 > :quit

REPL 元命令::check、:kb、:load <file>、:explain [query]、 :diagnose <query> [why|why_not|what_needs]、:what-if <mods>、:reset、 :quit。多行规则在 IF/AND 后继续输入(提示符变为 ... >)。 通过管道传入的输入会以批处理脚本的方式运行相同循环,不显示提示符:

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 --json

退出代码:成功时为 0;工具报告错误时为 1(包括 check 检测到无效 KB);用法错误时为 2。

完整 CLI 参考(所有标志、后端、JSON 输出):docs/CLI.md

输出示例
{
  "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)"}
          }
        }
      }
    }
  ]
}

规则可以通过末尾的 # RULE: <id> 注释携带审计跟踪 ID;该 ID 会显示为证明树中 rule 节点的 rule_id,因此可以引用某个决策(“此结论来自规则 GEN-2”)。

Diagnose 输出
{
  "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 输出
{
  "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 输出
{
  "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."
      ]
    }
  ]
}

使用场景

  • 小型大模型推理:将大模型(3-8B)的演绎任务交给确定性引擎
  • 可解释的决策:每个答案都附带证明树,可用于解释、推理追踪和论证
  • 业务规则:验证逻辑链(权限、工作流、合规性)
  • 依赖分析:检测循环依赖、进行拓扑排序
  • 教育:通过可见的证明链进行交互式逻辑辅导(参见 docs/DIDACTIC.md,这是一份围绕 euclid-cli REPL 编写的分步教学指南)
  • 知识预加载:复杂业务规则可以载入 Euclid,而不必使用向量数据库
  • 查询诊断:了解查询失败的原因,以及缺少哪些事实/规则
  • 场景分析:在将修改应用于生产环境之前,先测试“假设”情景
  • KB 验证:在推理前检查知识库是否一致
实际示例

这里提供了多个示例,包括:家谱、RBAC、分类、贷款资格、Cluedo 侦探、IT 安全与合规、LLM 与 Euclid-MCP 对比,…… 最值得关注的是 IT 安全与合规(包含 CIS、AWS、IAM 标准实施、公司政策实施以及数百条数据事实) 和并排对比的 LLM 与 Euclid-MCP。

示例完整说明:docs/EXAMPLES.md

集成

OpenCode

Euclid-MCP 在 .opencode.json 中包含一个预配置的 Agent:

{
  "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

运行 HTTP API:

python3 integrations/euclid_api.py --port 8080
端点方法用途
/reasonPOST使用证明树进行演绎
/explainPOST自然语言推理步骤
/diagnosePOST查询失败分析
/what-ifPOST场景测试
/check-kbPOSTKB 验证
/register-kbPOST注册命名 KB(kb_id)
/unregister-kbPOST移除命名 KB
/list-kbsPOST列出已注册的命名 KB
/healthGET健康检查(深度检查会 ping 引擎;仅在引擎卡死时返回 503)
/metricsGETPrometheus 指标(开放、只读,绝不包含 KB 内容)
# 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

Docker 镜像捆绑了 SWI-Prolog + Python,因此无需本地安装前置依赖。 基础镜像:swipl:stable(Debian Bookworm)。

通过 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-api

独立使用:

# 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 镜像大小:**约 370 MB(SWI-Prolog + Python 3.11 + 依赖项)。

**仅原生模式(精简版):**较小的镜像,使用纯 Python Euclid-IR 引擎, 不包含 SWI-Prolog(EUCLID_BACKEND=native)。适合空间有限的容器, 也适合作为小型知识库的默认选项。

# 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)
"

基础镜像:python:3.12-slim。

CLI 流水线
echo '{"knowledge": "red(apple)\\n? red($x)"}' | python3 integrations/euclid_cli.py

完整详情请参阅 integrations/README.md。

可扩展性

Euclid-MCP 引擎具有持久性:每个服务实例运行一个长期存活的 SWI-Prolog 进程,通过 JSON 行管道按请求重新加载,而不是每次调用都启动 Prolog。 单个实例一次处理一个请求。 请求保持无状态: 每个请求都携带自己的知识库(或使用预加载的知识库), 因此实例之间互不共享。

这使 Euclid-MCP 可以水平扩展:

  • HTTP API — 在负载均衡器(nginx、Kubernetes Service 等)后运行任意数量的实例。无需会话亲和性:任何实例都可以处理任何请求。
  • MCP stdio — 按设计,每个 MCP 客户端都会启动自己的实例,从而在客户端之间实现自然隔离和并行处理。
  • 资源占用 — 每个实例运行一个 swipl 进程(约几十 MB),而不是每个请求启动一个短暂运行的进程,因此单个实例即可低成本处理大量请求。

生产环境参考架构——为 HAProxy 后的副本集群配置负载均衡、资源限制、安全加固和监控: docs/PRODUCTION.md。

开发

要求: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=integrations

CI 工作流(.github/workflows/ci.yml)会在推送和拉取请求时,针对 Python 3.10–3.14 执行相同的检查。

日志与追踪

每次工具调用都会记录其名称、耗时和结果。设置 EUCLID_LOG_LEVEL(取值为 DEBUG、INFO、 WARNING、ERROR、CRITICAL)即可启用结构化日志,例如 EUCLID_LOG_LEVEL=INFO。未设置该变量时,仅输出警告和错误。

HTTP API 也支持请求追踪:发送 X-Request-Id 标头,该标头会在响应中原样返回,并包含在访问日志中。

监控与指标

HTTP API 在 GET /metrics 上公开 Prometheus 指标(开放、只读,绝不包含知识库内容):各工具调用/错误计数器和延迟直方图、引擎请求/重启/超时、HTTP 流量、返回的解、身份验证失败次数和进程运行时间——始终启用,无额外依赖 (euclid_mcp/metrics.py)。GET /health 是深度检查,会 ping 引擎并报告其工作区统计信息(仅当引擎卡死时返回 503)。

curl -s localhost:8080/metrics

完整技术栈(包含 Prometheus + Grafana + cAdvisor、仪表板和告警规则):monitoring/README.md。

什么是 Prolog?

Prolog(源自 PROgrammation en LOGique)是一种声明式逻辑编程 语言:你无需告诉机器如何计算答案,而是陈述事实和规则,让它通过合一和回溯找出由此推导出什么。Prolog 诞生于 20 世纪 70 年代初,至今仍是经受了实战考验的符号推理工具之一。

SWI-Prolog

Euclid-MCP 使用 SWI-Prolog 作为推理 引擎。SWI-Prolog 是成熟的 开源实现,自 1987 年以来持续开发并免费提供,广泛应用于工业界、学术界和研究领域。你可以用 Euclid-IR 编写规则;转换器会将其编译为 Prolog,而 SWI-Prolog 则执行推理并生成证明树,让 Euclid-MCP 的每个答案都可验证。

Euclid 是什么?

Euclid 是一位古希腊数学家。他在亚历山大生活和教学,通过严谨的逻辑证明奠定了几何学和数论的基础。

Euclid-MCP 不是:

  • 大模型
  • 知识库
  • 向量数据库
  • Agent 框架
  • 规划器

Euclid-MCP 是一个确定性推理引擎,可供上述任何一种系统使用。
Euclid-MCP 还能让 Edge 硬件上的小型大模型给出确定且可解释的回复。

许可证

Apache 2.0

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。