The Machine Query Interface is designed to act like using the "top 
level" prompt of SWI Prolog itself (i.e. the "?-" 
prompt). If you've built the Prolog part of your application by loading 
code, running it and debugging it using the normal SWI Prolog top level, 
integrating it with your native language should be straightforward: 
simply run the commands you'd normally run on the top level, but now run 
them using the query APIs provided by the library built for your target 
language. Those APIs will allow you to send the exact same text to 
Prolog and they should execute the same way. Here's an example using the 
Python swiplserver library:
% Prolog Top Level ?- member(X, [first, second, third]). X = first ; X = second ; X = third.
# Python using the swiplserver library
from swiplserver import PrologMQI, PrologThread
with PrologMQI() as mqi:
    with mqi.create_thread() as prolog_thread:
        result = prolog_thread.query("member(X, [first, second, third]).")
        print(result)
first
second
third
While the query functionality of the MQI does run on a thread, it will always be the same thread, and, if you use a single connection, it will only allow queries to be run one at a time, just like the top level. Of course, the queries you send can launch threads, just like the top level, so you are not limited to a single threaded application. There are a few differences from the top level, however:
user_input are initially bound 
to the standard operating system I/O streams (like STDIN) and, since the 
Prolog process is running invisibly, will obviously not work as 
expected. Those streams can be changed, however, by issuing commands 
using system predicates as defined in the SWI Prolog documentation.$residuals that 
is added to the results.s(CASP) 
has a model and justification.A basic rule to remember is: any predicates designed to interact with or change the default behavior of the top level itself probably won't have any effect.