Testing your MCP server with LocalLM Lab

An independent client, a range of models, and a wire-level view

If you're building an MCP server, you want to test it against a client that isn't the one you developed against. LocalLM Lab is a free, native macOS app with a full Model Context Protocol 2025-11-25 client — a fourth independent implementation alongside Claude Desktop, Cursor, and the MCP Inspector — and it lets you drive your server with several very different models to see how each one actually handles your tools.

The next protocol revision (2026-07-28) is already on our roadmap. If you're building a server against that revision now, we'd like to hear from you — get in touch.

Why a second client matters

↑ Top

The test loop

  1. Connect. MCP Servers panel → Add Server → your URL. Auth type None covers no-auth and any OAuth server (the client discovers the challenge and runs the flow — OAuth 2.1 + PKCE, DCR, CIMD). Use Personal Access Token or OAuth (manual client) for the servers that need them.
  2. Enable a tool or two. Every tool starts disabled. The context-budget line shows the running token cost — a useful number on its own.
  3. Pick a model in AI Models, write a prompt that should exercise the tool, and Run. Each tool call and its result show inline.
  4. Switch models and run the same prompt again. Save the setup as a Configuration Profile so you can flip between tool combinations while you compare.
  5. Read the wire. See Diagnostics below.
↑ Top

Seeing the protocol traffic

The MCP client logs every decision and failure to Apple's unified logging system — no setting to turn on. To see the full JSON-RPC exchange, including each SSE frame, run this in Terminal while you drive the app:

log stream --predicate 'subsystem == "ai.thisbrain.locallmlab.sdkcore" AND category BEGINSWITH "MCP"' --level debug

The four categories are MCP.connection (negotiation, HTTP, auth challenges), MCP.manager (add-server outcomes, and any tool result whose structuredContent fails its own outputSchema), MCP.oauth (the whole flow, step by step), and MCP.stream (each SSE frame as it's classified). Access and refresh tokens, auth codes, and client secrets are never written.

For a report you can paste into an issue, use MCP Servers panel → Copy Diagnostics — a redacted trace of recent connect / negotiate / authorize activity. Turn the detail all the way up first, without rebuilding anything:

defaults write ai.thisbrain.locallmlab.chooser MCPLogLevel debug   # then relaunch

Save As… on a connected server exports its full tool / resource / prompt list, with each tool's token cost, to a text file.

↑ Top

Scripting test runs

For a batch of prompts against your server — does the model pick the right tool? call it with valid arguments? recover from an error? — localai-cli is usually the better fit than API Lab: no HTTP layer, and each request names the exact {server, tool} pair to activate via mcp_tools, so a script can loop over tools and models without touching the app's UI between runs (the server still has to be added once in MCP Servers first).

import json, os, subprocess

CLI_PATH = os.environ.get("LOCALAI_CLI_PATH", "./localai-cli")
CONFIG_PATH = os.path.expanduser(
    "~/Library/Application Support/LocalLM Lab/localai-config.json"
)

request = {
    "system_prompt": "You are a concise assistant. Use the available tool to answer.",
    "user_input": "What documentation topics are available for nickclyde/duckduckgo-mcp-server?",
    "mcp_tools": [{"server": "https://mcp.deepwiki.com/mcp", "tool": "read_wiki_structure"}],
}

result = subprocess.run(
    [CLI_PATH, "--config", CONFIG_PATH, "--run"],
    input=json.dumps(request), capture_output=True, text=True,
)
response = json.loads(result.stdout)
print(response.get("error") or response.get("answer"))

Loop that over a list of prompts — and models, and {server, tool} pairs — for a batch pass; each call is independent, so a thread pool works fine too. Swap --run for --chat if you want to send an OpenAI-style messages array instead. Full CLI reference →

API Lab is the other option, useful when your harness is already written against an OpenAI SDK or you'd rather drive it from curl: it exposes the model — with your enabled MCP tools — over a local OpenAI-compatible /v1/chat/completions endpoint. The model is whatever's set in AI Models, the tools are what's enabled in the panel, and the assistant's text reply comes back — the individual tool calls are in the log stream output above, not the HTTP response.

To call a tool with exact arguments and no model in the loop at all, use the MCP Inspector — that's what it's for. A first-class "call this tool with this JSON" action inside LocalLM Lab, and an in-app protocol-log panel, are planned for a later release.

↑ Top

What this covers, and what it doesn't

LocalLM Lab exercises, against your server:

It is not a substitute for the MCP Inspector: there's no in-app raw-request editor or JSON tree view yet (use log stream), and no hand-crafted tools/call — the Inspector is still the tool for calling a tool with exact arguments and no model. LocalLM Lab also doesn't act as a sampling provider, and connects over remote Streamable HTTP only, not stdio. What it adds that the Inspector can't: a real model — several of them — actually deciding to call your tools.

↑ Top

Next

↑ Top

Contact

Building an MCP server and want to compare notes? neuron@thisbrain.ai or our Discord.

↑ Top