SWI-Prolog MCP server and service

I have created GitHub - JanWielemaker/mcp: SWI-Prolog MCP server framework with Prolog manual, introspection and toplevel servers. · GitHub, also available as the pack mcp. It provides

  • A implementation of an MCP server framework for SWI-Prolog with both stdio JSON-RPC transport and HTTP transport.
  • A good collection of Prolog specific tools, split over four groups:
    • prolog_help tools provides access to the SWI-Prolog manual, including (apropos) search and using introspection tools to find additional information on predicates, modules, files, etc.
    • source tools allow the LLM to list, search and extract fragments of the entire SWI-Prolog source code.
    • git tools allows the LLM to inspect the GIT history and search using git grep.
    • kernel tools find the location of foreign predicates.
    • target_toplevel allows the LLM to run a Prolog instance and interact with it. It also provides access to the tracer, linter, profiler and coverage tools. This only makes sense when using the stdio transport. The Prolog process runs under the same sandbox as the coding agent (make sure it runs in sandbox!). In theory you could also the the HTTP transport as long as you ensure the server is properly sandboxed.

There is a public server on https://ai.swi-prolog.org/mcp. I have connected that to the web version of Claude and asked

Can you tell me how SWI-Prolog implements atom_codes/2?

It nicely started using the MCP. Creates a long story and this summary:

The short version

atom_codes/2 itself contains essentially no logic; it sets X_ATOM and hands off to x_chars(), which is a generic bidirectional atomic↔text converter. The two modes collapse to: try PL_get_text on arg1 and PL_unify_text(...PL_CODE_LIST) on arg2; if arg1 is a variable, read arg2’s code list and PL_unify_text(...PL_ATOM) back onto arg1. All the encoding handling lives inside PL_get_text/PL_unify_text, and the number-parsing complexity in x_chars is dead code for the atom case.

One consequence worth noting: because arg1 is fetched with CVT_ATOMIC, atom_codes/2 in SWI-Prolog is more permissive than strict ISO on the forward mode — e.g. atom_codes(42, X) succeeds, since a number is atomic and its text is taken directly.

That is pretty accurate :slight_smile:

I think (hope) that connecting this to your web interface or coding agent should improve its ability to generate and reason about SWI-Prolog code. For coding

  • Install the pack. First update SWI-Prolog to the latest GIT version (or wait for version 10.1.11) using swipl pack install mcp
  • Next, create .mcp.json in your project directory holding
{
  "mcpServers": {
    "swipl": {
      "command": "swipl",
      "args": [
        "mcp"
      ]
    }
  }
}

Use swipl mcp --help for some options.

Writing your MCP servers

There are several examples in the examples directory to help you write your own Prolog based MCP server.

Limitations

Currently there is no way to have progress events in HTTP servers. Adding that requires some extensions to SWI-Prolog’s HTTP server framework.

Finally

Please try and report experience and/or suggests how we can improve this.

1 Like