Skip to main content

Unified MCP Server Observatory

Project description

Tooldex

Tooldex autodiscovers MCP servers configured across your AI clients — Claude Code, Cursor, Codex, Docker MCP Toolkit — and surfaces them in a unified UI. No manual config. Run it from any project directory and it finds everything.


Contents


Requirements

  • Python 3.10 or later
  • At least one supported MCP client configured (Claude Code, Cursor, Codex, or Docker MCP Toolkit)

Installation

pip install tooldex

Verify:

tooldex --version

Quick start

cd your-project
tooldex run

Tooldex scans config files, probes each discovered server for its tool surface, and opens the UI. The startup banner shows where to connect:

  ╔══════════════════════════════════════════════════╗
  ║         tooldex  v0.1.1                         ║
  ╠══════════════════════════════════════════════════╣
  ║  Servers  12                                     ║
  ║  Tools    187                                    ║
  ╠══════════════════════════════════════════════════╣
  ║  →  http://127.0.0.1:8282                        ║
  ╚══════════════════════════════════════════════════╝

To see the discovery summary without starting the server:

tooldex run --no-serve

How discovery works

When you run tooldex run, the following happens in order:

  1. Config scan — Tooldex reads every known MCP config location for the current directory (see Config file locations). Each found server gets a qualified ID in the form {client}:{server_name} so servers from different clients never collide.

  2. Live probe — Each discovered server is contacted concurrently. Tooldex calls tools/list on it and records which tools it exposes, how long it took, and any errors.

  3. Deduplication — If the same server name appears in multiple clients (e.g., browserbase in both Claude Code and Cursor), both are retained as separate entries under their respective clients. Duplicate server names across clients are reported in the duplicates field.

  4. UI — A local web server starts and serves the unified view.


Config file locations

Tooldex checks all of the following on every run. Files that do not exist are skipped silently.

Claude Code

Scope Path
Global ~/.claude.json
Project <project>/.claude/mcp.json
Project (flat) <project>/.claude.json

Cursor

Scope Path
Global ~/.cursor/mcp.json
Project <project>/.cursor/mcp.json

Codex CLI

Scope Path
Global ~/.codex/config.toml
Project <project>/.codex/config.toml

MCP JSON (shared / team configs)

Scope Path
Global ~/.mcp.json
Project <project>/.mcp.json

Docker MCP Toolkit

Tooldex reads all Docker MCP profiles via docker mcp profile ls. No additional configuration is needed.

Project-scoped paths are discovered by walking up the directory tree from cwd until the home directory. This means running tooldex run from a nested subdirectory will still find a .mcp.json at the project root.


MCP config format

All JSON-based clients use the same mcpServers structure. Tooldex understands both stdio (command-based) and http/sse (URL-based) transports.

stdio server (runs a local process)

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"],
      "env": {
        "SOME_VAR": "value"
      }
    },
    "my-db-server": {
      "command": "node",
      "args": ["/path/to/my-server/index.js"],
      "env": {
        "DB_HOST": "localhost",
        "DB_PORT": "5432"
      }
    }
  }
}

HTTP / SSE server (connects to a remote endpoint)

{
  "mcpServers": {
    "browserbase": {
      "type": "http",
      "url": "https://mcp.browserbase.com/mcp"
    },
    "remote-api": {
      "type": "sse",
      "url": "https://api.example.com/mcp/sse"
    }
  }
}

Codex (~/.codex/config.toml)

Codex uses TOML with an [mcp_servers.<id>] table per server:

[mcp_servers.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "."]

[mcp_servers.github]
type = "http"
url = "https://api.githubcopilot.com/mcp/"

What Tooldex detects from these files

For each config file found, Tooldex reports:

  • statusfound / not_found / empty / parse_error / read_error
  • server_ids — list of server names parsed from the file
  • in_file_duplicates — server names that appeared more than once as JSON keys (the last value is kept; all prior definitions are silently dropped by the JSON parser)

For each server probed:

  • statusfound / timeout / connection_failed / protocol_error / missing_command
  • tools — names, descriptions, and input schemas of every tool the server exposes
  • duration_ms — probe wall time
  • error — human-readable failure message when status is not found; includes install hints for common missing runtimes (uvx, npx, docker, etc.)

CLI reference

tooldex [OPTIONS] COMMAND [ARGS]

Global options

Flag Description
--version, -V Print version and exit
--help, -h Show help

tooldex run

Autodiscover MCP servers and start the UI.

tooldex run [OPTIONS]
Flag Default Description
--port, -p 8282 Starting port. Increments automatically if occupied.
--host 127.0.0.1 Interface to bind the UI server to.
--no-serve off Print discovery summary and exit without starting the server.
--json off Print discovery result as JSON and exit. Implies --no-serve. Does not probe servers.
--timeout 10.0 Per-server probe timeout in seconds.
--concurrency 8 Maximum concurrent server probes.
--no-probe <name> Skip probing a specific server by name. Repeatable.
--config <path> Additional MCP config file to include. Repeatable. Custom configs are processed first and win on duplicate server IDs.

All flags accept both --flag and -flag prefix.

Examples

# Discover and launch UI
tooldex run

# Custom port and host
tooldex run --port 9000 --host 0.0.0.0

# Just print what was found, don't start the server
tooldex run --no-serve

# Skip slow or broken servers during probing
tooldex run --no-probe node-api-docs --no-probe local-mcp

# Include an extra config file
tooldex run --config ~/shared/team-servers.json

# Increase timeout for slow servers
tooldex run --timeout 30

# Use all 16 cores for probing
tooldex run --concurrency 16

# Pipe the discovery result into jq
tooldex run --json | jq '.duplicates'

JSON output

tooldex run --json prints a single JSON object to stdout and exits. No servers are probed; this is fast and side-effect-free for use in scripts and CI.

{
  "sources": [
    {
      "client": "claude_code_user",
      "path": "/home/user/.claude.json",
      "status": "found",
      "error": null,
      "server_ids": ["filesystem", "github"],
      "in_file_duplicates": []
    },
    {
      "client": "mcp_json_user",
      "path": "/home/user/.mcp.json",
      "status": "not_found",
      "error": null,
      "server_ids": [],
      "in_file_duplicates": []
    }
  ],
  "servers": {
    "claude_code_user:filesystem": {
      "name": "filesystem",
      "transport": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"],
      "url": null
    }
  },
  "duplicates": [
    "\"filesystem\" in cursor_user is also configured in claude_code_user",
    "\"firecrawl-mcp\" is a duplicate key in /home/user/.mcp.json (last value kept)"
  ]
}

Fields:

Field Description
sources Every config location checked, with status and server IDs found.
servers Deduplicated map of all servers, keyed by {client}:{server_id}.
duplicates Human-readable notes about server name collisions across clients, and duplicate JSON keys within a single file.

Exit codes: 0 on success, 1 on serialisation error.


API endpoints

When the server is running (default http://127.0.0.1:8282):

All endpoints respond with or without a trailing slash.

Method Endpoint Description
GET /api/health/ status, current timestamp, and uptime_seconds since the server started
GET /api/servers/ All MCP servers with total_servers, total_tools, scanned_at. Per server: tool_count, source_file
GET /api/servers/{id}/ Single server with full tool detail
POST /api/servers/{id}/rescan/ Re-probe a single server and update its tools in place
GET /api/files/ All config files that were scanned: path, client, status, server IDs found, any parse errors
POST /api/rescan/ Full rediscovery — re-reads all MCP configs and re-probes every server. Returns {"status": "already_scanning"} if a rescan is already in progress.

Testing

Tooldex has a pytest unit-test suite that runs in CI on every PR:

pip install -e ".[test]"
pytest

See CONTRIBUTING.md for details. For ad-hoc manual checks against your own MCP config:

# Verify discovery against your local config
tooldex run --no-serve

# Inspect the raw discovery payload
tooldex run --json | jq .

# Check a specific extra config file
tooldex run --config ./my-config.json --json

# Confirm a server is reachable with a longer timeout
tooldex run --timeout 30 --no-probe github

To run the package from source without installing:

git clone <repo>
cd Tooldex
pip install -e .
tooldex --version

Contributing

Contributions are welcome. See CONTRIBUTING.md for setup instructions, the development workflow, and pull request guidelines.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tooldex-0.1.1.tar.gz (759.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tooldex-0.1.1-py3-none-any.whl (158.4 kB view details)

Uploaded Python 3

File details

Details for the file tooldex-0.1.1.tar.gz.

File metadata

  • Download URL: tooldex-0.1.1.tar.gz
  • Upload date:
  • Size: 759.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for tooldex-0.1.1.tar.gz
Algorithm Hash digest
SHA256 72f4c253f8c027755a17d235c67d3f06102dea4f3b850f6084e89d3c7a6392a3
MD5 7afa0574501c148d11f592772d4d5017
BLAKE2b-256 92a88b54a33fb0cdacae01ba4fce014c0d539039c473494cd0a16c5a0d25e999

See more details on using hashes here.

File details

Details for the file tooldex-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: tooldex-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 158.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for tooldex-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 18c676accd74a5f8f1fa874f11a268141c0b5659e1340c95969e97c05aaa235b
MD5 163d04837c79f73add0ad022f115c116
BLAKE2b-256 044ae8068ef21300f6fc959aff067829e20f225417f0087fc75a1ac57eeac4fd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page