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
<PackageReference Include="Prolog.NET.MQI" Version="1.0.0" />
<PackageVersion Include="Prolog.NET.MQI" Version="1.0.0" />
<PackageReference Include="Prolog.NET.MQI" />
paket add Prolog.NET.MQI --version 1.0.0
#r "nuget: Prolog.NET.MQI, 1.0.0"
#:package Prolog.NET.MQI@1.0.0
#addin nuget:?package=Prolog.NET.MQI&version=1.0.0
#tool nuget:?package=Prolog.NET.MQI&version=1.0.0
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 | Versions 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. |
-
net10.0
-
net8.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.8)
- System.IO.Pipelines (>= 9.0.0)
- System.Text.Json (>= 9.0.0)
-
net9.0
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 |