NAME
App::MCP::CLI::Command::interactive - Agent REPL that routes natural-language queries to MCP tools via a local LLM
VERSION
This module is distributed as part of App::MCP::CLI v0.0.1.
SYNOPSIS
# Start an interactive session against a named server in your config file
mcpcli interactive --server myserver
# Alias: the 'chat' sub-command is identical
mcpcli chat --server myserver
# Use a local Perl script as the server with a custom model
mcpcli interactive --server ./server.pl --model llama3
# Point at an SSE server by URL
mcpcli interactive --server http://localhost:8080/sse
# Override every option explicitly
mcpcli interactive \
--server myserver \
--provider ollama \
--model qwen2.5:1.5b \
--config /etc/mcp/config.json
DESCRIPTION
App::MCP::CLI::Command::interactive implements the interactive (alias chat) sub-command of the mcpcli application. It starts a Read-Eval-Print Loop (REPL) that:
Connects to the MCP server specified by
--server(either as a stdio subprocess or via HTTP/SSE).Retrieves the full tool catalogue from the server with
tools/list.Enters a prompt loop where each user message is forwarded to a local LLM (currently only Ollama is supported) together with the tool catalogue and a structured JSON dispatch schema.
If the LLM decides to invoke a tool (
action: "call_tool"), the command optionally asks the user for confirmation before executing thetools/callrequest and summarising the raw result via a second LLM call.If no tool is needed (
action: "reply"), the LLM's plain-text answer is printed directly.
Type exit or quit (case-insensitive) at the prompt to end the session.
TRANSPORT MODES
stdio (default)
The server is launched as a child process via IPC::Open2. Messages are exchanged as newline-delimited JSON on its stdin/stdout. This is the simplest mode and works with any compliant MCP server script.
HTTP/SSE
When the resolved server endpoint begins with http:// or https://, or when the config entry contains a url key, the client connects in SSE mode. It opens the event stream with a GET request, reads the endpoint event to learn the POST URL, then sends all JSON-RPC messages as POST requests to that URL. Responses are accepted either in the POST reply body or as message events on the stream. See App::MCP::CLI::Client.
CONFIGURATION FILE
The command accepts a JSON configuration file (--config) with the following optional top-level keys:
mcpServers(object)-
A map of server alias names to server descriptor objects. Each descriptor may contain:
command(string) - executable to launch (stdio mode).args(array of strings) - additional arguments for the executable.env(object) - environment variables for the launched server only.url(string) - SSE endpoint URL (SSE mode).transport(string) - informational ("stdio"or"sse"); a server is SSE when it has aurl."sse"without aurlis an error.
confirmTools(boolean, default true)-
When true, the agent pauses before executing any tool call and asks the user for explicit confirmation. Set to
falseto allow autonomous execution.
The configuration file is searched in the following order when --config is not given:
- 1.
./server_config.jsonin the current directory. - 2.
./mcp-config.jsonin the current directory. - 3.
$HOME/.config/mcp-cli/config.json.
Example configuration:
{
"confirmTools": true,
"mcpServers": {
"myserver": {
"command": "node",
"args": ["/opt/mcp/server.js"],
"env": { "DEBUG": "1" }
},
"remote": {
"url": "http://mcp.example.com/sse"
}
}
}
OPTIONS
--server|-sname_or_path-
The MCP server to connect to (optional when the config file defines exactly one server). Can be:
A key in the
mcpServerssection of the config file.A
.plfile path (launched with the current Perl interpreter).An
http://orhttps://URL (SSE mode).A bare shell command string (split on whitespace).
--provider|-pname (default:ollama)-
The LLM provider to use for query routing and result summarisation. Only
ollamais currently supported. --model|-mname (default:qwen2.5:1.5b)-
The Ollama model tag to query. Any model available on the Ollama instance (http://localhost:11434 unless
OLLAMA_HOSTis set) can be specified. --config|-cpath-
Path to a JSON configuration file. See "CONFIGURATION FILE" above.
--timeout|-tseconds-
How long to wait for each MCP server reply (default 30;
0waits forever).
INTERNAL METHODS
command_names
Returns qw(interactive chat) so that the sub-command can be invoked by either name.
opt_spec
Defines the command-line option specification passed to Getopt::Long::Descriptive via App::Cmd.
execute( $opt, $args )
Main entry point. Resolves the server, connects to it, retrieves tools, and runs the agent REPL until the user types exit/quit or sends EOF.
The model's decision is validated before anything is executed: it must be a JSON object, and a requested tool must exist on the server (otherwise the request is ignored with a message). Tool failures (transport errors, JSON-RPC errors, or results flagged isError) are reported and the session continues.
_ollama_url
Returns the Ollama /api/generate URL. The base address defaults to http://localhost:11434 and can be changed with the OLLAMA_HOST environment variable (with or without the http:// prefix).
_ask_llm( $query, $tools )
Sends $query together with the serialised $tools array to the Ollama /api/generate endpoint. The system prompt instructs the model to respond with a bare JSON object in one of two forms:
{ "action": "call_tool", "tool": "<name>", "arguments": { ... } }
{ "action": "reply", "answer": "<text>" }
Returns the decoded hashref. If the model's output is not a JSON object, or the request fails, a synthetic reply hashref describing the problem (or containing the raw text) is returned instead.
_summarize_with_llm( $query, $result )
Sends the original $query and the raw tool $result text to Ollama and asks for a concise natural-language summary. Returns the summary string, or the raw $result on failure.
DEPENDENCIES
In addition to the core App::MCP::CLI dependencies, this command requires:
HTTP::Tiny - for Ollama API calls and SSE transport.
A running Ollama instance on http://localhost:11434 is required for the LLM routing functionality.
SEE ALSO
AUTHOR
Mohammad Sajid Anwar, <mohammad.anwar at yahoo.com>
REPOSITORY
https://github.com/manwar/App-MCP-CLI
BUGS
Please report any bugs or feature requests through the web interface at https://github.com/manwar/App-MCP-CLI/issues. I will be notified and then you'll automatically be notified of progress on your bug as I make changes.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc App::MCP::CLI
You can also look for information at:
BUG Report
Search MetaCPAN
LICENSE AND COPYRIGHT
Copyright (C) 2026 Mohammad Sajid Anwar.
This program is free software; you can redistribute it and / or modify it under the terms of the the Artistic License (2.0). You may obtain a copy of the full license at:
http://www.perlfoundation.org/artistic_license_2_0
Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License.By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.
If your Modified Version has been derived from a Modified Version made by someone other than you,you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.
This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.
This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement,then this Artistic License to you shall terminate on the date that such litigation is filed.
Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.