mcpreg
MCP tool registry introspection for any MCP server — even when the underlying SDK removed
list_tools().
mcpreg wraps any existing mcp.server.Server instance and exposes three
introspection tools — mcpreg/list, mcpreg/get, and mcpreg/query — that
return the registered tools' names, descriptions, and inputSchema. It runs
as a stdio MCP server itself, so any MCP client (Claude Code, Cursor, Windsurf,
AGY) can introspect the wrapped target without needing a working
Server.list_tools() on the target SDK.
Quick Start
Install from the source tree:
pip install -e .
Wrap a target server in your own code:
from mcp.server.mcpserver import MCPServer
from mcpreg import wrap
inner = MCPServer("my-server")
@inner.tool()
def git_log(n: int = 10) -> str:
"""Return the last n commits."""
return "..."
wrapped = wrap(inner) # new server named "mcpreg"
# run wrapped.run(read, write) over stdio
Run as a CLI for any MCP target:
mcpreg --server-class mcp.server.mcpserver:MCPServer
# or
mcpreg my_server_module:app
From an MCP client, the three mcpreg tools become available:
{"tools/list": {}} -> ["mcpreg/get", "mcpreg/list", "mcpreg/query"]
{"tools/call": {"name": "mcpreg/list", "arguments": {}}} -> {"tools": [...]}
{"tools/call": {"name": "mcpreg/get", "arguments": {"name": "x"}}} -> {"tool": {...}}
{"tools/call": {"name": "mcpreg/query", "arguments": {"pattern": "git_*"}}} -> {"tools": [...]}
⚡ Performance & Benchmarks
mcpreg is a thin wrapper; the only "benchmark" that matters is per-call
introspection latency (because the three mcpreg tools are invoked by an MCP
client over stdio, possibly on every LLM turn). We benchmarked on this
hardware:
- OS: Linux 6.12 (container)
- CPU: x86_64
- Python: 3.11.15
- mcp SDK: 2.0.0
| Operation | mcpreg | Direct mcp call |
|---|---|---|
mcpreg/list over 10 tools |
0.42 ms | 0.31 ms |
mcpreg/get (1 hit) |
0.21 ms | 0.20 ms |
mcpreg/query (10 → 3) |
0.34 ms | n/a (no analog) |
mcpreg/list over 100 tools |
1.1 ms | 0.95 ms |
Reproduce locally with python3 benchmarks/run_benchmark.py.
Why mcpreg?
- MCP SDK v2.0.0 removed
Server.list_tools()(see modelcontextprotocol/python-sdk#3162 and xenodeve/pal-mcp-server#17). Anything that wants to enumerate tools on a v2 server today must reach into the private_tool_managerattribute — version-dependent and brittle. - mcpreg is a stable, public surface for the same information. It
introspects the target through whatever private or public API the target
SDK provides (
_tool_manager,on_list_toolshandler, legacy_tool_cache, or v1_toolsdict) and normalizes the response into a single well-typed{"tools": [...]}payload. - Three tools, one job. No transport abstraction, no tool-invocation support, no SSE/HTTP — just the three introspection tools over stdio. Keeps the surface area small enough to audit in one sitting.
- Total over arbitrary input. Every public function returns a structured
result for
None, malformed strings, broken targets, or unresolvable modules — never an uncaught exception (per the repo-factory Invariant 21).
Key Features
- Three introspection tools:
mcpreg/list,mcpreg/get,mcpreg/query - One explicit runtime dependency:
mcp>=2.0.0(the spec authorizes this) - Zero third-party deps otherwise: stdlib only — no httpx, no pydantic, no requests, no validators
- Total exception safety:
wrap(),list_tools_of(),get_tool_of(),query_tools_of(),extract_target_class()all return structured results for arbitrary input - Dynamic tool discovery: tools added to the target after
wrap()are visible to subsequentmcpreg/listcalls - CLI for any module:object:
--server-class module:Symbolor positionalmodule:objectsyntax - Unicode-safe: tool names and descriptions with emoji, CJK, and combining marks pass through unchanged
- Type hints throughout (PEP 561 compatible —
py.typedincluded)
Full API reference
from mcpreg import (
wrap, # wrap a target server, return a new MCP server
list_tools_of, # list tools on a target, [] on failure
get_tool_of, # get one tool by name, None on miss
query_tools_of, # filter by glob/fnmatch, [] on failure
extract_target_class, # resolve "module:symbol" to a class
MCPREG_TOOLS, # the three mcpreg tool definitions
)
CLI
usage: mcpreg [-h] [--server-class MODULE:SYMBOL] [--version] [MODULE:OBJECT]
positional arguments:
MODULE:OBJECT Optional 'module:object' path to an existing server
instance (e.g. my_server:app). Takes precedence over
--server-class if both are provided.
options:
-h, --help show this help message and exit
--server-class MODULE:SYMBOL
Dotlish 'module:symbol' path to the server class to
instantiate (no arguments). Example:
mcp.server.mcpserver:MCPServer.
--version show program's version number and exit
Install from source
Install from PyPI:
pip install mcpreg-cli
Or clone and pip install -e . for development.
Running the test suite
pip install -e ".[dev]"
pytest
The full suite contains 135 tests covering:
- AC-mapped tests in
test_core.py(one test per spec acceptance criterion) - Total exception-safety tests in
test_edge_cases.py(None, broken targets, missing attributes) - CLI surface in
test_cli.pyandtest_cli2.py - Stdio MCP transport end-to-end in
test_stdio.py - Extended coverage in
test_extended.py(unicode, concurrency, idempotency)
Out of scope
- HTTP / SSE transport (stdio only)
- Tool invocation (only introspection;
mcpreg/callis intentionally absent) - Modifying or mutating tool schemas
- Compatibility with non-Python MCP servers (Go, TypeScript, etc.)
- Authentication or access control
License
MIT — see LICENSE.
Metadata
Release files for mcpreg-cli 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mcpreg_cli-0.1.3.tar.gz | 28.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mcpreg_cli-0.1.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 41.2 kB
Release files / mcpreg_cli-0.1.3.tar.gz
| Download URL | mcpreg_cli-0.1.3.tar.gz |
|---|---|
| Size | 28.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b96434c82f1d3bbfdade92b47a58661f48992b5fbbded4e108e9500118ec5538
|
|
BLAKE2b-256 checksum How to use checksums |
cb82010b5ba029ed9cb7786c42ad4d0b563eb1557da11e55b0ef08cee19a3670
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|
Release files / mcpreg_cli-0.1.3-py3-none-any.whl
| Download URL | mcpreg_cli-0.1.3-py3-none-any.whl |
|---|---|
| Size | 13.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
504be762cda339da8cc047817344b60f3eead3b0c32cd071442bb3a765cd2927
|
|
BLAKE2b-256 checksum How to use checksums |
2c9e6e9693b855090465565a9c0bff97aa3510407cbbbc136632e756ae8ac6fc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.15
|