Skip to content

Recipe: The Launcher with Other MCP Clients

Goal

Register the composed launcher, python -m doc_processing_std_tools, with MCP clients other than the toolkit: a desktop assistant, an IDE, or your own code using an MCP SDK. Pass it the configuration it needs, and check the connection.

Prerequisites

  • std-tools installed with the extras you need, in its own virtual environment, so the client runs a known interpreter:

    python -m venv /opt/std-tools
    /opt/std-tools/bin/pip install "doc-processing-std-tools[all] @ git+https://github.com/rzoeb/doc-processing-std-tools.git@v0.6.1"
    

    On Windows the interpreter is C:\opt\std-tools\Scripts\python.exe.

  • Any software the tools use, installed where the server runs: LibreOffice for Office conversion, and Chromium (playwright install chromium) if you enable the browser.

Steps

1. Decide what the server needs

A client starts a stdio server with only the environment you give it. Most clients pass a short allow-list such as PATH and HOME, and nothing from your shell. So write every setting into the client's configuration:

Setting Why
DPTTOOLS_MEMORY_DIR, DPTTOOLS_SKILLS_DIR Their defaults are relative (./agent_memory, ./.agent_skills), and a client chooses the working directory. Use absolute paths
DPTTOOLS_WEB_SEARCH_PROVIDER, DPTTOOLS_WEB_SEARCH_API_KEY web_search returns an error without them
LLMWHISPERER_API_KEY For ocr_pdf and ocr_image
DPTTOOLS_ENABLE_BROWSER, DPTTOOLS_ENABLE_COMPUTER Only if you want the optional servers

The file tools also resolve a relative path against the server's working directory. Give absolute paths in prompts, or use a client that lets you set the working directory (cwd). Configuration lists every variable.

2. Register it with the client

JSON configuration with mcpServers (Claude Desktop's claude_desktop_config.json, and many other clients):

{
  "mcpServers": {
    "std-tools": {
      "command": "/opt/std-tools/bin/python",
      "args": ["-m", "doc_processing_std_tools"],
      "env": {
        "DPTTOOLS_MEMORY_DIR": "/home/me/agent/memory",
        "DPTTOOLS_SKILLS_DIR": "/home/me/agent/skills",
        "DPTTOOLS_WEB_SEARCH_PROVIDER": "tavily",
        "DPTTOOLS_WEB_SEARCH_API_KEY": "tvly-xxx"
      }
    }
  }
}

In JSON on Windows, write paths with forward slashes (C:/opt/std-tools/Scripts/python.exe) or doubled backslashes.

Claude Code, from the command line:

claude mcp add std-tools \
  -e DPTTOOLS_MEMORY_DIR=/home/me/agent/memory \
  -e DPTTOOLS_WEB_SEARCH_PROVIDER=tavily -e DPTTOOLS_WEB_SEARCH_API_KEY=tvly-xxx \
  -- /opt/std-tools/bin/python -m doc_processing_std_tools

VS Code (.vscode/mcp.json) can prompt for a key instead of storing it in the file, and can set the working directory:

{
  "inputs": [
    {"type": "promptString", "id": "tavily-key", "description": "Tavily API key", "password": true}
  ],
  "servers": {
    "std-tools": {
      "type": "stdio",
      "command": "/opt/std-tools/bin/python",
      "args": ["-m", "doc_processing_std_tools"],
      "cwd": "${workspaceFolder}",
      "env": {
        "DPTTOOLS_WEB_SEARCH_PROVIDER": "tavily",
        "DPTTOOLS_WEB_SEARCH_API_KEY": "${input:tavily-key}"
      }
    }
  }
}

Each client's own documentation has the details: where its file lives, and how it handles secrets.

3. Or serve it over HTTP

For a client that connects to a URL, or several clients sharing one server, run the launcher with streamable HTTP. It reads its configuration from its own environment, since no client passes one:

export DPTTOOLS_MEMORY_DIR=/home/me/agent/memory
python -m doc_processing_std_tools --transport http --port 8000

The endpoint is http://127.0.0.1:8000/mcp. For Claude Code: claude mcp add --transport http std-tools http://127.0.0.1:8000/mcp.

The HTTP transport has no authentication

It binds to 127.0.0.1 by default. Anyone who can reach the port can run every tool, including execute_command. Bind another interface (--host 0.0.0.0) only behind an authenticating proxy or a network policy (Architecture).

4. Check the connection

The launcher checks its settings before serving. A bad value stops it with a message naming the variable, which the client shows as a server that failed to start:

doc-processing-std-tools failed to start: ConfigError: DPTTOOLS_SANDBOX_TIMEOUT must be an integer (got 'soon').

Once it is connected, the client should list 56 tools, or 75 with the browser, 73 with the computer server and 92 with both. A short script with the MCP Python SDK checks the same thing without a client:

import asyncio

from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import get_default_environment, stdio_client

async def main():
    env = get_default_environment()
    env["DPTTOOLS_MEMORY_DIR"] = "/home/me/agent/memory"
    params = StdioServerParameters(
        command="/opt/std-tools/bin/python", args=["-m", "doc_processing_std_tools"], env=env
    )
    async with stdio_client(params) as (read, write), ClientSession(read, write) as session:
        await session.initialize()
        print(len((await session.list_tools()).tools))                  # 56
        result = await session.call_tool("write_memory", {"key": "report-folder",
                                                          "value": "Reports go to /finance."})
        print(result.content[0].text)                                    # Memory key 'report-folder' saved.

asyncio.run(main())

For HTTP, use streamablehttp_client("http://127.0.0.1:8000/mcp") from mcp.client.streamable_http in the same way. The MCP Inspector (npx @modelcontextprotocol/inspector) does the same check interactively.

5. Keep the tool list small

56 tool descriptions cost tokens on every turn, and some clients limit how many tools they show. To serve fewer tools, run one server on its own:

python -m doc_processing_std_tools.document_processing     # the 13 Documents tools
python -m doc_processing_std_tools.file_system

A server run this way skips the launcher's start-up check, so a bad setting shows up as an Error: from the first tool that reads it. Many clients can also hide tools you don't use.

What to validate

  • The client lists 56 tools (more with the optional servers), with names unchanged and not prefixed.
  • A memory written through one connection is in DPTTOOLS_MEMORY_DIR, at the absolute path you set.
  • web_search works; without the provider settings in the client's env, it returns an Error: naming them.
  • A bad setting stops the launcher with a message naming the variable.
  • Over HTTP, the server answers at /mcp on 127.0.0.1 only.

Test sources

  • tests/integration/test_multi_server_launcher.py: composition, the 56-tool count, no duplicate names, a call through each server, settings passed through.
  • tests/unit/test_launcher_offload.py: blocking tools run on worker threads in the launcher.
  • tests/integration/test_toolkit_compat.py: a stdio session started with env, as in step 4.