Prolog.NET.MQI 1.0.0

dotnet add package Prolog.NET.MQI --version 1.0.0
                    
NuGet\Install-Package Prolog.NET.MQI -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Prolog.NET.MQI" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Prolog.NET.MQI" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Prolog.NET.MQI" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Prolog.NET.MQI --version 1.0.0
                    
#r "nuget: Prolog.NET.MQI, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Prolog.NET.MQI@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Prolog.NET.MQI&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Prolog.NET.MQI&version=1.0.0
                    
Install as a Cake Tool

Prolog.NET.MQI

Prolog.NET.MQI provides a lightweight SWI Prolog Machine Query Interface (MQI) client for C#.

Usage

This library only implements the MQI's wire protocol; see the MQI documentation for message semantics, timeouts, and error conditions. Rather than a single generic "send a command" method, IMqiClient exposes one dedicated method per MQI message kind (Connect, Run, RunAsync, CancelAsync, AsyncResult, Close, Quit), each returning its own response type (RunResponse, AsyncResultResponse, etc.) instead of a raw Prolog term, so you pattern-match on the outcome instead of parsing terms yourself.

Registering the client

Register IMqiClient with dependency injection via AddMqiClient():

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMqiClient();

var app = builder.Build();

Connecting and running a goal

IMqiClient is registered as scoped, so resolving it inside a request gives you a connection for the lifetime of that request; the container disposes it automatically once the request ends.

app.MapGet("/people/{name}/children", async (string name, IMqiClient mqi, CancellationToken cancellationToken) =>
{
    ConnectResponse connect = await mqi.Connect("127.0.0.1", 12321, "12321", cancellationToken);
    if (connect is not ConnectResponse.True)
    {
        return Results.Problem("Could not connect to the MQI server.");
    }

    RunResponse response = await mqi.Run($"parent({name}, Child)", Prolog.NET.MQI.Timeout.Default);

    // Shuts down the connection to the MQI server
    await mqi.Close();

    return response switch
    {
        RunResponse.True { Solutions: var solutions }
          => Results.Ok(
              solutions
              .Select(s => ((PrologTerm.PrologString)s["Child"]).Value)
              .ToArray()),
        RunResponse.False => Results.Ok(Array.Empty<string>()),
        RunResponse.Error error => Results.Problem($"Query failed: {error.ErrorName}"),
        _ => Results.Problem("Could not run the query.")
    };
});

app.Run();

Reading terms

Solutions are returned as PrologTerm values, matching SWI-Prolog's canonical JSON representation of terms:

JSON PrologTerm
string PrologString
number Number
true / false Bool
null Null
array List (Cons / Nil)
{"functor": ..., "args": [...]} Compound
any other object Dict (keyed by DictKey)
non-JSON text Atom

For example, running parent(homer, Child) above yields a RunResponse.True whose Solutions bind "Child" to PrologTerm.PrologString values like "bart", "lisa" and "maggie", while a failing arithmetic goal like X is 1/0 instead yields a RunResponse.Error whose Exception is a RunResponse.ErrorValue.CompoundValue wrapping a PrologTerm.Compound with Functor: "evaluation_error".

Running tests locally

Configure test settings

Inside /tests/Prolog.NET.MQI.Tests, create appsettings.Development.json to set the required connection parameters:

{
  "MqiOptions": {
    "RunLocally": false,
    "Host": "127.0.0.1",
    "Port": 12321,
    "Password": "12321",
    "Version": {
      "Major": 1,
      "Minor": 0
    }
  }
}

If RunLocally is set to true, the integration tests will run against a SWI-Prolog test container using the configured Port and Password and made accessible from 127.0.0.1 (localhost). If set to false, you will need a running MQI server on the machine to test against and configure Port and Password to match those of your MQI server instance. Leave the Host value set to 127.0.0.1 for localhost to connect to an MQI server that runs on the same machine as the test process.

Running or debugging tests

To iterate more quickly, the recommended approach is to leave RunLocally set to false and run swipl mqi --port=12321 --password=12321 in the terminal matching the example settings above. You will need to download swipl or run a SWI-Prolog Docker container to do this. Setting RunLocally to true enables running the integration tests against a SWI-Prolog test container on the fly, which means you don't need to have SWI-Prolog installed locally, but this has some overhead and is considerably slower.

With the test settings configured, VS Code, Visual Studio and JetBrains Rider should be able to both run and debug tests.

For everything else, you can use the .NET CLI to run dotnet test at the root of the repo to just run the tests. To debug specific tests, set the environment variable VSTEST_HOST_DEBUG=1 and run dotnet test --filter <Expression>. The test host will pause on startup and print its process ID so that you can attach a .NET debugger (e.g. netcoredbg through your editor's DAP client) to that PID to continue. The filter expression lets you run selected unit tests; this repo uses xUnit.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 132 7/30/2026