Skip to main content
Glama
umuro

prolog-mcp

by umuro

prolog-mcp

MCP server wrapping SWI-Prolog for symbolic reasoning in coding agents.

Node.js 22+ SWI-Prolog 9.x MIT License Tests Passing


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: prolog-mcp

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/*.pl

A 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.x

Ubuntu / Debian:

sudo apt update
sudo apt install swi-prolog
swipl --version

Other 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.x

via package manager:

# macOS
brew install node@22

# Ubuntu / Debian
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install nodejs

Verify both are installed

swipl --version && node --version
# SWI-Prolog version 9.x.x ...
# v22.x.x

Installation

git clone https://github.com/umuro/prolog-mcp
cd prolog-mcp
npm install
npm run build

After 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
  • -i keeps stdin open for the MCP stdio transport.

  • -v mounts 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.sh

Idempotent, 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 fallback

MCP 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 Contractsvalid_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 Safetyequivalent(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

goal

string

required

Prolog goal, e.g. ancestor(tom, X)

timeout_ms

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

term

string

required

Prolog fact or rule, e.g. handles(billing, telegram) or route(X,C) :- handles(X,C)

layer

string

agent:main

agent:<id> for permanent storage or session:<id> for ephemeral session storage

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

term

string

required

Prolog fact or rule head to retract

layer

string

required

agent:<id> or session:<id>

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

path

string

required

Relative path inside kbDir, e.g. core.pl or scratch/rules.pl

content

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

path

string

required

Relative path inside kbDir

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

layer

string

Filter by layer, e.g. agent:main

functor

string

Filter by predicate name

limit

number

100

Max results

offset

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

layer

string

required

session:<id> or scratch

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

core

kbDir/core.pl

Operator only via prolog_write_file

Permanent, read-only at runtime

agent:<id>

kbDir/agents/<id>.pl

That agent via prolog_assert

Permanent, survives restarts

session:<id>

kbDir/sessions/<id>.pl

Any agent via prolog_assert

Session lifetime

scratch

kbDir/scratch/<name>.pl

Operator via prolog_write_file

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:

  1. Delete the file: rm kbDir/agents/<id>.pl

  2. Call 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

swiplPort

SWIPL_PORT

7474

Port for the SWI-Prolog HTTP daemon

kbDir

KB_DIR

~/.local/share/prolog-mcp

Knowledge base directory; ~ is expanded

defaultQueryTimeoutMs

5000

Default query timeout in ms

maxFileSizeBytes

524288

Max file size for prolog_write_file (512 KB)

autoRestartSwipl

true

Auto-restart swipl if it crashes

writeableLayers

["agent","session"]

Layer prefixes allowed for assert/retract


Security

Concern

Mitigation

Path traversal via prolog_write_file

path-guard.ts rejects paths outside kbDir and any .. segments

Agent writes to core.pl via assert

prolog_assert and prolog_retract reject core at runtime

Infinite query loops

call_with_time_limit/2 hard timeout per query (default 5 s, configurable)

Oversized file writes

512 KB max enforced before write; returns file_too_large

Syntax error crashing the server

check_syntax (via read_term) validates before consult; file rolled back on error; server continues

Double-start race on swipl restart

ServerHealth.ensureRunning() serializes restart attempts; start.sh is PID-file guarded

Concurrent writes to the same layer

Per-layer async write queue in LayerManager

In-memory facts surviving reset

mcp_layer_track/2 records assertz'd functor/arity per layer; abolished on 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_DIR must 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 warnings

Open an issue first for significant changes.


License

MIT

Available Tools

7 tools
prolog_assertA

Assert a fact or rule into the KB. Persists to disk and survives daemon restarts. Use agent:main (default) for permanent knowledge; use session: for ephemeral facts tied to the current session.

ParametersJSON Schema
NameRequiredDescriptionDefault
termYesProlog fact or rule, e.g. 'handles(billing, telegram)' or 'route(X,C) :- handles(X,C)'
layerNo'agent:<id>' for permanent storage (default: agent:main) or 'session:<id>' for session-scoped ephemeral storage

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses persistence to disk, survival of restarts, and scoping. No annotation burden; description fills gap well. Could mention error behavior or idempotency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded, no redundancy. Every part adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose, parameters, scoping, and persistence. No output schema, but return behavior (e.g., success) is not described – minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%; description adds value with examples for term and explanation of layer patterns and default. Enhances schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states it asserts facts/rules into KB, with persistence and scoping details. Distinguishes from query/retract tools implicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains when to use agent:main vs session:<id> for permanent vs ephemeral storage. Does not explicitly exclude sibling use cases, but context makes it clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

prolog_list_factsA

List facts in the KB, optionally filtered by functor

ParametersJSON Schema
NameRequiredDescriptionDefault
layerNoFilter by layer, e.g. 'agent:main' or 'session:abc'
limitNoMax results (default 100)
offsetNoSkip first N results
functorNoFilter by functor name

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must carry the burden. It does not disclose that the operation is read-only, nor does it mention pagination behavior or default limits (e.g., default limit 100 from schema). The description is minimally transparent but could be more explicit.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence with no redundant words. It is front-loaded with the core action and resource, making it highly concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given four parameters, no output schema, and no annotations, the description is minimally adequate. It does not describe return format, the effect of layer/offset/limit, or how to interpret results. Could be improved with more context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description only repeats the functor filter mentioned in the schema. It adds no new meaning beyond what the schema already provides for any parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action 'list facts' and the resource 'KB', and mentions optional filtering by functor, which distinguishes it from sibling tools like prolog_query (for queries) and prolog_assert (for adding facts).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus siblings such as prolog_query for complex queries or prolog_assert/retract for modifications. The description lacks context for appropriate usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

prolog_load_fileB

Hot-reload an existing .pl file

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesRelative path inside kbDir

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden. 'Hot-reload' implies mutating internal state, but it omits side effects (e.g., whether declared facts are cleared, if definitions are replaced). No disclosure of errors or preconditions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single concise sentence with no superfluous words. Every word adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description lacks important details: what 'hot-reload' entails, error behavior, if the file must be pre-loaded, and any state changes. Given no output schema and no annotations, the description is insufficient for safe and correct agent use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers 100% of parameters (only 'path'), and the json-schema description 'Relative path inside kbDir' is clear. The tool description adds no extra meaning, so baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('hot-reload') and resource ('.pl file'), clearly indicating it reloads an existing Prolog file. This distinguishes it from sibling tools like prolog_query, prolog_assert, etc., which perform different operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives (e.g., prolog_reset_layer or prolog_write_file). The description does not mention prerequisites, nor does it advise against using it in certain scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

prolog_queryA

Execute a Prolog goal and return all solutions as JSON

ParametersJSON Schema
NameRequiredDescriptionDefault
goalYesProlog goal, e.g. 'ancestor(tom, X)'
timeout_msNoTimeout in ms (default 5000)

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It states the tool returns all solutions as JSON but does not disclose potential behavioral traits like side-effects (likely none), rate limits, or performance implications for long-running queries.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence, 10 words, highly concise and front-loaded with key information. No unnecessary words or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 2 parameters and no output schema, the description covers the core functionality. However, it lacks details on error behavior, result limits, or how JSON is structured. For a query tool, this is adequate but not fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds an example for the 'goal' parameter but provides no additional context for 'timeout_ms' beyond its schema description. Overall, the description adds marginal value over the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Execute'), the resource ('a Prolog goal'), and the output ('return all solutions as JSON'). It distinguishes from siblings like prolog_assert and prolog_retract which modify the knowledge base.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

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, such as when to use prolog_list_facts for listing facts or prolog_write_file for persistence. No when-to-use or when-not-to-use context is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

prolog_reset_layerA

Clear a session or scratch layer (core and agent layers are permanent)

ParametersJSON Schema
NameRequiredDescriptionDefault
layerYes'session:<id>' or 'scratch'

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description must cover behavior. It discloses that core and agent layers are permanent (cannot be reset), but doesn't specify side effects, authorization needs, or whether the action is reversible.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence with no redundancy. Front-loads the key action and immediately provides critical context about permanence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with one parameter and no output schema, the description covers the essential functionality and constraints. It could mention that clearing is destructive and irreversible, but is otherwise adequate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the description adds value by clarifying which layer values are valid (session or scratch) and explicitly stating that core/agent are not, going beyond the schema's 'string' type.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states it clears a session or scratch layer, and distinguishes permanent layers (core, agent) from resettable ones. This differentiates from sibling tools like prolog_query or prolog_assert.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implies use for session or scratch layers only, via the parenthetical about permanent layers. However, no explicit guidance on when to use versus alternatives like prolog_retract.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

prolog_retractA

Retract matching facts or rules from a layer. Removes from disk and reloads — retraction survives daemon restarts.

ParametersJSON Schema
NameRequiredDescriptionDefault
termYesProlog fact or rule head to retract, e.g. 'handles(billing, telegram)'
layerYes'agent:<id>' or 'session:<id>' — must include the colon and an id

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Without annotations, the description fully carries the burden. It discloses persistence ('retraction survives daemon restarts') and the reload process. However, it omits details on side effects (e.g., reload scope) and error states (e.g., missing term).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences: the first states the action, the second adds critical behavioral context. No extraneous information, optimally front-loaded for quick understanding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple 2-parameter tool, the description covers core functionality and persistence but lacks details on return value, success/failure indication, and behavior when no matching fact exists. This gap could hinder correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with clear descriptions for both parameters (term example and layer format). The tool description adds little beyond restating 'from a layer', so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action 'Retract matching facts or rules from a layer' with a specific verb and resource. It distinguishes from siblings like prolog_assert (add) and prolog_reset_layer (clear all) by focusing on selective permanent removal.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit when-to-use or when-not-to-use guidance is provided. The context of siblings implies usage for persistent removal, but no alternatives or exclusions are mentioned, leaving the agent to infer from the name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

prolog_write_fileA

Write a .pl file to disk and hot-reload it. WARNING: replaces the entire file — not an append. Use for authoring multi-clause rule files (core.pl, scratch/). For individual facts use prolog_assert instead. On syntax error the file is rolled back and the server keeps running.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesRelative path inside kbDir, e.g. 'core.pl' or 'scratch/foo.pl'
contentYesComplete Prolog source — the full file content, not just the new clause

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses that it replaces the entire file (destructive behavior) and that on syntax error the file is rolled back with the server continuing to run. No annotations exist, so description carries full burden.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Concise, front-loaded purpose, then warning, then usage. Every sentence adds value with no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose, behavior (replace, rollback), usage examples, and alternatives. No output schema needed as return is implicit. Sibling tools listed for context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with good descriptions for both parameters. The description adds context about file usage (multi-clause rule files) but does not significantly extend beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it writes a .pl file and hot-reloads it. It distinguishes itself from prolog_assert for individual facts, making the purpose specific and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use (authoring multi-clause rule files like core.pl, scratch/) and when not to (use prolog_assert for individual facts). Also includes a warning about replacing the entire file.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4/5.0
Disambiguation5/5

Each tool has a clear, distinct purpose: query for executing queries, assert for adding facts/rules, retract for removing, write_file for authoring rule files, load_file for reloading, list_facts for listing, and reset_layer for clearing layers. No overlapping functionality.

Naming Consistency5/5

All tools use a consistent 'prolog_' prefix followed by a verb or verb_noun pattern in snake_case (e.g., prolog_query, prolog_write_file). The naming convention is uniform and predictable.

Tool Count5/5

With 7 tools, the set covers the core operations for a Prolog knowledge base server: querying, asserting, retracting, file management, listing, and resetting. The count is well-scoped for the domain.

Completeness4/5

The tool set covers essential operations (query, assert, retract, file I/O, listing, resetting). A minor gap is the lack of a direct update tool, but retract+assert can serve that purpose. Also, no tool to list all predicates without filtering, but list_facts with no filter may cover it.

Maintenance

ActivityStale
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP 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.
    79
    210
    Apache 2.0
  • A
    license
    B
    quality
    A
    maintenance
    MCP server for logical reasoning that turns facts into formal proofs using a deterministic inference engine with Prolog.
    8
    4
    Apache 2.0

Latest Blog Posts

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