tools.mcpo_proxy_tools module

Tools to install, configure, enumerate, document, and call MCP servers via mcpo (OpenAPI HTTP).

URLs are built only from configured mcpo.base_url plus validated path segments (not arbitrary user URLs), so loopback/private targets are allowed.

async tools.mcpo_proxy_tools.handle_install_runtime(package_spec='mcpo>=0.0.20', ctx=None)[source]

Install or upgrade the mcpo PyPI package into this Python environment.

Backs the mcpo_install_runtime tool. Intended for dev use without Docker (production runs mcpo as a Compose service). Gates on the UNSANDBOXED_EXEC privilege and a Python 3.11+ interpreter, then shells out to pip install.

Interacts with _require_unsandboxed() for the privilege gate and runs {sys.executable} -m pip install <package_spec> via subprocess.run on a worker thread (asyncio.to_thread) with a 600s timeout — a real side effect that mutates the local environment. After install it reads the resolved version through importlib.metadata.version("mcpo"). No Redis/KG/event-bus interaction.

Called indirectly by the tool registry (registered in TOOLS as mcpo_install_runtime and dispatched by tool_loader.py); also called directly in tests/test_mcpo_proxy_tools.py.

Parameters:
  • package_spec (str) – A pip requirement string (default "mcpo>=0.0.20").

  • ctx (ToolContext | None) – The tool invocation context, used for the privilege check.

Returns:

A JSON string. On the privilege/version gates, an error payload; otherwise {"ok", "exit_code", "mcpo_version", "stdout_tail", "stderr_tail"} (output tails capped at 4000 chars). pip timeout or failure yields {"error": "pip_timeout"} / {"error": "pip_failed"}.

Return type:

str

async tools.mcpo_proxy_tools.handle_upsert_server(server_name, server_config_json, ctx=None)[source]

Add or replace one server entry in the Claude-style mcpo JSON config.

Backs the mcpo_upsert_server tool. Parses server_config_json (a JSON object describing a single MCP server, e.g. command/args for stdio or type/url/headers for sse/streamable-http) and writes it under the mcpServers map in the on-disk mcpo config, creating the file if needed.

Gated by _require_unsandboxed() (UNSANDBOXED_EXEC); reads config via _require_cfg() and validates server_name against _SERVER_RE. The side effect is filesystem: it creates cfg.mcpo_config_path (and parent dirs), merges the new entry into any existing mcpServers, and rewrites the file as pretty-printed JSON. That path is bind-mounted into the mcpo Docker container, so with --hot-reload the change applies without a restart. No Redis/KG/event-bus writes.

Called indirectly through the tool registry (mcpo_upsert_server in TOOLS); also exercised directly by tests/test_mcpo_proxy_tools.py.

Parameters:
  • server_name (str) – Mount/route segment (validated by _SERVER_RE).

  • server_config_json (str) – JSON object string for this one server’s config.

  • ctx (ToolContext | None) – The tool invocation context (privilege check and config source).

Returns:

A JSON string — {"ok": True, "path", "server", "hint"} on success, or an error payload (forbidden, no_config, invalid_server_name, invalid_json, server_config_must_be_object, or existing_config_invalid_json).

Return type:

str

async tools.mcpo_proxy_tools.handle_remove_server(server_name, ctx=None)[source]

Remove one named server from the mcpo JSON config.

Backs the mcpo_remove_server tool. Loads the on-disk mcpo config, deletes the named entry from its mcpServers map, and rewrites the file. With Docker --hot-reload, mcpo drops the corresponding mount automatically.

Gated by _require_unsandboxed() (UNSANDBOXED_EXEC); config comes from _require_cfg() and the name is validated against _SERVER_RE. The side effect is filesystem: it reads and rewrites cfg.mcpo_config_path as pretty-printed JSON. No Redis/KG/event-bus writes.

Called indirectly via the tool registry (mcpo_remove_server in TOOLS); also called directly in tests/test_mcpo_proxy_tools.py.

Parameters:
  • server_name (str) – The mount name to remove (validated by _SERVER_RE).

  • ctx (ToolContext | None) – The tool invocation context (privilege check and config source).

Returns:

A JSON string — {"ok": True, "removed", "path", "hint"} on success, or an error/ok: False payload (forbidden, no_config, invalid_server_name, config_missing, config_invalid_json, no_mcp_servers_in_config, or server_not_found).

Return type:

str

async tools.mcpo_proxy_tools.handle_list_servers(probe_openapi=True, ctx=None)[source]

List MCP server names from the mcpo config, optionally probing OpenAPI.

Backs the mcpo_list_servers tool. Reads the mcpServers keys from the on-disk mcpo config and returns them sorted. When probe_openapi is true and a base URL is configured, it additionally GETs each server’s openapi.json to report its API title/version and HTTP status.

Reads cfg.mcpo_config_path (via _require_cfg()) and resolves the base URL with _mcpo_base(). The OpenAPI probe issues authenticated HTTP GETs (headers from _auth_headers(), URLs from _server_url()) through httpx.AsyncClient with a 15s/5s connect timeout; per-server failures are captured as openapi_error rather than raised. No Redis/KG/event-bus interaction.

Called indirectly via the tool registry (mcpo_list_servers in TOOLS); no direct internal callers outside the test suite.

Parameters:
  • probe_openapi (bool) – When True (default), fetch each server’s openapi.json for title/version metadata.

  • ctx (ToolContext | None) – The tool invocation context (config source).

Returns:

A JSON string with mcpo_base_url, config_path, and a servers list (names plus optional openapi_status/api_title/ api_version/openapi_error); or an error payload (no_config / config_invalid_json), or a note when the config file is missing.

Return type:

str

async tools.mcpo_proxy_tools.handle_list_tools(server_name, include_schemas=True, max_total_chars=120000, max_schema_chars_per_tool=24000, ctx=None)[source]

List the tools exposed by one mcpo server, with their JSON Schemas.

Backs the mcpo_list_tools tool. Fetches the server’s openapi.json and derives one entry per POST path (the mcpo tool-call convention), each with its name, summary/description, and optionally the request and 200 response JSON Schemas. Applies a two-level character budget: per-tool schemas are capped via _truncate_value(), and if the whole payload still exceeds max_total_chars it drops schemas from the tail until it fits.

Resolves config/base URL via _require_cfg() / _mcpo_base(), builds the URL with _server_url(), and issues an authenticated httpx GET (headers from _auth_headers(), 30s/8s connect timeout). Schemas are extracted with _request_schema() and _response_schema_200(). The docs/openapi.json/redoc paths are skipped. No Redis/KG/event-bus interaction.

Called indirectly via the tool registry (mcpo_list_tools in TOOLS); also called directly in tests/test_mcpo_proxy_tools.py.

Parameters:
  • server_name (str) – The mcpo server whose tools to enumerate.

  • include_schemas (bool) – When True (default), include request and 200 response schemas per tool.

  • max_total_chars (int) – Soft budget (default 120000) across the whole payload; schemas are progressively dropped to stay under it.

  • max_schema_chars_per_tool (int) – Per-schema character cap (default 24000); the response schema is additionally capped at 8000.

  • ctx (ToolContext | None) – The tool invocation context (config source).

Returns:

A JSON string with server, a tools list, a truncated flag, and a hint_truncated message when anything was dropped; or an error payload (no_config, mcpo_base_url_not_configured, bad_request, http_error, openapi_fetch_failed, openapi_not_json, or no_paths_in_openapi).

Return type:

str

async tools.mcpo_proxy_tools.handle_get_tool_schema(server_name, tool_name, max_chars=200000, ctx=None)[source]

Fetch the full OpenAPI schema for one specific mcpo tool.

Backs the mcpo_get_tool_schema tool — the per-tool fallback when handle_list_tools() truncated. Fetches the server’s openapi.json, locates the operation matching tool_name (trying /tool_name, the URL-encoded variant, then the last path segment of each path), and returns its summary, description, request schema, and 200 response schema. If the serialized result exceeds max_chars it re-truncates the schemas (request at cap/2, response at cap/4) via _truncate_value().

Resolves config/base URL via _require_cfg() / _mcpo_base(), validates both names against _SERVER_RE / _TOOL_RE, builds the URL with _server_url(), and issues an authenticated httpx GET (headers from _auth_headers(), 30s/8s connect timeout). Schemas come from _request_schema() and _response_schema_200(). No Redis/KG/event-bus interaction.

Called indirectly via the tool registry (mcpo_get_tool_schema in TOOLS); no direct internal callers found.

Parameters:
  • server_name (str) – The mcpo server hosting the tool (validated).

  • tool_name (str) – The tool/operation to fetch (validated).

  • max_chars (int) – Approximate cap on the serialized output (default 200000; floored at 1000).

  • ctx (ToolContext | None) – The tool invocation context (config source).

Returns:

A JSON string with server, tool, summary, description, request_schema, response_schema_200 (and a truncated flag if shrunk); or an error payload (no_config, mcpo_base_url_not_configured, invalid_name, bad_request, http_error, openapi_fetch_failed, openapi_not_json, no_paths, tool_not_found, or no_post_for_tool).

Return type:

str

async tools.mcpo_proxy_tools.handle_call_tool(server_name, tool_name, arguments_json='{}', timeout_seconds=120.0, ctx=None)[source]

Invoke one MCP tool through mcpo via an HTTP POST with a JSON body.

Backs the mcpo_call_tool tool — the actual execution path. Parses arguments_json into the request body and POSTs it to the tool’s mcpo endpoint, returning the upstream status code and (parsed JSON or text-capped) body. This is powerful and unrestricted by design; callers should constrain it with tool permissions where appropriate.

Resolves config/base URL via _require_cfg() / _mcpo_base(), validates both names against _SERVER_RE / _TOOL_RE, builds the tool URL with _server_url(), and POSTs through httpx.AsyncClient with bearer auth from _auth_headers(), a JSON content type, and a caller-supplied total timeout (10s connect). Whatever side effects occur live in the downstream MCP server; this function itself does no Redis/KG/event-bus work.

Called indirectly via the tool registry (mcpo_call_tool in TOOLS); no direct internal callers found.

Parameters:
  • server_name (str) – The mcpo server hosting the tool (validated).

  • tool_name (str) – The tool/operation to invoke (validated).

  • arguments_json (str) – JSON object string of tool arguments (default "{}").

  • timeout_seconds (float) – Total HTTP timeout for the call (default 120.0).

  • ctx (ToolContext | None) – The tool invocation context (config source).

Returns:

A JSON string {"status_code", "body"} where body is the parsed JSON response or the raw text capped at 500000 chars; or an error payload (no_config, mcpo_base_url_not_configured, invalid_name, invalid_arguments_json, arguments_must_be_object, bad_request, or http_error).

Return type:

str