Recursive AI

Inspect a server from the command line

OneModelContext is a free, open-source .NET SDK for the Model Context Protocol® from Recursive AI. MIT or Apache-2.0, no native dependencies.

List a Model Context Protocol® (MCP) server’s tools from your terminal, without a model.

Unzip the example first: it includes the local tool manifest. In its folder:

Terminal
dotnet tool install RecursiveAI.OneModelContext.Cli --local
# Needed only to build the example server:
dotnet add package RecursiveAI.OneModelContext

Requires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.

Terminal
dotnet build --nologo
dotnet tool run onemodelcontext inspect \
  "dotnet run --no-build -- --stdio"

Run those commands in the example folder shown below. After the build, inspection prints:

Text
server: Example 1.0.0
protocol: 2026-07-28 (modern era)
era chosen: the server answered server/discover
capabilities: tools (listChanged), logging
tools (1):
  add - Add two integers.

“Modern era” means the connection uses protocol revision 2026-07-28. “Era chosen” explains how the CLI selected it: here the server answered server/discover.

Unzip the example, then dotnet run.

The full program

The download contains a calculator server in the same executable, plus dotnet-tools.json pinning the CLI. dotnet run restores that local tool, starts the child server and runs inspect. The server’s only tool is add, accepting integer arguments a and b; its complete definition is below.

If the server command fails or cannot negotiate a revision, the CLI writes an error to standard error and returns a nonzero exit code. The wrapper program throws if a command returns nonzero.

C#
using RecursiveAI.OneModelContext;
using System.Diagnostics;
using System.Reflection;
 
if (args.Contains("--stdio"))
{
    await ModelContext.ServeAsync(new Calculator());
    return;
}
await Run("tool", "restore");
var assembly = Assembly.GetExecutingAssembly().Location;
await Run("tool", "run", "onemodelcontext", "inspect", $"dotnet \"{assembly}\" --stdio");
 
static async Task Run(params string[] arguments)
{
    var start = new ProcessStartInfo("dotnet") { RedirectStandardOutput = true };
    foreach (var argument in arguments) start.ArgumentList.Add(argument);
    using var process = Process.Start(start)!;
    var output = await process.StandardOutput.ReadToEndAsync();
    await process.WaitForExitAsync();
    if (process.ExitCode != 0) throw new Exception("Command failed.");
    if (arguments.Contains("inspect") || arguments.Contains("call")) Console.Write(output);
}
public partial class Calculator
{
    /// <summary>Add two integers.</summary>
    [Tool]
    public int Add(int a, int b) => a + b;
}

dotnet run prints:

Text
server: Example 1.0.0
protocol: 2026-07-28 (modern era)
era chosen: the server answered server/discover
capabilities: tools (listChanged), logging
tools (1):
  add - Add two integers.

Variations

Call the calculator instead of inspecting it. In the example folder, after building:

Terminal
dotnet tool run onemodelcontext call \
  "dotnet run --no-build -- --stdio" add \
  --arg a=2 --arg b=40
Text
42

Inspect an HTTP endpoint

Set SERVER_URL to your Streamable HTTP server’s endpoint (for example, https://example.com/context), then run:

Terminal
dotnet tool run onemodelcontext inspect "$SERVER_URL"

The listing depends on your server. With the example calculator exposed over HTTP, the command prints the same listing shown above.

Inspect a non-.NET stdio server

The server process does not need to use .NET. With Python 3 installed, inspect the included server.py:

Terminal
dotnet tool run onemodelcontext inspect "python3 -u server.py"
Text
server: PythonExample 1.0
protocol: 2025-03-26 (legacy era)
era chosen: the server does not speak the modern era (no server/discover answer), so the client used initialize
capabilities: tools
tools (0):

This minimal Python server supports legacy initialization and advertises an empty tool list. Its complete server.py is:

PYTHON
import json
import sys
 
for line in sys.stdin:
    request = json.loads(line)
    if "id" not in request:
        continue
    method = request["method"]
    if method == "initialize":
        result = {
            "protocolVersion": "2025-03-26",
            "serverInfo": {"name": "PythonExample", "version": "1.0"},
            "capabilities": {"tools": {}},
        }
    elif method == "tools/list":
        result = {"tools": []}
    else:
        print(json.dumps({
            "jsonrpc": "2.0", "id": request["id"],
            "error": {"code": -32601, "message": "Method not found"},
        }), flush=True)
        continue
    print(json.dumps({
        "jsonrpc": "2.0", "id": request["id"], "result": result,
    }), flush=True)

The pinned CliApp.cs documents both forms:

<server> is a command line ("npx -y some-server"), an http(s) URL, or a name in the config file.


The short answer

For an MCP inspector CLI workflow (Model Context Protocol®) in .NET, the onemodelcontext inspect command connects to a server and lists its identity, negotiated revision, capabilities and available tools. onemodelcontext call invokes one of those tools. This page uses OneModelContext’s CLI, not a browser interface.

The example is self-contained: its calculator server starts as a child process and communicates over stdio. There is no external endpoint to configure and no model service involved. Use it to check the full path from starting a server to discovering and invoking an operation.

How do I run an inspector command?

Install RecursiveAI.OneModelContext.Cli as a local .NET tool. The download already includes a tool manifest, so dotnet tool restore installs its pinned version. In a new folder without a manifest, create one with dotnet new tool-manifest before installing the tool if your SDK doesn’t create it automatically.

Pass the complete server command as one quoted argument to inspect. In the snippet at the top, dotnet run --no-build -- --stdio starts the example’s server branch. The preceding build is essential: the child process uses the existing assembly rather than compiling while the client waits for a protocol response.

The printed revision is what the connection actually selected, not just the latest revision the package knows. “Modern era” means the server answered the modern discovery path. The capabilities describe supported categories; the tools listing describes callable operations. A successful inspection confirms connection and discovery, not that every tool has been exercised.

The CLI also accepts HTTP endpoints and configured server names. Its complete command syntax is in the pinned CLI source. The process example here avoids relying on a running remote service.

What is a Model Context Protocol® inspector?

An inspector is a client used to examine a server’s advertised interface. That interface includes names, descriptions and input schemas. It is useful before wiring the server into a larger application: you can tell whether a missing tool is a discovery problem or an invocation problem.

The variation calls add with two arguments and prints 42. --arg pairs are interpreted using the tool’s input schema, so integer properties become JSON numbers rather than strings. Use the exact argument names the tool publishes; the calculator requires a and b. The tool’s description does not replace its input schema.

For a stdio server, keep diagnostics off standard output. The child process and the CLI exchange protocol messages on that stream. Ordinary application logging there can prevent negotiation or corrupt a later response. The full example prints results only in its parent branch.

Is the inspector free?

OneModelContext’s CLI is distributed under MIT OR Apache-2.0, like its core package. It runs locally through the .NET tool system; this example needs neither a paid service nor a model API key. Installing and restoring the tool still requires access to the package feed, and connecting to your own protected server may require that server’s credentials. The included calculator requires none.

All onemodelcontext recipes