mcp-tap 0.1.0__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 (115) hide show
  1. mcp_tap-0.1.0/.claude/agent-memory/api-craft-expert/MEMORY.md +6 -0
  2. mcp_tap-0.1.0/.claude/agent-memory/cicd-deployment-architect/MEMORY.md +7 -0
  3. mcp_tap-0.1.0/.claude/agent-memory/clean-architecture-designer/MEMORY.md +10 -0
  4. mcp_tap-0.1.0/.claude/agent-memory/db-performance-architect/MEMORY.md +5 -0
  5. mcp_tap-0.1.0/.claude/agent-memory/debug-detective/MEMORY.md +4 -0
  6. mcp_tap-0.1.0/.claude/agent-memory/design-system-architect/MEMORY.md +4 -0
  7. mcp_tap-0.1.0/.claude/agent-memory/innovation-lab/MEMORY.md +5 -0
  8. mcp_tap-0.1.0/.claude/agent-memory/llm-integration-architect/MEMORY.md +5 -0
  9. mcp_tap-0.1.0/.claude/agent-memory/orchestration-architect/MEMORY.md +4 -0
  10. mcp_tap-0.1.0/.claude/agent-memory/perf-optimizer/MEMORY.md +5 -0
  11. mcp_tap-0.1.0/.claude/agent-memory/playwright-e2e-architect/MEMORY.md +4 -0
  12. mcp_tap-0.1.0/.claude/agent-memory/premium-ui-designer/MEMORY.md +4 -0
  13. mcp_tap-0.1.0/.claude/agent-memory/product-strategy-advisor/MEMORY.md +45 -0
  14. mcp_tap-0.1.0/.claude/agent-memory/python-craftsman/MEMORY.md +49 -0
  15. mcp_tap-0.1.0/.claude/agent-memory/refactoring-specialist/MEMORY.md +6 -0
  16. mcp_tap-0.1.0/.claude/agent-memory/test-architect/MEMORY.md +81 -0
  17. mcp_tap-0.1.0/.claude/agent-memory/ux-simplifier/MEMORY.md +4 -0
  18. mcp_tap-0.1.0/.claude/agents/api-craft-expert.md +305 -0
  19. mcp_tap-0.1.0/.claude/agents/cicd-deployment-architect.md +161 -0
  20. mcp_tap-0.1.0/.claude/agents/clean-architecture-designer.md +162 -0
  21. mcp_tap-0.1.0/.claude/agents/db-performance-architect.md +157 -0
  22. mcp_tap-0.1.0/.claude/agents/debug-detective.md +153 -0
  23. mcp_tap-0.1.0/.claude/agents/design-system-architect.md +169 -0
  24. mcp_tap-0.1.0/.claude/agents/innovation-lab.md +128 -0
  25. mcp_tap-0.1.0/.claude/agents/llm-integration-architect.md +135 -0
  26. mcp_tap-0.1.0/.claude/agents/orchestration-architect.md +141 -0
  27. mcp_tap-0.1.0/.claude/agents/perf-optimizer.md +156 -0
  28. mcp_tap-0.1.0/.claude/agents/playwright-e2e-architect.md +190 -0
  29. mcp_tap-0.1.0/.claude/agents/premium-ui-designer.md +195 -0
  30. mcp_tap-0.1.0/.claude/agents/product-strategy-advisor.md +144 -0
  31. mcp_tap-0.1.0/.claude/agents/python-craftsman.md +183 -0
  32. mcp_tap-0.1.0/.claude/agents/refactoring-specialist.md +136 -0
  33. mcp_tap-0.1.0/.claude/agents/test-architect.md +260 -0
  34. mcp_tap-0.1.0/.claude/agents/ux-simplifier.md +131 -0
  35. mcp_tap-0.1.0/.github/workflows/ci.yml +50 -0
  36. mcp_tap-0.1.0/.github/workflows/publish.yml +35 -0
  37. mcp_tap-0.1.0/.gitignore +16 -0
  38. mcp_tap-0.1.0/CLAUDE.md +181 -0
  39. mcp_tap-0.1.0/LICENSE +21 -0
  40. mcp_tap-0.1.0/PKG-INFO +161 -0
  41. mcp_tap-0.1.0/README.md +139 -0
  42. mcp_tap-0.1.0/docs/CREATIVE_BRIEF.md +628 -0
  43. mcp_tap-0.1.0/docs/architecture/ARCHITECTURE.md +108 -0
  44. mcp_tap-0.1.0/docs/handoff/_TEMPLATE.md +30 -0
  45. mcp_tap-0.1.0/docs/issues/2026-02-19_batch-health-check.md +70 -0
  46. mcp_tap-0.1.0/docs/issues/2026-02-19_context-aware-search.md +71 -0
  47. mcp_tap-0.1.0/docs/issues/2026-02-19_e2e-install-flow.md +60 -0
  48. mcp_tap-0.1.0/docs/issues/2026-02-19_llm-interface-polish.md +51 -0
  49. mcp_tap-0.1.0/docs/issues/2026-02-19_multi-client-config.md +81 -0
  50. mcp_tap-0.1.0/docs/issues/2026-02-19_package-publish.md +75 -0
  51. mcp_tap-0.1.0/docs/issues/2026-02-19_project-scanner-engine.md +68 -0
  52. mcp_tap-0.1.0/docs/issues/2026-02-19_scan-project-tool.md +55 -0
  53. mcp_tap-0.1.0/docs/issues/2026-02-19_self-healing.md +65 -0
  54. mcp_tap-0.1.0/docs/issues/2026-02-19_test-suite-ci.md +104 -0
  55. mcp_tap-0.1.0/docs/issues/_TEMPLATE.md +38 -0
  56. mcp_tap-0.1.0/pyproject.toml +57 -0
  57. mcp_tap-0.1.0/src/mcp_tap/__init__.py +10 -0
  58. mcp_tap-0.1.0/src/mcp_tap/__main__.py +3 -0
  59. mcp_tap-0.1.0/src/mcp_tap/config/__init__.py +0 -0
  60. mcp_tap-0.1.0/src/mcp_tap/config/detection.py +222 -0
  61. mcp_tap-0.1.0/src/mcp_tap/config/reader.py +62 -0
  62. mcp_tap-0.1.0/src/mcp_tap/config/writer.py +77 -0
  63. mcp_tap-0.1.0/src/mcp_tap/connection/__init__.py +0 -0
  64. mcp_tap-0.1.0/src/mcp_tap/connection/tester.py +63 -0
  65. mcp_tap-0.1.0/src/mcp_tap/errors.py +43 -0
  66. mcp_tap-0.1.0/src/mcp_tap/installer/__init__.py +0 -0
  67. mcp_tap-0.1.0/src/mcp_tap/installer/base.py +27 -0
  68. mcp_tap-0.1.0/src/mcp_tap/installer/docker.py +54 -0
  69. mcp_tap-0.1.0/src/mcp_tap/installer/npm.py +55 -0
  70. mcp_tap-0.1.0/src/mcp_tap/installer/pip.py +66 -0
  71. mcp_tap-0.1.0/src/mcp_tap/installer/resolver.py +44 -0
  72. mcp_tap-0.1.0/src/mcp_tap/installer/subprocess.py +37 -0
  73. mcp_tap-0.1.0/src/mcp_tap/models.py +224 -0
  74. mcp_tap-0.1.0/src/mcp_tap/registry/__init__.py +0 -0
  75. mcp_tap-0.1.0/src/mcp_tap/registry/client.py +128 -0
  76. mcp_tap-0.1.0/src/mcp_tap/scanner/__init__.py +1 -0
  77. mcp_tap-0.1.0/src/mcp_tap/scanner/detector.py +602 -0
  78. mcp_tap-0.1.0/src/mcp_tap/scanner/recommendations.py +164 -0
  79. mcp_tap-0.1.0/src/mcp_tap/scanner/scoring.py +105 -0
  80. mcp_tap-0.1.0/src/mcp_tap/server.py +84 -0
  81. mcp_tap-0.1.0/src/mcp_tap/tools/__init__.py +0 -0
  82. mcp_tap-0.1.0/src/mcp_tap/tools/configure.py +278 -0
  83. mcp_tap-0.1.0/src/mcp_tap/tools/health.py +158 -0
  84. mcp_tap-0.1.0/src/mcp_tap/tools/list.py +76 -0
  85. mcp_tap-0.1.0/src/mcp_tap/tools/remove.py +172 -0
  86. mcp_tap-0.1.0/src/mcp_tap/tools/scan.py +142 -0
  87. mcp_tap-0.1.0/src/mcp_tap/tools/search.py +131 -0
  88. mcp_tap-0.1.0/src/mcp_tap/tools/test.py +93 -0
  89. mcp_tap-0.1.0/tests/__init__.py +0 -0
  90. mcp_tap-0.1.0/tests/fixtures/empty_project/.gitkeep +0 -0
  91. mcp_tap-0.1.0/tests/fixtures/minimal_project/Makefile +0 -0
  92. mcp_tap-0.1.0/tests/fixtures/minimal_project/requirements.txt +2 -0
  93. mcp_tap-0.1.0/tests/fixtures/node_express_project/docker-compose.yml +11 -0
  94. mcp_tap-0.1.0/tests/fixtures/node_express_project/package.json +24 -0
  95. mcp_tap-0.1.0/tests/fixtures/python_fastapi_project/.env.example +4 -0
  96. mcp_tap-0.1.0/tests/fixtures/python_fastapi_project/.github/workflows/ci.yml +0 -0
  97. mcp_tap-0.1.0/tests/fixtures/python_fastapi_project/docker-compose.yml +21 -0
  98. mcp_tap-0.1.0/tests/fixtures/python_fastapi_project/pyproject.toml +25 -0
  99. mcp_tap-0.1.0/tests/smoke_test.py +8 -0
  100. mcp_tap-0.1.0/tests/test_config.py +126 -0
  101. mcp_tap-0.1.0/tests/test_connection.py +103 -0
  102. mcp_tap-0.1.0/tests/test_detection.py +125 -0
  103. mcp_tap-0.1.0/tests/test_installers.py +203 -0
  104. mcp_tap-0.1.0/tests/test_models.py +23 -0
  105. mcp_tap-0.1.0/tests/test_registry.py +68 -0
  106. mcp_tap-0.1.0/tests/test_scanner.py +873 -0
  107. mcp_tap-0.1.0/tests/test_scoring.py +257 -0
  108. mcp_tap-0.1.0/tests/test_tools_configure.py +781 -0
  109. mcp_tap-0.1.0/tests/test_tools_health.py +554 -0
  110. mcp_tap-0.1.0/tests/test_tools_list.py +185 -0
  111. mcp_tap-0.1.0/tests/test_tools_remove.py +200 -0
  112. mcp_tap-0.1.0/tests/test_tools_scan.py +507 -0
  113. mcp_tap-0.1.0/tests/test_tools_search.py +459 -0
  114. mcp_tap-0.1.0/tests/test_tools_test.py +174 -0
  115. mcp_tap-0.1.0/uv.lock +787 -0
@@ -0,0 +1,6 @@
1
+ # API Craft Expert Memory — mcp-tap
2
+
3
+ ## Project: mcp-tap (MCP server, not REST API)
4
+ - Exposes tools via MCP protocol (FastMCP), not HTTP endpoints
5
+ - 5 tools: search_servers, configure_server, test_connection, list_installed, remove_server
6
+ - Tool annotations: readOnlyHint and destructiveHint properly set
@@ -0,0 +1,7 @@
1
+ # CI/CD Deployment Architect Memory — mcp-tap
2
+
3
+ ## Project: mcp-tap (Python MCP server, PyPI package)
4
+ - Build: hatchling
5
+ - Package: `mcp-tap` on PyPI
6
+ - Run: `uvx mcp-tap` or `python -m mcp_tap`
7
+ - No CI/CD pipeline yet. Fresh project.
@@ -0,0 +1,10 @@
1
+ # Clean Architecture Designer Memory — mcp-tap
2
+
3
+ ## Architecture
4
+ - Hexagonal (ports & adapters)
5
+ - Domain: `models.py` (frozen DCs) + `errors.py` (exception tree)
6
+ - Ports: Protocol classes in `base.py` files
7
+ - Adapters: `registry/`, `config/`, `installer/`, `connection/`
8
+ - Application: `tools/` (5 MCP tools)
9
+ - Composition root: `server.py` (wiring only)
10
+ - Dependency direction: tools → domain ← adapters
@@ -0,0 +1,5 @@
1
+ # Database Performance Architect Memory — mcp-tap
2
+
3
+ ## Project: mcp-tap (no database — reads/writes JSON config files)
4
+ - No database. Config stored as JSON files on filesystem.
5
+ - This agent is unlikely to be needed for this project.
@@ -0,0 +1,4 @@
1
+ # Debug Detective Memory — mcp-tap
2
+
3
+ ## Project: mcp-tap (Python MCP meta-server)
4
+ - No findings yet. Fresh project.
@@ -0,0 +1,4 @@
1
+ # Design System Architect Memory — mcp-tap
2
+
3
+ ## Project: mcp-tap (CLI/MCP server — no UI)
4
+ - No frontend. This agent is unlikely to be needed for this project.
@@ -0,0 +1,5 @@
1
+ # Innovation Lab Memory — mcp-tap
2
+
3
+ ## Project: mcp-tap (MCP meta-server)
4
+ - No experiments yet. Fresh project.
5
+ - See `docs/CREATIVE_BRIEF.md` for product vision and feature roadmap.
@@ -0,0 +1,5 @@
1
+ # LLM Integration Architect Memory — mcp-tap
2
+
3
+ ## Project: mcp-tap (MCP meta-server)
4
+ - No direct LLM integration. The MCP server is consumed BY LLMs, not calling them.
5
+ - Future: project-aware setup may use LLM for stack analysis.
@@ -0,0 +1,4 @@
1
+ # Orchestration Architect Memory — mcp-tap
2
+
3
+ ## Project: mcp-tap (MCP meta-server)
4
+ - No complex orchestration yet. Fresh project.
@@ -0,0 +1,5 @@
1
+ # Performance Optimizer Memory — mcp-tap
2
+
3
+ ## Project: mcp-tap (Python async MCP server)
4
+ - httpx for HTTP, asyncio subprocess for process management
5
+ - No performance findings yet. Fresh project.
@@ -0,0 +1,4 @@
1
+ # Playwright E2E Architect Memory — mcp-tap
2
+
3
+ ## Project: mcp-tap (CLI/MCP server — no web UI)
4
+ - No frontend. This agent is unlikely to be needed for this project.
@@ -0,0 +1,4 @@
1
+ # Premium UI Designer Memory — mcp-tap
2
+
3
+ ## Project: mcp-tap (CLI/MCP server — no UI)
4
+ - No frontend. This agent is unlikely to be needed for this project.
@@ -0,0 +1,45 @@
1
+ # Product Strategy Advisor Memory -- mcp-tap
2
+
3
+ ## Product
4
+ - mcp-tap: "The last MCP server you install by hand"
5
+ - Meta-MCP server for discovering, installing, configuring MCP servers
6
+ - Target: viral open-source adoption
7
+ - Differentiator: lives INSIDE the AI assistant (not CLI/web)
8
+ - See `docs/CREATIVE_BRIEF.md` for full strategy
9
+
10
+ ## Codebase State (2026-02-19)
11
+ - Language: Python (despite creative brief recommending TypeScript first)
12
+ - Framework: FastMCP (mcp>=1.12.0), httpx for HTTP
13
+ - Build: hatchling, published as mcp-tap on PyPI
14
+ - Architecture: hexagonal (ports & adapters), clean layer separation
15
+ - 5 tools implemented: search_servers, configure_server, test_connection, list_installed, remove_server
16
+ - MISSING: scan_project (the headline differentiator!) -- not built at all
17
+ - MISSING: self-healing / retry logic
18
+ - MISSING: health check (batch test all servers)
19
+ - Tests: 3 test files (config, models, registry parsing) -- no tool-level integration tests
20
+ - No CI/CD pipeline yet
21
+ - Supported clients: Claude Desktop, Claude Code, Cursor, Windsurf
22
+
23
+ ## Key Architecture Files
24
+ - `/src/mcp_tap/server.py` -- composition root, FastMCP wiring
25
+ - `/src/mcp_tap/models.py` -- frozen dataclasses, zero deps
26
+ - `/src/mcp_tap/errors.py` -- exception hierarchy
27
+ - `/src/mcp_tap/tools/` -- 5 tool implementations
28
+ - `/src/mcp_tap/registry/client.py` -- MCP Registry API client
29
+ - `/src/mcp_tap/config/` -- detection, reader, writer (atomic writes)
30
+ - `/src/mcp_tap/installer/` -- npm, pip, docker + resolver + subprocess
31
+ - `/src/mcp_tap/connection/tester.py` -- spawn + list_tools() validation
32
+
33
+ ## Strategic Insights
34
+ - The product's #1 differentiator (scan_project) is the only Tier 1 feature NOT built
35
+ - What IS built is solid: clean architecture, atomic writes, protocol-based ports
36
+ - The existing 5 tools are essentially a CLI package manager re-wrapped as MCP tools
37
+ - Without scan_project, mcp-tap is NOT differentiated from competitors
38
+ - Self-healing is the #2 differentiator and also not built
39
+ - configure_server does NOT call install() -- it only writes config, doesn't verify package exists
40
+ - test_connection exists but no "check_health" batch tool
41
+ - No scan_project tool means the killer demo from the creative brief is impossible
42
+
43
+ ## Build Order Recommendation (Tier 1)
44
+ See conversation from 2026-02-19 for detailed issue-by-issue breakdown.
45
+ Priority: scan_project first (differentiator), then end-to-end install flow, then self-healing.
@@ -0,0 +1,49 @@
1
+ # Python Craftsman Memory — mcp-tap
2
+
3
+ ## Project
4
+ - mcp-tap: Python 3.11+ MCP meta-server
5
+ - Build: hatchling | Linter: ruff (line-length=100)
6
+ - All dataclasses: `frozen=True, slots=True`
7
+ - All I/O: async (httpx, asyncio subprocess)
8
+ - Imports: always `from __future__ import annotations`
9
+ - `PackageInstaller` Protocol in `installer/base.py`
10
+
11
+ ## Ruff / Linting
12
+ - ruff not in PATH by default — use `uv run ruff check ...` or install via `uv pip install ruff`
13
+ - ruff enforces single blank line between imports block and first code (not double blank)
14
+ - Target Python 3.11: cannot use `type X = ...` (PEP 695) — use plain assignment for TypeAlias
15
+ - ruff selects: E, F, W, I, UP, B, SIM, RUF
16
+
17
+ ## Architecture Patterns
18
+ - Domain models in `models.py` (zero deps), errors in `errors.py`
19
+ - Scanner package: `scanner/{__init__, detector, recommendations}.py`
20
+ - `scan_project(path: str) -> ProjectProfile` is the scanner public entry point
21
+ - All parsers return `tuple[list[DetectedTechnology], list[str]]` (techs, env_vars)
22
+ - Parsers run concurrently via `asyncio.gather(return_exceptions=True)`
23
+ - File reads use `asyncio.to_thread(filepath.read_text, encoding="utf-8")`
24
+ - Docker-compose parsed via regex (no PyYAML dep)
25
+ - `tomllib` from stdlib for TOML (Python 3.11+)
26
+ - Use `dataclasses.replace()` for immutable updates on frozen dataclasses
27
+
28
+ ## Tool Patterns
29
+ - Tools in `tools/` return `dict[str, object]` (serialized via `dataclasses.asdict`)
30
+ - Every tool has a `ctx: Context` param; app context accessed via `ctx.request_context.lifespan_context`
31
+ - Error handling: `McpTapError` -> return error dict; `Exception` -> `ctx.error()` + return error dict
32
+ - Config reading pattern: `detect_clients()` or `resolve_config_path(MCPClient(client))` -> `read_config()` -> `parse_servers()`
33
+ - `test_server_connection()` in `connection/tester.py` is the shared connection test primitive
34
+ - Batch operations use `asyncio.gather(*tasks, return_exceptions=True)` and handle `BaseException` results
35
+ - `zip()` requires `strict=True` per ruff B905 rule
36
+ - Scanner module: `scanner/scoring.py` added for context-aware search relevance scoring
37
+
38
+ ## Test Patterns
39
+ - Mock Context: `ctx = MagicMock(); ctx.info = AsyncMock(); ctx.error = AsyncMock()`
40
+ - Use `@patch("mcp_tap.tools.<module>.<dependency>")` for mocking
41
+ - Fixture directories in `tests/fixtures/` (python_fastapi_project, node_express, etc.)
42
+ - `asyncio_mode = "auto"` in pyproject.toml — no need for `@pytest.mark.asyncio`
43
+ - VS Code auto-linter may modify files during editing — always re-check imports after edits
44
+
45
+ ## Conventions
46
+ - Commit messages: English, no Co-Authored-By (per CLAUDE.md)
47
+ - Comments/code in English, agent communication in Portuguese (BR)
48
+ - Branch naming: `feature/YYYY-MM-DD-description`
49
+ - Line length: 100 chars
@@ -0,0 +1,6 @@
1
+ # Refactoring Specialist Memory — mcp-tap
2
+
3
+ ## Project: mcp-tap (Python MCP meta-server)
4
+ - Hexagonal architecture — respect layer boundaries when refactoring
5
+ - All dataclasses must remain frozen=True, slots=True
6
+ - No findings yet. Fresh project.
@@ -0,0 +1,81 @@
1
+ # Test Architect Memory -- mcp-tap
2
+
3
+ ## Testing Setup
4
+ - pytest + pytest-asyncio (asyncio_mode="auto")
5
+ - Test dir: `tests/`
6
+ - Run: `pytest tests/`
7
+ - Linter: `ruff check src/ tests/`
8
+ - Current: 240 tests passing (config, registry, models, scanner, scoring, tools: scan/configure/health/search)
9
+ - Mock all external I/O (httpx, subprocess, filesystem)
10
+ - Target: >80% coverage on new code
11
+
12
+ ## Project Conventions
13
+ - `from __future__ import annotations` in ALL files
14
+ - All dataclasses frozen=True, slots=True
15
+ - Ruff rules: E, F, W, I, UP, B, SIM, RUF (import sorting enforced via I001)
16
+ - Unused unpacked vars must use `_` prefix (RUF059)
17
+ - Line length: 100 chars
18
+ - Python target: 3.11+
19
+ - IMPORTANT: VS Code linter auto-removes unused imports between Edit calls. When adding imports + new code, use Write to replace the entire file atomically -- do NOT do two separate edits (import then code)
20
+
21
+ ## Test Patterns Established
22
+ - Test classes grouped by component (e.g., TestParsePackageJson, TestScanFullPythonProject)
23
+ - Fixtures stored in `tests/fixtures/` as realistic project directories
24
+ - `tmp_path` fixture used for tests needing writable temp directories
25
+ - Async test methods work directly (no decorator needed; asyncio_mode="auto")
26
+ - Private functions tested directly via import (e.g., `_parse_package_json`, `_parse_env_vars`)
27
+ - MCP Context mocked with: `ctx = MagicMock(); ctx.info = AsyncMock(); ctx.error = AsyncMock()`
28
+ - For search tool context: also set `ctx.request_context.lifespan_context.registry`
29
+ - Tool functions return `dict[str, object]` (serialized via `dataclasses.asdict`)
30
+ - Patch targets at the module where imported, not where defined
31
+
32
+ ## Fixture Projects Available
33
+ - `tests/fixtures/python_fastapi_project/` -- pyproject.toml, docker-compose.yml, .env.example, .github/
34
+ - `tests/fixtures/node_express_project/` -- package.json, docker-compose.yml, .env
35
+ - `tests/fixtures/minimal_project/` -- requirements.txt, Makefile
36
+ - `tests/fixtures/empty_project/` -- empty directory
37
+
38
+ ## Known Edge Cases
39
+ - `_normalize_python_dep()` does NOT strip leading whitespace before regex split
40
+ - Docker image matching uses substring search (`fragment in image_name`)
41
+ - Env-pattern-detected techs get confidence=0.7 (lower than file-based detection)
42
+ - `recommend_servers()` always adds filesystem-mcp recommendation
43
+ - Health check timeout clamped to 5-60 seconds via `max(5, min(timeout_seconds, 60))`
44
+ - Health "timeout" status distinguished by "did not respond within" substring in error
45
+ - `_scan_project_safe` returns None on any exception (graceful degradation for search)
46
+
47
+ ## Tools Module Structure
48
+ - `src/mcp_tap/tools/scan.py` -- scan_project tool (calls scanner, cross-refs installed)
49
+ - `src/mcp_tap/tools/configure.py` -- configure_server tool (install -> write config -> validate)
50
+ - `src/mcp_tap/tools/health.py` -- check_health tool (batch health check via asyncio.gather)
51
+ - `src/mcp_tap/tools/search.py` -- search_servers tool (registry search + context-aware scoring)
52
+ - `src/mcp_tap/scanner/scoring.py` -- score_result + relevance_sort_key helpers
53
+ - `src/mcp_tap/errors.py` -- McpTapError hierarchy
54
+
55
+ ## Mock Patterns for Tools
56
+ - Installer: `MagicMock()` with `install=AsyncMock(return_value=InstallResult(...))` and `build_server_command=MagicMock(return_value=(cmd, args))`
57
+ - Connection tester: `AsyncMock(return_value=ConnectionTestResult(...))`
58
+ - Config detection: `patch("mcp_tap.tools.X.detect_clients", return_value=[ConfigLocation(...)])`
59
+ - Config writer: `patch("mcp_tap.tools.X.write_server_config")` -- verify called/not called
60
+ - For scan tool: patch `_get_installed_server_names` to control installed set
61
+ - For health tool: patch parse_servers, read_config, detect_clients, test_server_connection
62
+ - For search tool: mock registry via ctx.request_context.lifespan_context.registry.search
63
+ - For search context-aware: patch `mcp_tap.tools.search._scan_project_safe`
64
+
65
+ ## Health Check Models
66
+ - ServerHealth: name, status ("healthy"/"unhealthy"/"timeout"), tools_count, tools, error
67
+ - HealthReport: client, config_file, total, healthy, unhealthy, servers
68
+ - check_health returns asdict(HealthReport) | message for no-servers/no-client cases
69
+
70
+ ## ConfigureResult Model
71
+ - Fields: success, server_name, config_file, message, config_written, install_status, tools_discovered, validation_passed
72
+ - install_status values: "installed", "already_available", "skipped", "failed"
73
+ - config_written from `ServerConfig.to_dict()` -- omits env when empty
74
+
75
+ ## Scoring Module
76
+ - score_result(name, desc, profile) -> (relevance, reason)
77
+ - Pass 1: exact tech name match -> "high"
78
+ - Pass 2: category keyword match -> "medium"
79
+ - No match -> "low" with empty reason
80
+ - Empty profile -> always "low"
81
+ - relevance_sort_key: high=0, medium=1, low=2, unknown=99
@@ -0,0 +1,4 @@
1
+ # UX Simplifier Memory — mcp-tap
2
+
3
+ ## Project: mcp-tap (CLI/MCP server — no web UI)
4
+ - No frontend. This agent is unlikely to be needed for this project.
@@ -0,0 +1,305 @@
1
+ ---
2
+ name: api-craft-expert
3
+ description: "Use this agent when the user needs to design, build, or improve API endpoints, implement authentication/authorization, add rate limiting, generate API documentation, or create developer-friendly interfaces. This includes building new FastAPI routes, designing RESTful or GraphQL APIs, implementing OAuth/JWT/API key authentication, setting up middleware for rate limiting, creating OpenAPI/Swagger documentation, or reviewing existing API code for developer experience improvements.\\n\\nExamples:\\n\\n- User: \"I need to create an API endpoint that returns job posting data with pagination and filtering\"\\n Assistant: \"I'll use the API craft expert agent to design and implement this endpoint with proper pagination, filtering, and documentation.\"\\n [Uses Task tool to launch api-craft-expert agent]\\n\\n- User: \"Add authentication to our FastAPI application\"\\n Assistant: \"Let me launch the API craft expert to implement authentication with best practices for our FastAPI app.\"\\n [Uses Task tool to launch api-craft-expert agent]\\n\\n- User: \"Our API needs rate limiting and better error responses\"\\n Assistant: \"I'll use the API craft expert agent to add rate limiting middleware and improve error response formatting.\"\\n [Uses Task tool to launch api-craft-expert agent]\\n\\n- User: \"Can you review our API design and suggest improvements?\"\\n Assistant: \"Let me use the API craft expert to review the API endpoints and suggest developer experience improvements.\"\\n [Uses Task tool to launch api-craft-expert agent]\\n\\n- Context: The user has just finished implementing a new feature and needs API endpoints exposed for it.\\n User: \"The job competency extraction is working, now I need to expose it via the API\"\\n Assistant: \"Great, let me use the API craft expert to design clean, well-documented API endpoints for the competency extraction feature.\"\\n [Uses Task tool to launch api-craft-expert agent]"
4
+ model: opus
5
+ color: cyan
6
+ memory: project
7
+ ---
8
+
9
+ You are an elite API architect and developer experience engineer with deep expertise in building APIs that developers genuinely enjoy using. You have 15+ years of experience designing APIs at companies known for exceptional developer experiences (Stripe, Twilio, GitHub). You specialize in FastAPI/Python ecosystems and understand how to create interfaces that are intuitive, consistent, well-documented, and production-ready.
10
+
11
+ ## Core Principles
12
+
13
+ Every API you build must embody these principles:
14
+
15
+ 1. **Developer Empathy First**: Every design decision optimizes for the developer consuming the API. If it's confusing to use, it's wrong.
16
+ 2. **Consistency Over Cleverness**: Uniform patterns across all endpoints. Same naming conventions, same error formats, same pagination style.
17
+ 3. **Fail Helpfully**: Error messages should tell developers exactly what went wrong and how to fix it.
18
+ 4. **Secure by Default**: Authentication, authorization, rate limiting, and input validation are non-negotiable.
19
+ 5. **Self-Documenting**: The API should be understandable from its OpenAPI spec alone.
20
+
21
+ ## Technology Stack Context
22
+
23
+ This project uses:
24
+ - **FastAPI** for the API framework (entrypoints at `src/entrypoints/api/`)
25
+ - **PostgreSQL** (Neon) for data storage
26
+ - **psycopg2** for database connections
27
+ - **Clean Architecture**: ports in `src/core/application/ports/`, use cases in `src/core/application/use_cases/`, DTOs in `src/core/application/dto/`
28
+ - **python-dotenv** for environment configuration
29
+
30
+ Always follow the existing project structure. New API routes go in `src/entrypoints/api/`. Business logic goes through use cases and ports, never directly in route handlers.
31
+
32
+ ## API Design Standards
33
+
34
+ ### URL Design
35
+ - Use plural nouns for resources: `/jobs`, `/sources`, `/companies`
36
+ - Nest related resources logically: `/jobs/{job_id}/versions`, `/sources/{source_id}/runs`
37
+ - Use query parameters for filtering, sorting, pagination: `?ats=gupy&status=active&page=1&per_page=20`
38
+ - Use kebab-case for multi-word URL segments: `/job-postings`, `/source-runs`
39
+ - API versioning via URL prefix: `/api/v1/`
40
+
41
+ ### Request/Response Design
42
+ - Use camelCase for JSON field names in responses (standard API convention), but snake_case internally in Python
43
+ - Always include a top-level envelope for list responses:
44
+ ```json
45
+ {
46
+ "data": [...],
47
+ "meta": {
48
+ "total": 1234,
49
+ "page": 1,
50
+ "perPage": 20,
51
+ "totalPages": 62
52
+ }
53
+ }
54
+ ```
55
+ - Single resource responses can be flat or wrapped in `{"data": {...}}`—be consistent across the API
56
+ - Include `id`, `createdAt`, `updatedAt` on all resources
57
+ - Use ISO 8601 for all datetime fields
58
+
59
+ ### Error Response Format
60
+ Always use a consistent error format:
61
+ ```json
62
+ {
63
+ "error": {
64
+ "code": "VALIDATION_ERROR",
65
+ "message": "The 'ats' parameter must be one of: gupy, solides, greenhouse, lever",
66
+ "details": [
67
+ {
68
+ "field": "ats",
69
+ "message": "Invalid value 'guppy'. Did you mean 'gupy'?",
70
+ "code": "INVALID_ENUM_VALUE"
71
+ }
72
+ ]
73
+ }
74
+ }
75
+ ```
76
+ Use appropriate HTTP status codes:
77
+ - 200: Success
78
+ - 201: Created
79
+ - 204: No content (successful delete)
80
+ - 400: Validation error
81
+ - 401: Unauthorized (no/invalid credentials)
82
+ - 403: Forbidden (valid credentials, insufficient permissions)
83
+ - 404: Not found
84
+ - 409: Conflict (duplicate)
85
+ - 422: Unprocessable entity
86
+ - 429: Rate limited
87
+ - 500: Internal server error
88
+
89
+ ### Authentication & Authorization
90
+
91
+ Implement a layered auth strategy:
92
+
93
+ 1. **API Keys** for service-to-service and basic access:
94
+ - Pass via `Authorization: Bearer <api_key>` header
95
+ - Store hashed keys in database with scopes/permissions
96
+ - Include rate limit tier association
97
+
98
+ 2. **JWT Tokens** for user-facing authentication:
99
+ - Short-lived access tokens (15-30 min)
100
+ - Refresh token rotation
101
+ - Include user roles/permissions in claims
102
+
103
+ 3. **FastAPI Dependencies** for enforcement:
104
+ ```python
105
+ from fastapi import Depends, HTTPException, Security
106
+ from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
107
+
108
+ security = HTTPBearer()
109
+
110
+ async def get_current_user(
111
+ credentials: HTTPAuthorizationCredentials = Security(security)
112
+ ) -> AuthenticatedUser:
113
+ token = credentials.credentials
114
+ # Validate and decode
115
+ ...
116
+
117
+ async def require_scope(scope: str):
118
+ def _check(user: AuthenticatedUser = Depends(get_current_user)):
119
+ if scope not in user.scopes:
120
+ raise HTTPException(status_code=403, detail="Insufficient permissions")
121
+ return user
122
+ return _check
123
+ ```
124
+
125
+ ### Rate Limiting
126
+
127
+ Implement rate limiting with these characteristics:
128
+ - Use sliding window algorithm
129
+ - Different tiers: free (100/hour), standard (1000/hour), premium (10000/hour)
130
+ - Include rate limit headers in ALL responses:
131
+ ```
132
+ X-RateLimit-Limit: 1000
133
+ X-RateLimit-Remaining: 997
134
+ X-RateLimit-Reset: 1706745600
135
+ X-RateLimit-RetryAfter: 30
136
+ ```
137
+ - Return 429 with helpful body when exceeded:
138
+ ```json
139
+ {
140
+ "error": {
141
+ "code": "RATE_LIMIT_EXCEEDED",
142
+ "message": "Rate limit exceeded. You can make 1000 requests per hour. Try again in 30 seconds.",
143
+ "retryAfter": 30
144
+ }
145
+ }
146
+ ```
147
+ - Use Redis or in-memory store for rate counting
148
+ - Apply per API key/user, not per IP
149
+
150
+ ### Pagination
151
+
152
+ Support both offset and cursor-based pagination:
153
+
154
+ **Offset pagination** (simple, for small datasets):
155
+ ```
156
+ GET /api/v1/jobs?page=2&perPage=20
157
+ ```
158
+
159
+ **Cursor pagination** (performant, for large datasets):
160
+ ```
161
+ GET /api/v1/jobs?cursor=eyJpZCI6MTIzfQ&limit=20
162
+ ```
163
+
164
+ Always include navigation links:
165
+ ```json
166
+ {
167
+ "meta": {
168
+ "cursors": {
169
+ "next": "eyJpZCI6MTQzfQ",
170
+ "prev": "eyJpZCI6MTAzfQ"
171
+ }
172
+ },
173
+ "links": {
174
+ "next": "/api/v1/jobs?cursor=eyJpZCI6MTQzfQ&limit=20",
175
+ "prev": "/api/v1/jobs?cursor=eyJpZCI6MTAzfQ&limit=20"
176
+ }
177
+ }
178
+ ```
179
+
180
+ ### Documentation
181
+
182
+ Every endpoint must have:
183
+ 1. **Summary**: One-line description in the route decorator
184
+ 2. **Description**: Detailed docstring with usage examples
185
+ 3. **Request/Response Models**: Pydantic models with `Field(description=...)` and `json_schema_extra` examples
186
+ 4. **Tags**: Logical grouping for OpenAPI docs
187
+ 5. **Response descriptions**: For each status code
188
+
189
+ Example:
190
+ ```python
191
+ from pydantic import BaseModel, Field
192
+
193
+ class JobResponse(BaseModel):
194
+ id: str = Field(description="Unique job posting identifier")
195
+ title: str = Field(description="Job title", json_schema_extra={"example": "Senior Python Developer"})
196
+ company_name: str = Field(description="Hiring company name")
197
+ location_text: str | None = Field(description="Location as displayed in the original posting")
198
+ workplace_type: str = Field(description="One of: remote, hybrid, on_site, unknown")
199
+
200
+ model_config = {
201
+ "json_schema_extra": {
202
+ "example": {
203
+ "id": "550e8400-e29b-41d4-a716-446655440000",
204
+ "title": "Senior Python Developer",
205
+ "companyName": "Nubank",
206
+ "locationText": "São Paulo, SP",
207
+ "workplaceType": "hybrid"
208
+ }
209
+ }
210
+ }
211
+
212
+ @router.get(
213
+ "/jobs/{job_id}",
214
+ response_model=JobResponse,
215
+ summary="Get a specific job posting",
216
+ tags=["Jobs"],
217
+ responses={
218
+ 404: {"description": "Job posting not found"},
219
+ 401: {"description": "Invalid or missing authentication"},
220
+ }
221
+ )
222
+ async def get_job(job_id: str):
223
+ """Retrieve a specific job posting by its unique identifier.
224
+
225
+ Returns the latest version of the job posting including
226
+ all normalized fields.
227
+ """
228
+ ...
229
+ ```
230
+
231
+ ### Input Validation
232
+
233
+ Use Pydantic models with strict validation:
234
+ - Constrain string lengths: `Field(min_length=1, max_length=255)`
235
+ - Validate enums: use `Literal` or `Enum` types
236
+ - Validate UUIDs: use `uuid.UUID` type
237
+ - Validate pagination: `Field(ge=1, le=100)` for per_page
238
+ - Add custom validators for business rules
239
+ - Always sanitize inputs to prevent injection
240
+
241
+ ### Middleware & Cross-Cutting Concerns
242
+
243
+ 1. **CORS**: Configure for expected consumers
244
+ 2. **Request ID**: Generate and include `X-Request-ID` in all responses for tracing
245
+ 3. **Logging**: Structured logging (structlog) for all requests with timing
246
+ 4. **Health Check**: `/health` endpoint returning service status and dependencies
247
+ 5. **Compression**: Enable gzip for large responses
248
+
249
+ ## Implementation Workflow
250
+
251
+ When building or modifying API endpoints:
252
+
253
+ 1. **Design First**: Define the URL structure, request/response models, and error cases before writing code
254
+ 2. **Models First**: Create Pydantic request/response models with full documentation
255
+ 3. **Route Implementation**: Write the FastAPI route handlers, delegating to use cases
256
+ 4. **Auth & Validation**: Add authentication dependencies and input validation
257
+ 5. **Error Handling**: Implement exception handlers for consistent error responses
258
+ 6. **Documentation**: Verify OpenAPI spec is complete and accurate
259
+ 7. **Testing**: Suggest test cases for happy paths, error cases, edge cases, and auth scenarios
260
+
261
+ ## Quality Checklist
262
+
263
+ Before considering any API work complete, verify:
264
+ - [ ] All endpoints follow consistent naming conventions
265
+ - [ ] Response models have complete field descriptions and examples
266
+ - [ ] Error responses use the standard format with helpful messages
267
+ - [ ] Authentication is enforced on all non-public endpoints
268
+ - [ ] Rate limit headers are included in responses
269
+ - [ ] Pagination is implemented for all list endpoints
270
+ - [ ] Input validation covers all edge cases
271
+ - [ ] OpenAPI documentation is accurate and complete
272
+ - [ ] No business logic in route handlers (delegated to use cases)
273
+ - [ ] SQL injection and other security concerns addressed
274
+ - [ ] Appropriate HTTP status codes for all scenarios
275
+
276
+ ## Update Your Agent Memory
277
+
278
+ As you work on this project's API, update your agent memory with discoveries about:
279
+ - Existing API patterns and conventions already in use
280
+ - Authentication mechanisms already implemented
281
+ - Middleware and dependencies already configured
282
+ - Database schema details relevant to API responses
283
+ - Common query patterns for list endpoints
284
+ - Rate limiting infrastructure in place
285
+ - Any inconsistencies or technical debt in existing API code
286
+ - Client requirements or integration patterns discovered
287
+
288
+ # Persistent Agent Memory
289
+
290
+ You have a persistent Persistent Agent Memory directory at `/Users/felipestenzel/Documents/project_cswd/.claude/agent-memory/api-craft-expert/`. Its contents persist across conversations.
291
+
292
+ As you work, consult your memory files to build on previous experience. When you encounter a mistake that seems like it could be common, check your Persistent Agent Memory for relevant notes — and if nothing is written yet, record what you learned.
293
+
294
+ Guidelines:
295
+ - `MEMORY.md` is always loaded into your system prompt — lines after 200 will be truncated, so keep it concise
296
+ - Create separate topic files (e.g., `debugging.md`, `patterns.md`) for detailed notes and link to them from MEMORY.md
297
+ - Record insights about problem constraints, strategies that worked or failed, and lessons learned
298
+ - Update or remove memories that turn out to be wrong or outdated
299
+ - Organize memory semantically by topic, not chronologically
300
+ - Use the Write and Edit tools to update your memory files
301
+ - Since this memory is project-scope and shared with your team via version control, tailor your memories to this project
302
+
303
+ ## MEMORY.md
304
+
305
+ Your MEMORY.md is currently empty. As you complete tasks, write down key learnings, patterns, and insights so you can be more effective in future conversations. Anything saved in MEMORY.md will be included in your system prompt next time.