prolog-mcp
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., "@prolog-mcpfind overlapping cron schedules for backup and maintenance"
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.
prolog-mcp
MCP server wrapping SWI-Prolog for symbolic reasoning in coding agents.
Why
LLMs hallucinate on structured relational reasoning. They know the rules for message routing, scheduling constraints, or conflict detection — yet apply them incorrectly when reasoning in natural language. The gap between "the agent knows the rules" and "the agent correctly applies the rules" is exactly where a symbolic engine earns its place.
Prolog does not hallucinate. It backtracks exhaustively and returns all valid solutions. An agent can assert facts, query rules deterministically, and trust the results.
This MCP server gives coding agents a small, local, persistent Prolog runtime. The agent authors .pl files, asserts facts, queries the knowledge base, and interprets results. SWI-Prolog does the inference — deterministically, without guessing.
Background: First-Order Logic in Software Engineering — 16 use cases across the full software lifecycle where provable answers beat plausible guesses.
What you get:
Conflict detection — encode cron schedules as facts, query for overlapping periods. No manual interval arithmetic.
Routing rules — express message dispatch or handler policies as clauses. Query
handles(billing, Channel)and get the correct channel back.Constraint solving — model scheduling, resource contention, or planning as Prolog goals. The engine backtracks; the agent reads solutions.
Agent self-knowledge — agents accumulate persistent facts (
user_preference/3,session_context/2, etc.) into a per-agent layer. Shared fact visibility across agents is intentional.
Related MCP server: Chiasmus
How it works
Claude Code ┐
├─── MCP stdio ───► prolog-mcp (Node.js) ─── HTTP ───► SWI-Prolog :7474
OpenClaw agents ┘ │ │
write consult
│ │
└──────────────► kbDir/ ◄────────────┘
core.pl
agents/*.pl
sessions/*.pl
scratch/*.plA single Node.js process (prolog-mcp) listens on stdio for MCP calls. SWI-Prolog runs as a persistent HTTP daemon on localhost:7474. Both Claude Code and OpenClaw agents connect via separate stdio MCP transports and share the same Prolog backend.
Layer files are the source of truth — reloaded on daemon restart. Facts written via prolog_assert are appended to disk immediately and survive restarts. The MCP tools are the public API; the HTTP endpoints are internal.
Prerequisites
Skip prerequisites with Docker — if you have Docker installed you can run prolog-mcp without installing SWI-Prolog or Node.js locally. See Docker below.
SWI-Prolog 9.x
macOS (Homebrew):
brew install swi-prolog
swipl --version # SWI-Prolog version 9.x.xUbuntu / Debian:
sudo apt update
sudo apt install swi-prolog
swipl --versionOther Linux / manual install: see swi-prolog.org/Download.html
Node.js 22+
via nvm (recommended):
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
nvm install 22
nvm use 22
node --version # v22.x.xvia package manager:
# macOS
brew install node@22
# Ubuntu / Debian
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install nodejsVerify both are installed
swipl --version && node --version
# SWI-Prolog version 9.x.x ...
# v22.x.xInstallation
git clone https://github.com/umuro/prolog-mcp
cd prolog-mcp
npm install
npm run buildAfter npm run build, dist/ is populated. The KB directory (~/.local/share/prolog-mcp) is created automatically on first run with subdirectories agents/, sessions/, and scratch/.
Docker
No SWI-Prolog or Node.js installation required — the image bundles both.
Build:
docker build -t prolog-mcp .Run (MCP over stdio):
docker run -i --rm \
-v "$HOME/.local/share/prolog-mcp:/data/prolog-mcp" \
prolog-mcp-ikeeps stdin open for the MCP stdio transport.-vmounts your KB directory so facts persist between container runs. Omit it for an ephemeral, in-container KB.
Register with Claude Desktop (Docker variant):
{
"mcpServers": {
"prolog": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-v", "/Users/you/.local/share/prolog-mcp:/data/prolog-mcp",
"prolog-mcp"
]
}
}
}The swipl daemon is started automatically inside the container by the Node.js process on first tool call (autoRestartSwipl: true).
Quick Start
Step 1 — Start the daemon:
bash prolog/start.shIdempotent, PID-guarded. Starts swipl on :7474, creates KB dirs, writes PID to /tmp/prolog-mcp.pid.
Step 2 — Register with your MCP client (see Registration below).
Step 3 — First query:
Write a fact file:
{ "tool": "prolog_write_file", "arguments": { "path": "scratch/hello.pl", "content": "greeting(world)." } }Response: { "ok": true }
Query it:
{ "tool": "prolog_query", "arguments": { "goal": "greeting(X)" } }Response: { "solutions": [{ "X": "world" }], "exhausted": true }
Assert a new fact (persists to agent:main by default):
{ "tool": "prolog_assert", "arguments": { "term": "greeting(claude)" } }Query again — both facts returned:
{ "solutions": [{ "X": "world" }, { "X": "claude" }], "exhausted": true }Step 4 — Stop the daemon:
kill $(cat /tmp/prolog-mcp.pid)Case Studies
Case Study 1: Circular Dependency Detection
Problem: Given a module dependency graph, find all cycles and the exact edges to cut. In a codebase with 20+ modules, manual inspection misses transitive cycles.
The Prolog rules:
:- dynamic depends/2.
path(A, B, _) :- depends(A, B).
path(A, B, Vis) :- depends(A, C), \+ member(C, Vis), path(C, B, [C|Vis]).
can_reach(A, B) :- path(A, B, [A]).
cycle(A) :-
depends(A, Next),
(Next = A ; path(Next, A, [A, Next])).
cycle_edge(A, B) :-
depends(A, B), cycle(A), cycle(B).MCP sequence:
// Write the rule file
{ "tool": "prolog_write_file", "arguments": { "path": "scratch/deps.pl", "content": "... above ..." } }
// Assert the graph — logger→auth is the bug
{ "tool": "prolog_assert", "arguments": { "term": "depends(auth, db)" } }
{ "tool": "prolog_assert", "arguments": { "term": "depends(db, cache)" } }
{ "tool": "prolog_assert", "arguments": { "term": "depends(cache, logger)" } }
{ "tool": "prolog_assert", "arguments": { "term": "depends(logger, auth)" } }
{ "tool": "prolog_assert", "arguments": { "term": "depends(api, router)" } }
{ "tool": "prolog_assert", "arguments": { "term": "depends(standalone, utils)" } }
// Which modules are in a cycle?
{ "tool": "prolog_query", "arguments": { "goal": "cycle(M)" } }
→ { "solutions": [{ "M": "auth" }, { "M": "db" }, { "M": "cache" }, { "M": "logger" }] }
// Exact edges forming the cycle
{ "tool": "prolog_query", "arguments": { "goal": "cycle_edge(A, B)" } }
→ { "solutions": [
{ "A": "auth", "B": "db" }, { "A": "db", "B": "cache" },
{ "A": "cache", "B": "logger" }, { "A": "logger", "B": "auth" }
] }
// Standalone is safe
{ "tool": "prolog_query", "arguments": { "goal": "cycle(standalone)" } }
→ { "solutions": [] }An LLM tracing a 20-node graph manually will hallucinate. Prolog backtracks exhaustively and returns every cycle — not a guess.
Case Study 2: Routing Rules with Runtime Updates
Problem: A multi-agent system routes messages by topic. Rules change at runtime as agents come online. Static config requires a restart; LLM routing guesses wrong under edge cases.
The routing rules (core.pl):
handles(billing, telegram).
handles(support, telegram).
handles(technical, discord).
handles(X, telegram) :- \+ handles(X, _). % default fallbackMCP sequence:
// Load routing rules
{ "tool": "prolog_write_file", "arguments": { "path": "core.pl", "content": "... above ..." } }
// Route a message
{ "tool": "prolog_query", "arguments": { "goal": "handles(billing, Channel)" } }
→ { "solutions": [{ "Channel": "telegram" }] }
// Fallback for unknown topic
{ "tool": "prolog_query", "arguments": { "goal": "handles(marketing, Channel)" } }
→ { "solutions": [{ "Channel": "telegram" }] }
// New agent comes online — add route, no restart
{ "tool": "prolog_assert", "arguments": { "term": "handles(alerts, pagerduty)" } }
// Retract and replace a rule — persists to disk
{ "tool": "prolog_retract", "arguments": { "term": "handles(billing, telegram)", "layer": "agent:main" } }
{ "tool": "prolog_assert", "arguments": { "term": "handles(billing, slack)" } }"What channels handle discord?" becomes prolog_query("handles(X, discord)"). No parsing, no regex, no LLM guess.
Case Study 3: Cron Job Conflict Detection
Problem: A scheduler has 10+ periodic jobs. Some fire at overlapping times, causing lock contention. Which jobs conflict?
The rules (scratch/cron.pl):
:- dynamic job/3.
conflicts(A, B) :-
job(A, every, PA),
job(B, every, PB),
A @< B,
( 0 is PA mod PB ; 0 is PB mod PA ).MCP sequence:
{ "tool": "prolog_write_file", "arguments": { "path": "scratch/cron.pl", "content": "... above ..." } }
{ "tool": "prolog_assert", "arguments": { "term": "job(brain_watchdog, every, 3600)" } }
{ "tool": "prolog_assert", "arguments": { "term": "job(linkedin_mon, every, 1800)" } }
{ "tool": "prolog_assert", "arguments": { "term": "job(cache_warm, every, 300)" } }
{ "tool": "prolog_assert", "arguments": { "term": "job(backup_db, every, 900)" } }
{ "tool": "prolog_assert", "arguments": { "term": "job(log_rotate, every, 3600)" } }
{ "tool": "prolog_query", "arguments": { "goal": "conflicts(X, Y)" } }
→ { "solutions": [
{ "X": "brain_watchdog", "Y": "linkedin_mon" },
{ "X": "brain_watchdog", "Y": "log_rotate" },
{ "X": "backup_db", "Y": "cache_warm" }
] }Desynchronize one job by adjusting its period, re-query — conflicts instantly recalculated. No arithmetic errors, no missed pairs.
Software Lifecycle Use Cases
The 3 case studies above demonstrate core capabilities. The following 12 use cases show how first-order logic applies across the entire software lifecycle. Each one is a place where Prolog's provable answers beat an LLM's plausible guesses.
Full article: First-Order Logic in Software Engineering
Requirements
4. Requirements Consistency Checking — Express requirements as Prolog facts. Query for contradictions. An LLM says "they look fine." Prolog finds the exact conflicting pair.
5. Cross-Team Interface Contracts — Team A produces user_id: string, Team B expects user_id: integer. Query all_interfaces_valid? before teams meet. Catch bugs at design time.
6. Acceptance Criteria as Provable Contracts — valid_order(User, Items) :- has_permission(User, create_order), all_items_in_stock(Items), ... The spec IS the test oracle.
Architecture & Design
7. Configuration Constraint Satisfaction — Port assignments, service placement, resource allocation. Prolog returns every valid configuration; LLMs guess one and miss constraints.
8. Access Control Matrix Verification — 8 roles, 40 permissions, escalation rules. Prolog explores every role-path, finds privilege escalations LLMs say "look secure."
9. State Machine Invariant Verification — "Can a payment exist without an order?" Prolog explores all transitions, proves impossibility or finds the breaking sequence.
Implementation
10. Exhaustive Test Case Generation — Preconditions as rules → minimal test matrix covering every valid/invalid combination. Zero missed edge cases.
11. Data Flow Integrity (PII Leak Detection) — Query pii_leak(source, sink)? across 40 services. Get the actual data path, not "review your data flow."
12. Refactoring Safety — equivalent(old, new, Input)? for every input class. Find the one case where your refactor changes behavior.
Deployment & Operations
13. Deployment Ordering — Topological sort with constraints. Optimal order, safe parallelization, cycle detection.
14. Cron Conflict Detection — Every time overlap against shared resource rules. 47 jobs, 12 servers, zero missed conflicts.
Compliance
15. Regulatory Compliance — GDPR/HIPAA/SOC2 as Prolog rules. Query compliant(my_workflow)? for provable yes/no. Show output to auditors.
16. Architectural Debt Detection — "No service bypasses the API gateway." Six months later, which ones do? Prolog tells you.
Use Case Summary
Category | Cases |
Graph/Relational | Dependency detection, routing, scheduling, agent memory |
Requirements | Consistency, contracts, acceptance criteria |
Architecture | Config constraints, access control, state invariants |
Implementation | Test generation, data flow, refactoring safety |
Deployment | Ordering, cron conflicts |
Compliance | Regulatory rules, architectural debt |
The pattern: every bug that escapes production was a logical relationship nobody verified. Prolog closes that gap — not by guessing better, but by proving.
Full article: hightechmind.io/ai/first-order-logic
Tool Reference
prolog_query
Execute a Prolog goal across all loaded KB layers and return all solutions.
Parameter | Type | Default | Description |
| string | required | Prolog goal, e.g. |
| number | 5000 | Hard timeout in milliseconds |
// Request
{ "goal": "ancestor(tom, X)", "timeout_ms": 5000 }
// All solutions found
{ "solutions": [{ "X": "bob" }, { "X": "ann" }], "exhausted": true }
// No solutions — not an error
{ "solutions": [], "exhausted": true }
// Timeout with partial results
{ "error": "timeout", "partial": [{ "X": "bob" }] }Queries for undefined predicates return [] instead of an error.
prolog_assert
Assert a fact or rule into the KB. Persists to disk and survives daemon restarts.
Parameter | Type | Default | Description |
| string | required | Prolog fact or rule, e.g. |
| string |
|
|
// Fact (permanent by default)
{ "term": "handles(billing, telegram)" }
→ { "ok": true }
// Rule
{ "term": "route(X,C) :- handles(X,C)", "layer": "agent:main" }
→ { "ok": true }
// Session-scoped (ephemeral)
{ "term": "current_task(refactor)", "layer": "session:abc123" }
→ { "ok": true }Layer must contain a colon (agent:main, not agent). core is rejected — use prolog_write_file for core.pl. Trailing periods in the term are stripped automatically.
prolog_retract
Retract matching facts or rules from a layer. Removes from disk and reloads — retraction survives daemon restarts.
Parameter | Type | Default | Description |
| string | required | Prolog fact or rule head to retract |
| string | required |
|
{ "term": "handles(billing, telegram)", "layer": "agent:main" }
→ { "ok": true, "removed": 1 }Uses file-backed removal: the layer file is rewritten on disk and reloaded. Retraction persists across restarts. core is rejected.
prolog_write_file
Write a .pl file to disk and hot-reload it.
Warning: replaces the entire file — not an append. For individual facts use
prolog_assert. On syntax error the file is rolled back and the server keeps running.
Parameter | Type | Default | Description |
| string | required | Relative path inside |
| string | required | Complete Prolog source — the full file content |
{ "path": "scratch/deps.pl", "content": ":- dynamic depends/2.\ncycle(A) :- depends(A, A)." }
→ { "ok": true }
// Syntax error — file is rolled back
→ { "error": "syntax_error", "detail": "line 3: unexpected token ':-'" }Path traversal (..) is rejected. Max 512 KB (configurable).
prolog_load_file
Hot-reload an existing .pl file already on disk without modifying its content.
Parameter | Type | Default | Description |
| string | required | Relative path inside |
{ "path": "agents/main.pl" }
→ { "ok": true }Validates syntax with read_term before loading. Useful for re-syncing after manual file edits.
prolog_list_facts
List facts in the KB, optionally filtered by layer and functor name.
Parameter | Type | Default | Description |
| string | — | Filter by layer, e.g. |
| string | — | Filter by predicate name |
| number | 100 | Max results |
| number | 0 | Skip first N results (pagination) |
{ "layer": "agent:main", "functor": "user_preference", "limit": 50 }
→ { "facts": ["user_preference(alice, dark_mode, true)."], "truncated": false }
// More results exist
→ { "facts": [...], "truncated": true }functor and layer filters can be combined. offset >= total returns [].
prolog_reset_layer
Clear a session or scratch layer. Core and agent layers are permanent and cannot be bulk-reset.
Parameter | Type | Default | Description |
| string | required |
|
{ "layer": "session:abc123" }
→ { "ok": true, "removed": 17 }Rejects core and agent:*. For session:<id>, also deletes the file from disk. To forcibly clear an agent layer, delete agents/<id>.pl directly and call prolog_load_file with an empty file.
KB Layer Model
The knowledge base is split into named layers. Each layer is a .pl file loaded into memory on daemon startup and reloaded whenever the file changes.
Layer | File path | Who writes | Lifetime |
|
| Operator only via | Permanent, read-only at runtime |
|
| That agent via | Permanent, survives restarts |
|
| Any agent via | Session lifetime |
|
| Operator via | Manual reset only |
All layers are visible to all queries — cross-agent fact visibility is intentional. Layer files are the source of truth and are reloaded on daemon restart.
Agent layer bulk-reset is intentionally unavailable via MCP. Operator escape hatch for stale agent facts:
Delete the file:
rm kbDir/agents/<id>.plCall
prolog_load_file("agents/<id>.pl")with an empty file to unload predicates from SWI memory
Configuration
All settings can be provided via a JSON config file or environment variables. Environment variables take precedence.
Config file: prolog-mcp.json in the working directory, or ~/.config/prolog-mcp.json. Override with PROLOG_MCP_CONFIG.
{
"swiplPort": 7474,
"kbDir": "~/.local/share/prolog-mcp",
"defaultQueryTimeoutMs": 5000,
"maxFileSizeBytes": 524288,
"autoRestartSwipl": true,
"writeableLayers": ["agent", "session"]
}Key | Env var | Default | Description |
|
|
| Port for the SWI-Prolog HTTP daemon |
|
|
| Knowledge base directory; |
| — |
| Default query timeout in ms |
| — |
| Max file size for |
| — |
| Auto-restart swipl if it crashes |
| — |
| Layer prefixes allowed for assert/retract |
Security
Concern | Mitigation |
Path traversal via |
|
Agent writes to |
|
Infinite query loops |
|
Oversized file writes | 512 KB max enforced before write; returns |
Syntax error crashing the server |
|
Double-start race on swipl restart |
|
Concurrent writes to the same layer | Per-layer async write queue in |
In-memory facts surviving reset |
|
Trust model: core.pl is operator-only. Agent layers are permanent and writable only by the owning agent. Session and scratch layers are ephemeral. All writable paths are validated against kbDir before any disk operation.
Registration
Claude Code (~/.claude/settings.json)
{
"mcpServers": {
"prolog": {
"command": "node",
"args": ["/absolute/path/to/prolog-mcp/dist/index.js"],
"env": { "KB_DIR": "/absolute/path/to/your/kb" }
}
}
}OpenClaw (~/.openclaw/openclaw.json)
{
"tools": {
"mcp": {
"servers": {
"prolog": {
"transport": "stdio",
"command": "node",
"args": ["/absolute/path/to/prolog-mcp/dist/index.js"],
"env": { "KB_DIR": "/absolute/path/to/your/kb" }
}
}
}
}
}Gemini CLI (~/.gemini/settings.json)
{
"mcpServers": {
"prolog": {
"command": "node",
"args": ["/absolute/path/to/prolog-mcp/dist/index.js"],
"env": { "KB_DIR": "/absolute/path/to/your/kb" }
}
}
}Crush (~/.config/crush/crush.json)
{
"mcpServers": {
"prolog": {
"type": "stdio",
"command": "node",
"args": ["/absolute/path/to/prolog-mcp/dist/index.js"],
"env": { "KB_DIR": "/absolute/path/to/your/kb" }
}
}
}
KB_DIRmust be an absolute path. The server expands~at startup as a convenience, but explicit absolute paths are required for non-interactive contexts (CI, Docker).
Contributing
Contributions welcome. Before submitting a PR:
npm run build # must compile clean
npm test # 89 tests, all must pass (requires swipl)
npm run lint # zero warningsOpen an issue first for significant changes.
License
MIT
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-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
- Flicense-qualityDmaintenanceA neurosymbolic AI server combining Prolog’s symbolic reasoning with Model Context Protocol (MCP) for hybrid AI applications.Last updated24
- Alicense-qualityFmaintenanceA symbolic reasoning engine that enables symbolic ontology operations through an MCP server.Last updated1Mozilla Public 2.0
Related MCP Connectors
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Local-first RAG engine with MCP server for AI agent integration.
MCP server for AI agent profiles and smart notes. 60+ coding prompt packs with expert personas.
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/umuro/prolog-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server