tooldex 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. tooldex-0.1.1/.github/CODEOWNERS +1 -0
  2. tooldex-0.1.1/.github/PULL_REQUEST_TEMPLATE.md +30 -0
  3. tooldex-0.1.1/.github/workflows/docs.yml +24 -0
  4. tooldex-0.1.1/.github/workflows/tests.yml +29 -0
  5. tooldex-0.1.1/.gitignore +69 -0
  6. tooldex-0.1.1/CONTRIBUTING.md +127 -0
  7. tooldex-0.1.1/PKG-INFO +395 -0
  8. tooldex-0.1.1/README.dev.md +260 -0
  9. tooldex-0.1.1/README.md +374 -0
  10. tooldex-0.1.1/docs/index.md +364 -0
  11. tooldex-0.1.1/docs/stylesheets/extra.css +63 -0
  12. tooldex-0.1.1/mkdocs.yml +40 -0
  13. tooldex-0.1.1/package-lock.json +6 -0
  14. tooldex-0.1.1/pyproject.toml +38 -0
  15. tooldex-0.1.1/requirements.txt +27 -0
  16. tooldex-0.1.1/site/404.html +357 -0
  17. tooldex-0.1.1/site/assets/images/favicon.png +0 -0
  18. tooldex-0.1.1/site/assets/javascripts/bundle.79ae519e.min.js +16 -0
  19. tooldex-0.1.1/site/assets/javascripts/bundle.79ae519e.min.js.map +7 -0
  20. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.ar.min.js +1 -0
  21. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.da.min.js +18 -0
  22. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.de.min.js +18 -0
  23. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.du.min.js +18 -0
  24. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.el.min.js +1 -0
  25. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.es.min.js +18 -0
  26. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.fi.min.js +18 -0
  27. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.fr.min.js +18 -0
  28. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.he.min.js +1 -0
  29. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.hi.min.js +1 -0
  30. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.hu.min.js +18 -0
  31. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.hy.min.js +1 -0
  32. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.it.min.js +18 -0
  33. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.ja.min.js +1 -0
  34. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.jp.min.js +1 -0
  35. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.kn.min.js +1 -0
  36. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.ko.min.js +1 -0
  37. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.multi.min.js +1 -0
  38. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.nl.min.js +18 -0
  39. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.no.min.js +18 -0
  40. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.pt.min.js +18 -0
  41. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.ro.min.js +18 -0
  42. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.ru.min.js +18 -0
  43. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.sa.min.js +1 -0
  44. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.stemmer.support.min.js +1 -0
  45. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.sv.min.js +18 -0
  46. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.ta.min.js +1 -0
  47. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.te.min.js +1 -0
  48. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.th.min.js +1 -0
  49. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.tr.min.js +18 -0
  50. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.vi.min.js +1 -0
  51. tooldex-0.1.1/site/assets/javascripts/lunr/min/lunr.zh.min.js +1 -0
  52. tooldex-0.1.1/site/assets/javascripts/lunr/tinyseg.js +206 -0
  53. tooldex-0.1.1/site/assets/javascripts/lunr/wordcut.js +6708 -0
  54. tooldex-0.1.1/site/assets/javascripts/workers/search.2c215733.min.js +42 -0
  55. tooldex-0.1.1/site/assets/javascripts/workers/search.2c215733.min.js.map +7 -0
  56. tooldex-0.1.1/site/assets/stylesheets/main.484c7ddc.min.css +1 -0
  57. tooldex-0.1.1/site/assets/stylesheets/main.484c7ddc.min.css.map +1 -0
  58. tooldex-0.1.1/site/assets/stylesheets/palette.ab4e12ef.min.css +1 -0
  59. tooldex-0.1.1/site/assets/stylesheets/palette.ab4e12ef.min.css.map +1 -0
  60. tooldex-0.1.1/site/index.html +1348 -0
  61. tooldex-0.1.1/site/search/search_index.json +164 -0
  62. tooldex-0.1.1/site/sitemap.xml +7 -0
  63. tooldex-0.1.1/site/sitemap.xml.gz +0 -0
  64. tooldex-0.1.1/site/stylesheets/extra.css +63 -0
  65. tooldex-0.1.1/tests/__init__.py +0 -0
  66. tooldex-0.1.1/tests/conftest.py +21 -0
  67. tooldex-0.1.1/tests/test_api_servers.py +126 -0
  68. tooldex-0.1.1/tests/test_config_detector.py +97 -0
  69. tooldex-0.1.1/tests/test_models.py +71 -0
  70. tooldex-0.1.1/tests/test_parser_singleton.py +67 -0
  71. tooldex-0.1.1/tests/test_parsers.py +226 -0
  72. tooldex-0.1.1/tests/test_paths.py +122 -0
  73. tooldex-0.1.1/tests/test_readers.py +104 -0
  74. tooldex-0.1.1/tests/test_results.py +80 -0
  75. tooldex-0.1.1/tests/test_to_manifest.py +98 -0
  76. tooldex-0.1.1/tooldex/__init__.py +6 -0
  77. tooldex-0.1.1/tooldex/_cli_output.py +141 -0
  78. tooldex-0.1.1/tooldex/api/__init__.py +0 -0
  79. tooldex-0.1.1/tooldex/api/app.py +74 -0
  80. tooldex-0.1.1/tooldex/api/deps.py +0 -0
  81. tooldex-0.1.1/tooldex/api/routers/__init__.py +0 -0
  82. tooldex-0.1.1/tooldex/api/routers/files.py +31 -0
  83. tooldex-0.1.1/tooldex/api/routers/health.py +82 -0
  84. tooldex-0.1.1/tooldex/api/routers/servers.py +127 -0
  85. tooldex-0.1.1/tooldex/cli.py +346 -0
  86. tooldex-0.1.1/tooldex/core/__init__.py +0 -0
  87. tooldex-0.1.1/tooldex/core/discovery/__init__.py +42 -0
  88. tooldex-0.1.1/tooldex/core/discovery/_docker_mcp.py +246 -0
  89. tooldex-0.1.1/tooldex/core/discovery/_parsers.py +220 -0
  90. tooldex-0.1.1/tooldex/core/discovery/_paths.py +117 -0
  91. tooldex-0.1.1/tooldex/core/discovery/_readers.py +182 -0
  92. tooldex-0.1.1/tooldex/core/discovery/_status_claude.py +68 -0
  93. tooldex-0.1.1/tooldex/core/discovery/_status_codex.py +57 -0
  94. tooldex-0.1.1/tooldex/core/discovery/_status_cursor.py +65 -0
  95. tooldex-0.1.1/tooldex/core/discovery/config_detector.py +249 -0
  96. tooldex-0.1.1/tooldex/core/discovery/mcp_client.py +412 -0
  97. tooldex-0.1.1/tooldex/core/discovery/results.py +143 -0
  98. tooldex-0.1.1/tooldex/core/discovery/to_manifest.py +50 -0
  99. tooldex-0.1.1/tooldex/core/discovery/tool_discovery.py +105 -0
  100. tooldex-0.1.1/tooldex/core/models/__init__.py +7 -0
  101. tooldex-0.1.1/tooldex/core/models/manifest.py +24 -0
  102. tooldex-0.1.1/tooldex/core/models/server.py +54 -0
  103. tooldex-0.1.1/tooldex/core/parsers/__init__.py +0 -0
  104. tooldex-0.1.1/tooldex/core/parsers/parser.py +67 -0
  105. tooldex-0.1.1/tooldex/settings.py +1 -0
  106. tooldex-0.1.1/tooldex/ui/.vite/deps_temp_b4933b73/package.json +3 -0
  107. tooldex-0.1.1/tooldex/ui/dist/assets/index-DzYGk_2D.js +8 -0
  108. tooldex-0.1.1/tooldex/ui/dist/assets/index-EQo7TfH-.css +1 -0
  109. tooldex-0.1.1/tooldex/ui/dist/index.html +18 -0
  110. tooldex-0.1.1/tooldex/ui/dist/tooldex.ico +0 -0
  111. tooldex-0.1.1/tooldex/ui/dist/tooldex.svg +6 -0
  112. tooldex-0.1.1/tooldex/ui/index.html +17 -0
  113. tooldex-0.1.1/tooldex/ui/package-lock.json +1565 -0
  114. tooldex-0.1.1/tooldex/ui/package.json +19 -0
  115. tooldex-0.1.1/tooldex/ui/public/tooldex.ico +0 -0
  116. tooldex-0.1.1/tooldex/ui/public/tooldex.svg +6 -0
  117. tooldex-0.1.1/tooldex/ui/src/App.jsx +137 -0
  118. tooldex-0.1.1/tooldex/ui/src/api.js +32 -0
  119. tooldex-0.1.1/tooldex/ui/src/components/Topbar.jsx +53 -0
  120. tooldex-0.1.1/tooldex/ui/src/components/ui.jsx +276 -0
  121. tooldex-0.1.1/tooldex/ui/src/constants.js +14 -0
  122. tooldex-0.1.1/tooldex/ui/src/hooks/useFetch.js +17 -0
  123. tooldex-0.1.1/tooldex/ui/src/index.css +128 -0
  124. tooldex-0.1.1/tooldex/ui/src/main.jsx +6 -0
  125. tooldex-0.1.1/tooldex/ui/src/views/Agents.jsx +168 -0
  126. tooldex-0.1.1/tooldex/ui/src/views/Dashboard.jsx +114 -0
  127. tooldex-0.1.1/tooldex/ui/src/views/Permissions.jsx +109 -0
  128. tooldex-0.1.1/tooldex/ui/src/views/Servers.jsx +689 -0
  129. tooldex-0.1.1/tooldex/ui/vite.config.js +20 -0
@@ -0,0 +1 @@
1
+ * @RiaBanerjee24
@@ -0,0 +1,30 @@
1
+ ## Summary
2
+
3
+ <!-- What does this PR change, and why? -->
4
+
5
+ ## Related issue
6
+
7
+ <!-- Link any related issue, e.g. Closes #123 -->
8
+
9
+ ## Changes
10
+
11
+ <!-- Bullet list of the key changes -->
12
+
13
+ -
14
+
15
+ ## Testing
16
+
17
+ <!-- How did you verify this works? Include commands run and relevant output. -->
18
+
19
+ ```bash
20
+
21
+ ```
22
+
23
+ ## Checklist
24
+
25
+ - [ ] I read [CONTRIBUTING.md](../CONTRIBUTING.md)
26
+ - [ ] `pytest` passes locally (required — CI will block the merge otherwise)
27
+ - [ ] I added/updated unit tests in `tests/` for any new or changed logic
28
+ - [ ] I manually verified the change (see Testing above)
29
+ - [ ] I updated relevant docs (`README.md`, `README.dev.md`, `docs/index.md`) if behavior changed
30
+ - [ ] This PR is scoped to a single concern
@@ -0,0 +1,24 @@
1
+ name: Deploy docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+
7
+ permissions:
8
+ contents: write
9
+
10
+ jobs:
11
+ deploy:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - uses: actions/setup-python@v5
17
+ with:
18
+ python-version: "3.x"
19
+
20
+ - name: Install MkDocs
21
+ run: pip install mkdocs-material
22
+
23
+ - name: Deploy to GitHub Pages
24
+ run: mkdocs gh-deploy --force
@@ -0,0 +1,29 @@
1
+ name: Tests
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main]
6
+ push:
7
+ branches: [main]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ matrix:
17
+ python-version: ["3.10", "3.11", "3.12"]
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - uses: actions/setup-python@v5
22
+ with:
23
+ python-version: ${{ matrix.python-version }}
24
+
25
+ - name: Install tooldex with test dependencies
26
+ run: pip install -e ".[test]"
27
+
28
+ - name: Run unit tests
29
+ run: pytest -v
@@ -0,0 +1,69 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.pyo
5
+ *.pyd
6
+ .Python
7
+ *.egg
8
+ *.egg-info/
9
+ build/
10
+ .eggs/
11
+ pip-wheel-metadata/
12
+ .pypirc
13
+
14
+ # Virtual environments
15
+ .venv/
16
+ venv/
17
+ env/
18
+ ENV/
19
+
20
+ # Environment variables
21
+ .env
22
+ .env.local
23
+ .env.*.local
24
+
25
+ # Node
26
+ node_modules/
27
+ tooldex/ui/node_modules/
28
+ npm-debug.log*
29
+ yarn-debug.log*
30
+ yarn-error.log*
31
+
32
+
33
+ # Test / lint caches
34
+ .pytest_cache/
35
+ .coverage
36
+ .coverage.*
37
+ htmlcov/
38
+ .mypy_cache/
39
+ .ruff_cache/
40
+
41
+ # Logs
42
+ logs/
43
+ *.log
44
+ audit.log
45
+ changes.txt
46
+
47
+ # OS
48
+ .DS_Store
49
+ Thumbs.db
50
+
51
+ # IDEs
52
+ .vscode/
53
+ .idea/
54
+ *.swp
55
+ *.swo
56
+
57
+ # OPA
58
+ *.rego.bak
59
+
60
+ # Secrets / keys
61
+ *.pem
62
+ *.key
63
+ *.cert
64
+ *.p12
65
+
66
+ # PyPI / packaging
67
+ *.whl
68
+ *.tar.gz
69
+ MANIFEST
@@ -0,0 +1,127 @@
1
+ # Contributing to Tooldex
2
+
3
+ Thanks for taking the time to contribute. This guide covers how to set up the project, the expected workflow, and what to include in a pull request.
4
+
5
+ ---
6
+
7
+ ## Contents
8
+
9
+ - [Getting started](#getting-started)
10
+ - [Development workflow](#development-workflow)
11
+ - [Coding guidelines](#coding-guidelines)
12
+ - [Testing](#testing)
13
+ - [Submitting a pull request](#submitting-a-pull-request)
14
+ - [Reporting bugs](#reporting-bugs)
15
+ - [Adding a new MCP client](#adding-a-new-mcp-client)
16
+
17
+ ---
18
+
19
+ ## Getting started
20
+
21
+ 1. Fork the repository and clone your fork:
22
+
23
+ ```bash
24
+ git clone https://github.com/<your-username>/Tooldex.git
25
+ cd Tooldex
26
+ ```
27
+
28
+ 2. Install in editable mode:
29
+
30
+ ```bash
31
+ pip install -e .
32
+ tooldex --version
33
+ ```
34
+
35
+ 3. Read [`README.dev.md`](README.dev.md) for an overview of the project structure and architecture before making non-trivial changes.
36
+
37
+ ---
38
+
39
+ ## Development workflow
40
+
41
+ 1. Create a branch off `main`:
42
+
43
+ ```bash
44
+ git checkout -b your-feature-name
45
+ ```
46
+
47
+ 2. Make your changes. Keep commits focused — one logical change per commit.
48
+
49
+ 3. Run the unit-test suite and add tests for any new behavior (see [Testing](#testing)) before opening a PR. This is mandatory — the same suite runs in CI on every PR and must pass before a PR is considered healthy.
50
+
51
+ 4. Push your branch and open a pull request against `main`.
52
+
53
+ ---
54
+
55
+ ## Coding guidelines
56
+
57
+ - Match the existing style of the module you're editing rather than introducing a new convention.
58
+ - Keep the sync/async boundary intact: CLI and API handlers are sync; only `core/discovery/mcp_client.py` should contain async I/O. See [`README.dev.md`](README.dev.md#async-architecture).
59
+ - New data structures should be Pydantic v2 models, consistent with `core/models/`.
60
+ - Don't add dependencies unless necessary. If you do, add them to `pyproject.toml` under `dependencies`.
61
+
62
+ ---
63
+
64
+ ## Testing
65
+
66
+ Tooldex has a `pytest` unit-test suite under `tests/`, covering config parsing, path resolution, discovery merging, manifest building, the parser singleton, and the API routers. **All tests must pass before a PR can be merged** — the same suite runs in CI (see [`.github/workflows/tests.yml`](.github/workflows/tests.yml)) against Python 3.10–3.12.
67
+
68
+ Install test dependencies and run the suite:
69
+
70
+ ```bash
71
+ pip install -e ".[test]"
72
+ pytest
73
+ ```
74
+
75
+ Run a single file or a single test while iterating:
76
+
77
+ ```bash
78
+ pytest tests/test_parsers.py
79
+ pytest tests/test_parsers.py::TestParseMcpServers::test_parses_stdio_server -v
80
+ ```
81
+
82
+ If you add or change behavior in `tooldex/core/` or `tooldex/api/`, add or update the corresponding test file in `tests/` as part of your PR — a PR that changes logic without matching test coverage will be asked to add it.
83
+
84
+ For manual, end-to-end checks against your own MCP config:
85
+
86
+ ```bash
87
+ # Verify discovery against your local MCP config
88
+ tooldex run --no-serve
89
+
90
+ # Inspect the raw discovery payload
91
+ tooldex run --json | jq .
92
+
93
+ # Confirm the API server starts and responds
94
+ tooldex run
95
+ curl http://127.0.0.1:8282/api/health/
96
+ ```
97
+
98
+ ---
99
+
100
+ ## Submitting a pull request
101
+
102
+ Use the [pull request template](.github/PULL_REQUEST_TEMPLATE.md) (auto-filled when you open a PR). In summary, include:
103
+
104
+ - A clear description of what changed and why.
105
+ - Any relevant issue numbers.
106
+ - The manual verification steps you ran (commands + output, where useful).
107
+ - Notes on any follow-up work that's intentionally out of scope.
108
+
109
+ Keep PRs scoped to a single concern — smaller PRs are easier to review and merge.
110
+
111
+ ---
112
+
113
+ ## Reporting bugs
114
+
115
+ Open a GitHub issue with:
116
+
117
+ - Tooldex version (`tooldex --version`)
118
+ - Python version and OS
119
+ - The MCP client(s) and config involved
120
+ - Steps to reproduce, expected behavior, and actual behavior
121
+ - Relevant output from `tooldex run --json` or server logs, with secrets redacted
122
+
123
+ ---
124
+
125
+ ## Adding a new MCP client
126
+
127
+ See [`README.dev.md` → Adding a new MCP client](README.dev.md#adding-a-new-mcp-client) for the exact steps (path resolvers, `build_plan()` registration, optional status enrichment and agent CLI fallback).
tooldex-0.1.1/PKG-INFO ADDED
@@ -0,0 +1,395 @@
1
+ Metadata-Version: 2.4
2
+ Name: tooldex
3
+ Version: 0.1.1
4
+ Summary: Unified MCP Server Observatory
5
+ License: MIT
6
+ Keywords: agents,ai,mcp,observability,permissions
7
+ Requires-Python: >=3.10
8
+ Requires-Dist: fastapi>=0.115.0
9
+ Requires-Dist: mcp>=1.0
10
+ Requires-Dist: pydantic>=2.0
11
+ Requires-Dist: pyyaml>=6.0
12
+ Requires-Dist: tomli>=2.0; python_version < '3.11'
13
+ Requires-Dist: typer>=0.12.0
14
+ Requires-Dist: uvicorn[standard]>=0.30.0
15
+ Requires-Dist: watchfiles>=0.21.0
16
+ Provides-Extra: test
17
+ Requires-Dist: httpx>=0.27; extra == 'test'
18
+ Requires-Dist: pytest-cov>=5.0; extra == 'test'
19
+ Requires-Dist: pytest>=8.0; extra == 'test'
20
+ Description-Content-Type: text/markdown
21
+
22
+ # Tooldex
23
+
24
+ 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.
25
+
26
+ ---
27
+
28
+ ## Contents
29
+
30
+ - [Requirements](#requirements)
31
+ - [Installation](#installation)
32
+ - [Quick start](#quick-start)
33
+ - [How discovery works](#how-discovery-works)
34
+ - [Config file locations](#config-file-locations)
35
+ - [MCP config format](#mcp-config-format)
36
+ - [CLI reference](#cli-reference)
37
+ - [JSON output](#json-output)
38
+ - [API endpoints](#api-endpoints)
39
+ - [Testing](#testing)
40
+ - [Contributing](#contributing)
41
+
42
+ ---
43
+
44
+ ## Requirements
45
+
46
+ - Python 3.10 or later
47
+ - At least one supported MCP client configured (Claude Code, Cursor, Codex, or Docker MCP Toolkit)
48
+
49
+ ---
50
+
51
+ ## Installation
52
+
53
+ ```bash
54
+ pip install tooldex
55
+ ```
56
+
57
+ Verify:
58
+
59
+ ```bash
60
+ tooldex --version
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Quick start
66
+
67
+ ```bash
68
+ cd your-project
69
+ tooldex run
70
+ ```
71
+
72
+ Tooldex scans config files, probes each discovered server for its tool surface, and opens the UI. The startup banner shows where to connect:
73
+
74
+ ```
75
+ ╔══════════════════════════════════════════════════╗
76
+ ║ tooldex v0.1.1 ║
77
+ ╠══════════════════════════════════════════════════╣
78
+ ║ Servers 12 ║
79
+ ║ Tools 187 ║
80
+ ╠══════════════════════════════════════════════════╣
81
+ ║ → http://127.0.0.1:8282 ║
82
+ ╚══════════════════════════════════════════════════╝
83
+ ```
84
+
85
+ To see the discovery summary without starting the server:
86
+
87
+ ```bash
88
+ tooldex run --no-serve
89
+ ```
90
+
91
+ ---
92
+
93
+ ## How discovery works
94
+
95
+ When you run `tooldex run`, the following happens in order:
96
+
97
+ 1. **Config scan** — Tooldex reads every known MCP config location for the current directory (see [Config file locations](#config-file-locations)). Each found server gets a qualified ID in the form `{client}:{server_name}` so servers from different clients never collide.
98
+
99
+ 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.
100
+
101
+ 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.
102
+
103
+ 4. **UI** — A local web server starts and serves the unified view.
104
+
105
+ ---
106
+
107
+ ## Config file locations
108
+
109
+ Tooldex checks all of the following on every run. Files that do not exist are skipped silently.
110
+
111
+ ### Claude Code
112
+
113
+ | Scope | Path |
114
+ |---|---|
115
+ | Global | `~/.claude.json` |
116
+ | Project | `<project>/.claude/mcp.json` |
117
+ | Project (flat) | `<project>/.claude.json` |
118
+
119
+ ### Cursor
120
+
121
+ | Scope | Path |
122
+ |---|---|
123
+ | Global | `~/.cursor/mcp.json` |
124
+ | Project | `<project>/.cursor/mcp.json` |
125
+
126
+ ### Codex CLI
127
+
128
+ | Scope | Path |
129
+ |---|---|
130
+ | Global | `~/.codex/config.toml` |
131
+ | Project | `<project>/.codex/config.toml` |
132
+
133
+ ### MCP JSON (shared / team configs)
134
+
135
+ | Scope | Path |
136
+ |---|---|
137
+ | Global | `~/.mcp.json` |
138
+ | Project | `<project>/.mcp.json` |
139
+
140
+ ### Docker MCP Toolkit
141
+
142
+ Tooldex reads all Docker MCP profiles via `docker mcp profile ls`. No additional configuration is needed.
143
+
144
+ **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.
145
+
146
+ ---
147
+
148
+ ## MCP config format
149
+
150
+ All JSON-based clients use the same `mcpServers` structure. Tooldex understands both `stdio` (command-based) and `http`/`sse` (URL-based) transports.
151
+
152
+ ### stdio server (runs a local process)
153
+
154
+ ```json
155
+ {
156
+ "mcpServers": {
157
+ "filesystem": {
158
+ "command": "npx",
159
+ "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"],
160
+ "env": {
161
+ "SOME_VAR": "value"
162
+ }
163
+ },
164
+ "my-db-server": {
165
+ "command": "node",
166
+ "args": ["/path/to/my-server/index.js"],
167
+ "env": {
168
+ "DB_HOST": "localhost",
169
+ "DB_PORT": "5432"
170
+ }
171
+ }
172
+ }
173
+ }
174
+ ```
175
+
176
+ ### HTTP / SSE server (connects to a remote endpoint)
177
+
178
+ ```json
179
+ {
180
+ "mcpServers": {
181
+ "browserbase": {
182
+ "type": "http",
183
+ "url": "https://mcp.browserbase.com/mcp"
184
+ },
185
+ "remote-api": {
186
+ "type": "sse",
187
+ "url": "https://api.example.com/mcp/sse"
188
+ }
189
+ }
190
+ }
191
+ ```
192
+
193
+ ### Codex (`~/.codex/config.toml`)
194
+
195
+ Codex uses TOML with an `[mcp_servers.<id>]` table per server:
196
+
197
+ ```toml
198
+ [mcp_servers.filesystem]
199
+ command = "npx"
200
+ args = ["-y", "@modelcontextprotocol/server-filesystem", "."]
201
+
202
+ [mcp_servers.github]
203
+ type = "http"
204
+ url = "https://api.githubcopilot.com/mcp/"
205
+ ```
206
+
207
+ ### What Tooldex detects from these files
208
+
209
+ For each config file found, Tooldex reports:
210
+
211
+ - **`status`** — `found` / `not_found` / `empty` / `parse_error` / `read_error`
212
+ - **`server_ids`** — list of server names parsed from the file
213
+ - **`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)
214
+
215
+ For each server probed:
216
+
217
+ - **`status`** — `found` / `timeout` / `connection_failed` / `protocol_error` / `missing_command`
218
+ - **`tools`** — names, descriptions, and input schemas of every tool the server exposes
219
+ - **`duration_ms`** — probe wall time
220
+ - **`error`** — human-readable failure message when status is not `found`; includes install hints for common missing runtimes (`uvx`, `npx`, `docker`, etc.)
221
+
222
+ ---
223
+
224
+ ## CLI reference
225
+
226
+ ```
227
+ tooldex [OPTIONS] COMMAND [ARGS]
228
+ ```
229
+
230
+ ### Global options
231
+
232
+ | Flag | Description |
233
+ |---|---|
234
+ | `--version`, `-V` | Print version and exit |
235
+ | `--help`, `-h` | Show help |
236
+
237
+ ### `tooldex run`
238
+
239
+ Autodiscover MCP servers and start the UI.
240
+
241
+ ```bash
242
+ tooldex run [OPTIONS]
243
+ ```
244
+
245
+ | Flag | Default | Description |
246
+ |---|---|---|
247
+ | `--port`, `-p` | `8282` | Starting port. Increments automatically if occupied. |
248
+ | `--host` | `127.0.0.1` | Interface to bind the UI server to. |
249
+ | `--no-serve` | off | Print discovery summary and exit without starting the server. |
250
+ | `--json` | off | Print discovery result as JSON and exit. Implies `--no-serve`. Does not probe servers. |
251
+ | `--timeout` | `10.0` | Per-server probe timeout in seconds. |
252
+ | `--concurrency` | `8` | Maximum concurrent server probes. |
253
+ | `--no-probe <name>` | — | Skip probing a specific server by name. Repeatable. |
254
+ | `--config <path>` | — | Additional MCP config file to include. Repeatable. Custom configs are processed first and win on duplicate server IDs. |
255
+
256
+ All flags accept both `--flag` and `-flag` prefix.
257
+
258
+ #### Examples
259
+
260
+ ```bash
261
+ # Discover and launch UI
262
+ tooldex run
263
+
264
+ # Custom port and host
265
+ tooldex run --port 9000 --host 0.0.0.0
266
+
267
+ # Just print what was found, don't start the server
268
+ tooldex run --no-serve
269
+
270
+ # Skip slow or broken servers during probing
271
+ tooldex run --no-probe node-api-docs --no-probe local-mcp
272
+
273
+ # Include an extra config file
274
+ tooldex run --config ~/shared/team-servers.json
275
+
276
+ # Increase timeout for slow servers
277
+ tooldex run --timeout 30
278
+
279
+ # Use all 16 cores for probing
280
+ tooldex run --concurrency 16
281
+
282
+ # Pipe the discovery result into jq
283
+ tooldex run --json | jq '.duplicates'
284
+ ```
285
+
286
+ ---
287
+
288
+ ## JSON output
289
+
290
+ `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.
291
+
292
+ ```json
293
+ {
294
+ "sources": [
295
+ {
296
+ "client": "claude_code_user",
297
+ "path": "/home/user/.claude.json",
298
+ "status": "found",
299
+ "error": null,
300
+ "server_ids": ["filesystem", "github"],
301
+ "in_file_duplicates": []
302
+ },
303
+ {
304
+ "client": "mcp_json_user",
305
+ "path": "/home/user/.mcp.json",
306
+ "status": "not_found",
307
+ "error": null,
308
+ "server_ids": [],
309
+ "in_file_duplicates": []
310
+ }
311
+ ],
312
+ "servers": {
313
+ "claude_code_user:filesystem": {
314
+ "name": "filesystem",
315
+ "transport": "stdio",
316
+ "command": "npx",
317
+ "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"],
318
+ "url": null
319
+ }
320
+ },
321
+ "duplicates": [
322
+ "\"filesystem\" in cursor_user is also configured in claude_code_user",
323
+ "\"firecrawl-mcp\" is a duplicate key in /home/user/.mcp.json (last value kept)"
324
+ ]
325
+ }
326
+ ```
327
+
328
+ **Fields:**
329
+
330
+ | Field | Description |
331
+ |---|---|
332
+ | `sources` | Every config location checked, with status and server IDs found. |
333
+ | `servers` | Deduplicated map of all servers, keyed by `{client}:{server_id}`. |
334
+ | `duplicates` | Human-readable notes about server name collisions across clients, and duplicate JSON keys within a single file. |
335
+
336
+ **Exit codes:** `0` on success, `1` on serialisation error.
337
+
338
+ ---
339
+
340
+ ## API endpoints
341
+
342
+ When the server is running (default `http://127.0.0.1:8282`):
343
+
344
+ All endpoints respond with or without a trailing slash.
345
+
346
+ | Method | Endpoint | Description |
347
+ |---|---|---|
348
+ | `GET` | `/api/health/` | `status`, current `timestamp`, and `uptime_seconds` since the server started |
349
+ | `GET` | `/api/servers/` | All MCP servers with `total_servers`, `total_tools`, `scanned_at`. Per server: `tool_count`, `source_file` |
350
+ | `GET` | `/api/servers/{id}/` | Single server with full tool detail |
351
+ | `POST` | `/api/servers/{id}/rescan/` | Re-probe a single server and update its tools in place |
352
+ | `GET` | `/api/files/` | All config files that were scanned: path, client, status, server IDs found, any parse errors |
353
+ | `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. |
354
+
355
+ ---
356
+
357
+ ## Testing
358
+
359
+ Tooldex has a `pytest` unit-test suite that runs in CI on every PR:
360
+
361
+ ```bash
362
+ pip install -e ".[test]"
363
+ pytest
364
+ ```
365
+
366
+ See [CONTRIBUTING.md](CONTRIBUTING.md#testing) for details. For ad-hoc manual checks against your own MCP config:
367
+
368
+ ```bash
369
+ # Verify discovery against your local config
370
+ tooldex run --no-serve
371
+
372
+ # Inspect the raw discovery payload
373
+ tooldex run --json | jq .
374
+
375
+ # Check a specific extra config file
376
+ tooldex run --config ./my-config.json --json
377
+
378
+ # Confirm a server is reachable with a longer timeout
379
+ tooldex run --timeout 30 --no-probe github
380
+ ```
381
+
382
+ To run the package from source without installing:
383
+
384
+ ```bash
385
+ git clone <repo>
386
+ cd Tooldex
387
+ pip install -e .
388
+ tooldex --version
389
+ ```
390
+
391
+ ---
392
+
393
+ ## Contributing
394
+
395
+ Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for setup instructions, the development workflow, and pull request guidelines.