mcp-common 0.2.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.
- mcp_common-0.2.0/.github/FUNDING.yml +1 -0
- mcp_common-0.2.0/.gitignore +72 -0
- mcp_common-0.2.0/.pre-commit-config.yaml +102 -0
- mcp_common-0.2.0/CLAUDE.md +528 -0
- mcp_common-0.2.0/LICENSE +28 -0
- mcp_common-0.2.0/PKG-INFO +568 -0
- mcp_common-0.2.0/README.md +508 -0
- mcp_common-0.2.0/docs/ACB_FOUNDATION.md +789 -0
- mcp_common-0.2.0/docs/ARCHITECTURE.md +1482 -0
- mcp_common-0.2.0/docs/EXCEPTION_SUPPRESSION_ACTION_PLAN.md +233 -0
- mcp_common-0.2.0/docs/IMPLEMENTATION_PLAN.md +1497 -0
- mcp_common-0.2.0/docs/IMPORT_DETECTION_MIGRATION.md +542 -0
- mcp_common-0.2.0/docs/INTEGRATION_TRACKING.md +672 -0
- mcp_common-0.2.0/docs/MCP_ECOSYSTEM_CRITICAL_AUDIT.md +1693 -0
- mcp_common-0.2.0/docs/MCP_SERVERS_INTEGRATION_SUMMARY.md +726 -0
- mcp_common-0.2.0/docs/PHASE3_3_M2_PROGRESS.md +263 -0
- mcp_common-0.2.0/docs/PHASE3_3_M3_RFC.md +338 -0
- mcp_common-0.2.0/docs/PHASE3_ARCHITECTURE_REVIEW.md +755 -0
- mcp_common-0.2.0/docs/PHASE3_COMPLETION_SUMMARY.md +451 -0
- mcp_common-0.2.0/docs/PHASE3_CONSOLIDATED_REVIEW.md +862 -0
- mcp_common-0.2.0/docs/PHASE4_10_RFC.md +793 -0
- mcp_common-0.2.0/docs/PLAN_STATUS.md +221 -0
- mcp_common-0.2.0/docs/RATE_LIMIT_CONFIG_MIGRATION.md +501 -0
- mcp_common-0.2.0/docs/RATE_LIMIT_LOAD_TESTING.md +455 -0
- mcp_common-0.2.0/docs/SECURITY_IMPLEMENTATION.md +531 -0
- mcp_common-0.2.0/examples/README.md +275 -0
- mcp_common-0.2.0/examples/settings/weather.yaml +26 -0
- mcp_common-0.2.0/examples/weather_server.py +241 -0
- mcp_common-0.2.0/mcp_common/__init__.py +74 -0
- mcp_common-0.2.0/mcp_common/adapters/__init__.py +10 -0
- mcp_common-0.2.0/mcp_common/adapters/http/__init__.py +10 -0
- mcp_common-0.2.0/mcp_common/adapters/http/client.py +266 -0
- mcp_common-0.2.0/mcp_common/config/__init__.py +11 -0
- mcp_common-0.2.0/mcp_common/config/base.py +367 -0
- mcp_common-0.2.0/mcp_common/config/validation_mixin.py +258 -0
- mcp_common-0.2.0/mcp_common/exceptions.py +241 -0
- mcp_common-0.2.0/mcp_common/health.py +188 -0
- mcp_common-0.2.0/mcp_common/http_health.py +322 -0
- mcp_common-0.2.0/mcp_common/middleware/__init__.py +25 -0
- mcp_common-0.2.0/mcp_common/middleware/rate_limit_config.py +222 -0
- mcp_common-0.2.0/mcp_common/py.typed +0 -0
- mcp_common-0.2.0/mcp_common/security/__init__.py +23 -0
- mcp_common-0.2.0/mcp_common/security/api_keys.py +342 -0
- mcp_common-0.2.0/mcp_common/security/sanitization.py +279 -0
- mcp_common-0.2.0/mcp_common/ui/__init__.py +10 -0
- mcp_common-0.2.0/mcp_common/ui/panels.py +333 -0
- mcp_common-0.2.0/pyproject.toml +294 -0
- mcp_common-0.2.0/tests/__init__.py +1 -0
- mcp_common-0.2.0/tests/conftest.py +80 -0
- mcp_common-0.2.0/tests/performance/test_rate_limits_load.py +334 -0
- mcp_common-0.2.0/tests/test_config.py +328 -0
- mcp_common-0.2.0/tests/test_config_security.py +466 -0
- mcp_common-0.2.0/tests/test_config_validation_mixin.py +359 -0
- mcp_common-0.2.0/tests/test_health.py +328 -0
- mcp_common-0.2.0/tests/test_http_client.py +267 -0
- mcp_common-0.2.0/tests/test_http_health.py +356 -0
- mcp_common-0.2.0/tests/test_rate_limit_config.py +329 -0
- mcp_common-0.2.0/tests/test_security_api_keys.py +381 -0
- mcp_common-0.2.0/tests/test_security_sanitization.py +446 -0
- mcp_common-0.2.0/tests/test_ui_panels.py +251 -0
- mcp_common-0.2.0/tests/test_version.py +8 -0
- mcp_common-0.2.0/uv.lock +4819 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
github: [lesleslie]
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
MANIFEST
|
|
23
|
+
|
|
24
|
+
# Virtual environments
|
|
25
|
+
venv/
|
|
26
|
+
ENV/
|
|
27
|
+
env/
|
|
28
|
+
.venv/
|
|
29
|
+
|
|
30
|
+
# Testing
|
|
31
|
+
.pytest_cache/
|
|
32
|
+
.coverage
|
|
33
|
+
.coverage.*
|
|
34
|
+
htmlcov/
|
|
35
|
+
.tox/
|
|
36
|
+
.nox/
|
|
37
|
+
coverage.xml
|
|
38
|
+
*.cover
|
|
39
|
+
.hypothesis/
|
|
40
|
+
|
|
41
|
+
# Type checking
|
|
42
|
+
.mypy_cache/
|
|
43
|
+
.dmypy.json
|
|
44
|
+
dmypy.json
|
|
45
|
+
.pytype/
|
|
46
|
+
|
|
47
|
+
# IDEs
|
|
48
|
+
.vscode/
|
|
49
|
+
.idea/
|
|
50
|
+
*.swp
|
|
51
|
+
*.swo
|
|
52
|
+
*~
|
|
53
|
+
.DS_Store
|
|
54
|
+
|
|
55
|
+
# Ruff
|
|
56
|
+
.ruff_cache/
|
|
57
|
+
|
|
58
|
+
# Environment
|
|
59
|
+
.env
|
|
60
|
+
.env.local
|
|
61
|
+
.env.*.local
|
|
62
|
+
|
|
63
|
+
# Documentation builds
|
|
64
|
+
docs/_build/
|
|
65
|
+
site/
|
|
66
|
+
|
|
67
|
+
# Hatch
|
|
68
|
+
.hatch/
|
|
69
|
+
/.benchmarks/
|
|
70
|
+
/.claude/
|
|
71
|
+
/.envrc
|
|
72
|
+
/.mcp.json
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: local
|
|
3
|
+
hooks:
|
|
4
|
+
- id: validate-regex-patterns
|
|
5
|
+
name: validate-regex-patterns
|
|
6
|
+
entry: uv run python -m crackerjack.tools.validate_regex_patterns
|
|
7
|
+
language: system
|
|
8
|
+
files: \.py$
|
|
9
|
+
exclude: ^\.venv/|^src/
|
|
10
|
+
- id: skylos
|
|
11
|
+
name: skylos-dead-code-detection
|
|
12
|
+
entry: skylos
|
|
13
|
+
language: system
|
|
14
|
+
args: ["mcp_common", "--exclude", "tests"]
|
|
15
|
+
pass_filenames: false
|
|
16
|
+
exclude: ^tests/|^src/
|
|
17
|
+
stages: ["pre-push", "manual"]
|
|
18
|
+
- id: zuban
|
|
19
|
+
name: zuban-type-checking
|
|
20
|
+
entry: uv run zuban check
|
|
21
|
+
language: system
|
|
22
|
+
args: ["--config-file", "mypy.ini", "./mcp_common"]
|
|
23
|
+
pass_filenames: false
|
|
24
|
+
exclude: ^tests/|^src/
|
|
25
|
+
stages: ["pre-push", "manual"]
|
|
26
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
27
|
+
rev: v6.0.0
|
|
28
|
+
hooks:
|
|
29
|
+
- id: trailing-whitespace
|
|
30
|
+
name: trailing-whitespace
|
|
31
|
+
exclude: ^\.venv/|^src/
|
|
32
|
+
- id: end-of-file-fixer
|
|
33
|
+
name: end-of-file-fixer
|
|
34
|
+
exclude: ^\.venv/|^src/
|
|
35
|
+
- id: check-yaml
|
|
36
|
+
name: check-yaml
|
|
37
|
+
exclude: ^\.venv/|^src/
|
|
38
|
+
- id: check-toml
|
|
39
|
+
name: check-toml
|
|
40
|
+
exclude: ^\.venv/|^src/
|
|
41
|
+
- id: check-added-large-files
|
|
42
|
+
name: check-added-large-files
|
|
43
|
+
exclude: ^\.venv/|^src/
|
|
44
|
+
- repo: https://github.com/astral-sh/uv-pre-commit
|
|
45
|
+
rev: 0.9.0
|
|
46
|
+
hooks:
|
|
47
|
+
- id: uv-lock
|
|
48
|
+
files: ^ pyproject\.toml$
|
|
49
|
+
exclude: ^src/
|
|
50
|
+
- repo: https://github.com/gitleaks/gitleaks
|
|
51
|
+
rev: v8.28.0
|
|
52
|
+
hooks:
|
|
53
|
+
- id: gitleaks
|
|
54
|
+
exclude: uv\.lock|pyproject\.toml|tests/.*|docs/.*|\.claude/.*|.*\.md|^src/
|
|
55
|
+
- repo: https://github.com/PyCQA/bandit
|
|
56
|
+
rev: 1.8.6
|
|
57
|
+
hooks:
|
|
58
|
+
- id: bandit
|
|
59
|
+
args: ["-c", "pyproject.toml", "-r", "-ll"]
|
|
60
|
+
files: ^mcp_common/.*\.py$
|
|
61
|
+
exclude: ^tests/|^src/
|
|
62
|
+
stages: ["pre-push", "manual"]
|
|
63
|
+
- repo: https://github.com/codespell-project/codespell
|
|
64
|
+
rev: v2.4.1
|
|
65
|
+
hooks:
|
|
66
|
+
- id: codespell
|
|
67
|
+
exclude: ^\.venv/|^src/
|
|
68
|
+
additional_dependencies: ["tomli"]
|
|
69
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
70
|
+
rev: v0.14.0
|
|
71
|
+
hooks:
|
|
72
|
+
- id: ruff-check
|
|
73
|
+
exclude: ^\.venv/|^src/
|
|
74
|
+
- id: ruff-format
|
|
75
|
+
exclude: ^\.venv/|^src/
|
|
76
|
+
- repo: https://github.com/executablebooks/mdformat
|
|
77
|
+
rev: 0.7.22
|
|
78
|
+
hooks:
|
|
79
|
+
- id: mdformat
|
|
80
|
+
exclude: ^\.venv/|^src/
|
|
81
|
+
additional_dependencies: ["mdformat-ruff"]
|
|
82
|
+
- repo: https://github.com/fredrikaverpil/creosote
|
|
83
|
+
rev: v4.1.0
|
|
84
|
+
hooks:
|
|
85
|
+
- id: creosote
|
|
86
|
+
exclude: ^\.venv/|^src/
|
|
87
|
+
stages: ["pre-push", "manual"]
|
|
88
|
+
- repo: https://github.com/rohaquinlop/complexipy-pre-commit
|
|
89
|
+
rev: v3.3.0
|
|
90
|
+
hooks:
|
|
91
|
+
- id: complexipy
|
|
92
|
+
args: ["-d", "low", "--max-complexity-allowed", "15"]
|
|
93
|
+
files: ^mcp_common/.*\.py$
|
|
94
|
+
exclude: ^(\.venv/|tests/)|^src/
|
|
95
|
+
stages: ["pre-push", "manual"]
|
|
96
|
+
- repo: https://github.com/dosisod/refurb
|
|
97
|
+
rev: v2.2.0
|
|
98
|
+
hooks:
|
|
99
|
+
- id: refurb
|
|
100
|
+
files: ^mcp_common/.*\.py$
|
|
101
|
+
exclude: ^tests/|^src/
|
|
102
|
+
stages: ["pre-push", "manual"]
|
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
**mcp-common** is an ACB-native foundation library for building production-grade MCP (Model Context Protocol) servers. It provides battle-tested patterns extracted from 9 production servers including crackerjack, session-mgmt-mcp, and fastblocks.
|
|
8
|
+
|
|
9
|
+
**Current Status:** v2.0.0 - **Partially Implemented**
|
|
10
|
+
|
|
11
|
+
- ✅ Core package structure complete
|
|
12
|
+
- ✅ MCPBaseSettings with YAML + environment variable support
|
|
13
|
+
- ✅ HTTPClientAdapter with connection pooling (implemented)
|
|
14
|
+
- ✅ ServerPanels for Rich UI (implemented)
|
|
15
|
+
- ✅ Security utilities (API key validation, sanitization)
|
|
16
|
+
- ✅ Health check system (HTTP connectivity, component health)
|
|
17
|
+
- ✅ Exception hierarchy (MCPServerError, validation errors)
|
|
18
|
+
- ✅ ValidationMixin for Pydantic models
|
|
19
|
+
- ✅ Comprehensive test suite with 90%+ coverage
|
|
20
|
+
- 🚧 Rate limiting adapter (in middleware/rate_limit_config.py, needs ACB migration)
|
|
21
|
+
- 🚧 Complete example server (`examples/weather_server.py`)
|
|
22
|
+
|
|
23
|
+
## Critical Prerequisites
|
|
24
|
+
|
|
25
|
+
### ACB Framework Dependency
|
|
26
|
+
|
|
27
|
+
This library is **ACB-native**, meaning it is built **on top of ACB**, not as a standalone utility:
|
|
28
|
+
|
|
29
|
+
- **ACB (Asynchronous Component Base)** provides: adapters, dependency injection, structured logging, settings, console
|
|
30
|
+
- **mcp-common** provides: MCP-specific adapters built using ACB patterns
|
|
31
|
+
- **Relationship:** mcp-common extends ACB for MCP server use cases
|
|
32
|
+
|
|
33
|
+
**ACB is installed as an editable dependency** from `../acb`:
|
|
34
|
+
|
|
35
|
+
```toml
|
|
36
|
+
[tool.uv.sources]
|
|
37
|
+
acb = { path = "../acb", editable = true }
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This means changes to the ACB project at `../acb` are immediately reflected in mcp-common.
|
|
41
|
+
|
|
42
|
+
**IMPORTANT:** Before implementing any adapter, read `docs/ACB_FOUNDATION.md` to understand:
|
|
43
|
+
|
|
44
|
+
- ACB adapter lifecycle (MODULE_ID, MODULE_STATUS, MODULE_METADATA)
|
|
45
|
+
- Dependency injection with `acb.depends`
|
|
46
|
+
- Logger injection via `LoggerProtocol`
|
|
47
|
+
- Settings extending `acb.config.Settings`
|
|
48
|
+
|
|
49
|
+
### Reference Implementations
|
|
50
|
+
|
|
51
|
+
The design is extracted from these production servers (located in `../` relative to this repo):
|
|
52
|
+
|
|
53
|
+
**Primary Pattern Sources:**
|
|
54
|
+
|
|
55
|
+
- **crackerjack** (`../crackerjack/mcp/`) - Rate limiting adapter, Rich UI panels (ServerPanels), MCP server structure, tool organization
|
|
56
|
+
- **session-mgmt-mcp** (`../session-mgmt-mcp/`) - ACB Settings with YAML configuration, comprehensive DI usage, adapter lifecycle patterns
|
|
57
|
+
- **fastblocks** (`../fastblocks/`) - ACB adapter organization, module structure
|
|
58
|
+
|
|
59
|
+
**Key Patterns from Production Servers:**
|
|
60
|
+
|
|
61
|
+
- **Rate Limiting:** `crackerjack/mcp/rate_limiter.py` - Token bucket algorithm implementation
|
|
62
|
+
- **Rich UI Panels:** `crackerjack/ui/` - Professional console output with Rich library
|
|
63
|
+
- **Tool Registration:** `crackerjack/mcp/` - FastMCP tool organization patterns
|
|
64
|
+
- **Structured Logging:** Uses ACB logger with correlation IDs and context binding
|
|
65
|
+
- **MCP Server Structure:** Clean separation of concerns (tools, adapters, settings)
|
|
66
|
+
|
|
67
|
+
When implementing adapters, **always reference these codebases** for proven ACB patterns. Don't guess at ACB patterns - look at working production code.
|
|
68
|
+
|
|
69
|
+
## Development Commands
|
|
70
|
+
|
|
71
|
+
### Environment Setup
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Install with development dependencies (recommended)
|
|
75
|
+
uv sync --group dev
|
|
76
|
+
|
|
77
|
+
# Or with pip
|
|
78
|
+
pip install -e ".[dev]"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Testing
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Run all tests with coverage (requires 90% minimum)
|
|
85
|
+
uv run pytest
|
|
86
|
+
|
|
87
|
+
# Run specific test file
|
|
88
|
+
uv run pytest tests/test_config.py -v
|
|
89
|
+
|
|
90
|
+
# Run with coverage report
|
|
91
|
+
uv run pytest --cov=mcp_common --cov-report=html
|
|
92
|
+
|
|
93
|
+
# Run only unit tests
|
|
94
|
+
uv run pytest -m unit
|
|
95
|
+
|
|
96
|
+
# Run only integration tests
|
|
97
|
+
uv run pytest -m integration
|
|
98
|
+
|
|
99
|
+
# Skip slow tests (performance benchmarks)
|
|
100
|
+
uv run pytest -m "not slow"
|
|
101
|
+
|
|
102
|
+
# Run specific test by name
|
|
103
|
+
uv run pytest tests/test_http_client.py::test_connection_pooling -v
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Code Quality
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# Format code (Ruff)
|
|
110
|
+
uv run ruff format
|
|
111
|
+
|
|
112
|
+
# Check formatting without changes
|
|
113
|
+
uv run ruff format --check
|
|
114
|
+
|
|
115
|
+
# Lint code
|
|
116
|
+
uv run ruff check
|
|
117
|
+
|
|
118
|
+
# Auto-fix linting issues
|
|
119
|
+
uv run ruff check --fix
|
|
120
|
+
|
|
121
|
+
# Type checking (MyPy with strict mode)
|
|
122
|
+
uv run mypy mcp_common tests
|
|
123
|
+
|
|
124
|
+
# Security scan (Bandit)
|
|
125
|
+
uv run bandit -r mcp_common
|
|
126
|
+
|
|
127
|
+
# Run all quality checks (format + lint + type check + test)
|
|
128
|
+
uv run ruff format && uv run ruff check && uv run mypy mcp_common tests && uv run pytest
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Using Hatch Scripts (Alternative)
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
hatch run test # Run tests
|
|
135
|
+
hatch run test-cov # Tests with coverage
|
|
136
|
+
hatch run lint # Lint only
|
|
137
|
+
hatch run format # Format code
|
|
138
|
+
hatch run type-check # Type check
|
|
139
|
+
hatch run security # Security scan
|
|
140
|
+
hatch run all # All checks
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Package Structure
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
mcp_common/
|
|
147
|
+
├── __init__.py # Package registration, public API exports
|
|
148
|
+
├── adapters/
|
|
149
|
+
│ ├── __init__.py # HTTPClientAdapter exports
|
|
150
|
+
│ └── http/
|
|
151
|
+
│ ├── __init__.py
|
|
152
|
+
│ └── client.py # ✅ HTTPClientAdapter (connection pooling)
|
|
153
|
+
├── config/
|
|
154
|
+
│ ├── __init__.py # MCPBaseSettings, ValidationMixin exports
|
|
155
|
+
│ ├── base.py # ✅ MCPBaseSettings (YAML + env vars)
|
|
156
|
+
│ └── validation_mixin.py # ✅ ValidationMixin for Pydantic models
|
|
157
|
+
├── middleware/
|
|
158
|
+
│ ├── __init__.py
|
|
159
|
+
│ └── rate_limit_config.py # 🚧 Rate limit configuration (needs ACB migration)
|
|
160
|
+
├── security/
|
|
161
|
+
│ ├── __init__.py # Security utilities exports
|
|
162
|
+
│ ├── api_keys.py # ✅ APIKeyValidator (format validation)
|
|
163
|
+
│ └── sanitization.py # ✅ Sanitize user inputs, filter data
|
|
164
|
+
├── ui/
|
|
165
|
+
│ ├── __init__.py # ServerPanels exports
|
|
166
|
+
│ └── panels.py # ✅ ServerPanels (Rich UI panels)
|
|
167
|
+
├── exceptions.py # ✅ Custom exception hierarchy
|
|
168
|
+
├── health.py # ✅ Health check models (HealthStatus, ComponentHealth)
|
|
169
|
+
└── http_health.py # ✅ HTTP health check functions
|
|
170
|
+
|
|
171
|
+
tests/
|
|
172
|
+
├── conftest.py # Shared pytest fixtures
|
|
173
|
+
├── test_config.py # MCPBaseSettings tests
|
|
174
|
+
├── test_config_security.py # Security integration tests
|
|
175
|
+
├── test_config_validation_mixin.py # ValidationMixin tests
|
|
176
|
+
├── test_health.py # Health check system tests
|
|
177
|
+
├── test_http_client.py # HTTPClientAdapter tests
|
|
178
|
+
├── test_http_health.py # HTTP health check tests
|
|
179
|
+
├── test_rate_limit_config.py # Rate limit configuration tests
|
|
180
|
+
├── test_security_api_keys.py # API key validation tests
|
|
181
|
+
├── test_security_sanitization.py # Sanitization tests
|
|
182
|
+
├── test_ui_panels.py # ServerPanels tests
|
|
183
|
+
├── test_version.py # Version import tests
|
|
184
|
+
└── performance/ # Performance benchmarks
|
|
185
|
+
└── test_http_pooling.py
|
|
186
|
+
|
|
187
|
+
examples/
|
|
188
|
+
├── README.md # Example documentation
|
|
189
|
+
├── settings/
|
|
190
|
+
│ └── weather.yaml # Example YAML configuration
|
|
191
|
+
└── weather_server.py # ✅ Complete working Weather MCP server
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Note:** There is NO `logging/` directory - ACB logger is used directly via `LoggerProtocol` injection.
|
|
195
|
+
|
|
196
|
+
## Architecture Overview
|
|
197
|
+
|
|
198
|
+
### ACB-Native Adapter Pattern
|
|
199
|
+
|
|
200
|
+
All adapters in this library follow the ACB adapter pattern:
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
from acb.config import AdapterBase, Settings
|
|
204
|
+
from acb.adapters.logger import LoggerProtocol
|
|
205
|
+
from acb.adapters import AdapterStatus, AdapterMetadata, AdapterCapability
|
|
206
|
+
from uuid import UUID
|
|
207
|
+
from contextlib import suppress
|
|
208
|
+
|
|
209
|
+
# Static UUID7 - generated once, hardcoded forever (NEVER use uuid4())
|
|
210
|
+
MODULE_ID = UUID("01947e12-3b4c-7d8e-9f0a-1b2c3d4e5f6a")
|
|
211
|
+
MODULE_STATUS = AdapterStatus.STABLE # Enum, not string
|
|
212
|
+
|
|
213
|
+
MODULE_METADATA = AdapterMetadata(
|
|
214
|
+
module_id=MODULE_ID,
|
|
215
|
+
name="Example Adapter",
|
|
216
|
+
category="category",
|
|
217
|
+
provider="provider",
|
|
218
|
+
version="1.0.0",
|
|
219
|
+
acb_min_version="0.19.0",
|
|
220
|
+
status=MODULE_STATUS,
|
|
221
|
+
capabilities=[AdapterCapability.ASYNC_OPERATIONS],
|
|
222
|
+
required_packages=["package>=1.0.0"],
|
|
223
|
+
description="Adapter description",
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
class ExampleAdapter(AdapterBase):
|
|
228
|
+
settings: ExampleSettings | None = None
|
|
229
|
+
logger: LoggerProtocol # Injected by ACB - NEVER create Logger()
|
|
230
|
+
|
|
231
|
+
def __init__(self, **kwargs):
|
|
232
|
+
super().__init__(**kwargs) # REQUIRED: Call parent constructor
|
|
233
|
+
if self.settings is None:
|
|
234
|
+
self.settings = ExampleSettings()
|
|
235
|
+
|
|
236
|
+
async def _create_client(self):
|
|
237
|
+
"""Lazy initialization lifecycle method."""
|
|
238
|
+
# Initialize resources
|
|
239
|
+
self.logger.info("Resource initialized")
|
|
240
|
+
|
|
241
|
+
async def _cleanup_resources(self):
|
|
242
|
+
"""Cleanup on shutdown lifecycle method."""
|
|
243
|
+
# Close resources
|
|
244
|
+
self.logger.info("Resource closed")
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
# Auto-register with DI container at module level
|
|
248
|
+
with suppress(Exception):
|
|
249
|
+
depends.set(ExampleAdapter)
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Critical Pattern Rules
|
|
253
|
+
|
|
254
|
+
1. **MODULE_ID must be static UUID7** - Generated once during implementation, then hardcoded forever (NOT `uuid4()`)
|
|
255
|
+
1. **MODULE_STATUS is enum** - Use `AdapterStatus.STABLE`, not string `"stable"`
|
|
256
|
+
1. **Logger is injected** - Type hint `logger: LoggerProtocol`, ACB injects automatically
|
|
257
|
+
1. \*\*Always call super().__init__(**kwargs)** - Required for ACB lifecycle
|
|
258
|
+
1. **Implement lifecycle methods** - `_create_client()` and `_cleanup_resources()`
|
|
259
|
+
1. **DI registration at module level** - Use `with suppress(Exception): depends.set()`
|
|
260
|
+
|
|
261
|
+
## Implementation Guidelines
|
|
262
|
+
|
|
263
|
+
### When Implementing a New Adapter
|
|
264
|
+
|
|
265
|
+
1. **Read `docs/ACB_FOUNDATION.md`** for ACB fundamentals (adapters, DI, lifecycle)
|
|
266
|
+
1. **Read relevant documentation** in `docs/` for the specific feature
|
|
267
|
+
1. **Generate static UUID7** for MODULE_ID (use `uuidv7` CLI or Python uuid7 library)
|
|
268
|
+
1. **Create MODULE_METADATA** with all required fields
|
|
269
|
+
1. **Reference production code** in `../crackerjack`, `../session-mgmt-mcp`, or `../fastblocks`
|
|
270
|
+
- For rate limiting: Study `crackerjack/mcp/rate_limiter.py`
|
|
271
|
+
- For Rich UI: Study `crackerjack/ui/panels.py`
|
|
272
|
+
- For ACB patterns: Study `session-mgmt-mcp/adapters/`
|
|
273
|
+
1. **Implement lifecycle methods** (`_create_client()`, `_cleanup_resources()`)
|
|
274
|
+
1. **Write tests first** (TDD approach, target 90%+ coverage)
|
|
275
|
+
1. **Register at module level** with `suppress(Exception): depends.set()`
|
|
276
|
+
1. **Run quality checks** with `uv run pytest` and linting
|
|
277
|
+
|
|
278
|
+
**Development Cycle:**
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
# 1. Implement feature
|
|
282
|
+
vim mcp_common/adapters/rate_limit/limiter.py
|
|
283
|
+
|
|
284
|
+
# 2. Write tests
|
|
285
|
+
vim tests/test_rate_limiter.py
|
|
286
|
+
|
|
287
|
+
# 3. Run tests
|
|
288
|
+
uv run pytest tests/test_rate_limiter.py -v
|
|
289
|
+
|
|
290
|
+
# 4. Run quality checks
|
|
291
|
+
uv run ruff format
|
|
292
|
+
uv run ruff check
|
|
293
|
+
uv run mypy mcp_common tests
|
|
294
|
+
|
|
295
|
+
# 5. Run full test suite with coverage
|
|
296
|
+
uv run pytest --cov=mcp_common
|
|
297
|
+
|
|
298
|
+
# 6. Commit when all checks pass
|
|
299
|
+
git add . && git commit -m "feat: implement rate limiter adapter"
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Settings Pattern
|
|
303
|
+
|
|
304
|
+
All settings extend ACB's `acb.config.Settings`, not raw Pydantic:
|
|
305
|
+
|
|
306
|
+
```python
|
|
307
|
+
from mcp_common.config import MCPBaseSettings
|
|
308
|
+
from pydantic import Field
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
class MyServerSettings(MCPBaseSettings):
|
|
312
|
+
"""Server configuration using ACB Settings.
|
|
313
|
+
|
|
314
|
+
Loads from (in order):
|
|
315
|
+
1. settings/local.yaml (gitignored)
|
|
316
|
+
2. settings/my-server.yaml
|
|
317
|
+
3. Environment variables MY_SERVER_*
|
|
318
|
+
4. Defaults below
|
|
319
|
+
"""
|
|
320
|
+
|
|
321
|
+
api_key: str = Field(description="API key")
|
|
322
|
+
timeout: int = Field(default=30, description="Timeout in seconds")
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Dependency Injection Usage
|
|
326
|
+
|
|
327
|
+
All adapters use ACB's dependency injection:
|
|
328
|
+
|
|
329
|
+
```python
|
|
330
|
+
from acb.depends import depends
|
|
331
|
+
from mcp_common.adapters.http import HTTPClientAdapter
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
@mcp.tool()
|
|
335
|
+
async def my_tool():
|
|
336
|
+
# Get adapter from DI container (singleton)
|
|
337
|
+
http = depends(HTTPClientAdapter)
|
|
338
|
+
client = await http._create_client()
|
|
339
|
+
response = await client.get("https://api.example.com")
|
|
340
|
+
return response.json()
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Testing with DI
|
|
344
|
+
|
|
345
|
+
Tests can mock adapters via dependency injection:
|
|
346
|
+
|
|
347
|
+
```python
|
|
348
|
+
from acb.depends import depends
|
|
349
|
+
import pytest
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
@pytest.fixture
|
|
353
|
+
def mock_http():
|
|
354
|
+
"""Create mock HTTP adapter."""
|
|
355
|
+
mock = MockHTTPClientAdapter()
|
|
356
|
+
depends.set(HTTPClientAdapter, mock)
|
|
357
|
+
return mock
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
async def test_my_tool(mock_http):
|
|
361
|
+
"""Test uses mock automatically via DI."""
|
|
362
|
+
result = await my_tool()
|
|
363
|
+
assert mock_http.called
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## Quality Standards
|
|
367
|
+
|
|
368
|
+
This project follows **strict quality standards** enforced by test suite and linting:
|
|
369
|
+
|
|
370
|
+
- **Test Coverage:** Minimum 90% (enforced by pytest with `--cov-fail-under=90`)
|
|
371
|
+
- **Type Safety:** Strict MyPy (`strict = true` in pyproject.toml)
|
|
372
|
+
- Full type hints required for all functions and methods
|
|
373
|
+
- No `Any` types without justification
|
|
374
|
+
- Type stubs (`.pyi`) for external dependencies if needed
|
|
375
|
+
- **Code Style:** Ruff with comprehensive rule set (136 enabled rules - see pyproject.toml)
|
|
376
|
+
- Line length: 100 characters
|
|
377
|
+
- Python 3.13+ target
|
|
378
|
+
- Google-style docstrings
|
|
379
|
+
- **Security:** Bandit security scanning (no security issues tolerated)
|
|
380
|
+
- **Documentation:**
|
|
381
|
+
- Google-style docstrings required for all public APIs
|
|
382
|
+
- Type hints serve as primary documentation for parameters/returns
|
|
383
|
+
- Complex logic requires inline comments explaining "why", not "what"
|
|
384
|
+
|
|
385
|
+
**Before committing, always run:**
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
# Format + lint + type check + test
|
|
389
|
+
uv run ruff format && uv run ruff check && uv run mypy mcp_common tests && uv run pytest
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
## Key Documentation Files
|
|
393
|
+
|
|
394
|
+
- **`README.md`** - User-facing documentation with quickstart and examples
|
|
395
|
+
- **`docs/ACB_FOUNDATION.md`** - **START HERE** - ACB prerequisite guide (MUST READ before implementing)
|
|
396
|
+
- **`docs/ARCHITECTURE.md`** - Complete technical design (if exists - check docs/)
|
|
397
|
+
- **`docs/IMPLEMENTATION_PLAN.md`** - Phased implementation roadmap (if exists)
|
|
398
|
+
- **`docs/MCP_ECOSYSTEM_CRITICAL_AUDIT.md`** - Analysis of 9 production servers that informed design
|
|
399
|
+
- **`docs/SECURITY_IMPLEMENTATION.md`** - Security features and patterns
|
|
400
|
+
- **`docs/PHASE3_*.md`** - Phase-specific implementation documentation
|
|
401
|
+
- **`examples/README.md`** - Example server documentation
|
|
402
|
+
|
|
403
|
+
## Common Pitfalls to Avoid
|
|
404
|
+
|
|
405
|
+
1. **Using `uuid4()` for MODULE_ID** - Must be static UUID7, generated once and hardcoded
|
|
406
|
+
1. **Creating Logger manually** - Logger is injected by ACB via `LoggerProtocol`
|
|
407
|
+
1. **String for MODULE_STATUS** - Must use `AdapterStatus.STABLE` enum
|
|
408
|
+
1. **Forgetting `super().__init__(**kwargs)`** - Required for ACB lifecycle
|
|
409
|
+
1. **Missing MODULE_METADATA** - Required for ACB component discovery
|
|
410
|
+
1. **DI registration in `__init__`** - Must be at module level with `suppress(Exception)`
|
|
411
|
+
1. **Not implementing lifecycle methods** - `_create_client()` and `_cleanup_resources()` required
|
|
412
|
+
1. **Ignoring test coverage** - Must maintain 90%+ coverage (enforced by CI)
|
|
413
|
+
1. **Skipping type hints** - Strict MyPy requires full type coverage
|
|
414
|
+
|
|
415
|
+
## Implemented Components (v2.0.0)
|
|
416
|
+
|
|
417
|
+
### ✅ Core Configuration (mcp_common/config/)
|
|
418
|
+
|
|
419
|
+
- **MCPBaseSettings** - YAML + environment variable configuration
|
|
420
|
+
- Extends `acb.config.Settings`
|
|
421
|
+
- Automatic YAML loading from `settings/{name}.yaml`
|
|
422
|
+
- Environment variable overrides
|
|
423
|
+
- Path expansion (`~` → home directory)
|
|
424
|
+
- API key validation methods (`get_api_key()`, `get_api_key_secure()`, `get_masked_key()`)
|
|
425
|
+
- **MCPServerSettings** - Extended settings with common MCP server fields
|
|
426
|
+
- **ValidationMixin** - Reusable Pydantic validation logic
|
|
427
|
+
|
|
428
|
+
### ✅ HTTP Client Adapter (mcp_common/adapters/http/)
|
|
429
|
+
|
|
430
|
+
- **HTTPClientAdapter** - Connection pooling with httpx
|
|
431
|
+
- 11x performance improvement vs per-request clients
|
|
432
|
+
- Automatic lifecycle management
|
|
433
|
+
- Configurable pool size, timeouts, retries
|
|
434
|
+
- ACB-native with DI registration
|
|
435
|
+
|
|
436
|
+
### ✅ Security Utilities (mcp_common/security/)
|
|
437
|
+
|
|
438
|
+
- **APIKeyValidator** - Format validation for API keys
|
|
439
|
+
- Provider-specific patterns (OpenAI, Anthropic, Mailgun, etc.)
|
|
440
|
+
- Format validation with detailed error messages
|
|
441
|
+
- Key masking for safe logging
|
|
442
|
+
- **Sanitization** - Input sanitization and data filtering
|
|
443
|
+
- HTML/SQL injection prevention
|
|
444
|
+
- Path traversal protection
|
|
445
|
+
- Data redaction for sensitive fields
|
|
446
|
+
|
|
447
|
+
### ✅ Health Checks (mcp_common/health.py, mcp_common/http_health.py)
|
|
448
|
+
|
|
449
|
+
- **HealthStatus** - Enum for component health states
|
|
450
|
+
- **ComponentHealth** - Model for component health information
|
|
451
|
+
- **HealthCheckResponse** - Comprehensive health check responses
|
|
452
|
+
- **HTTP Health Functions** - Check HTTP connectivity and client health
|
|
453
|
+
|
|
454
|
+
### ✅ Rich UI Panels (mcp_common/ui/panels.py)
|
|
455
|
+
|
|
456
|
+
- **ServerPanels** - Professional console output with Rich
|
|
457
|
+
- `startup_success()` - Startup panel with features list
|
|
458
|
+
- `error()` - Error display with suggestions
|
|
459
|
+
- `status_table()` - Status tables with health indicators
|
|
460
|
+
- `notification()` - General notification panels
|
|
461
|
+
|
|
462
|
+
### ✅ Exception Hierarchy (mcp_common/exceptions.py)
|
|
463
|
+
|
|
464
|
+
- **MCPServerError** - Base exception for all MCP errors
|
|
465
|
+
- **ServerConfigurationError** - Configuration validation errors
|
|
466
|
+
- **ServerInitializationError** - Startup failures
|
|
467
|
+
- **DependencyMissingError** - Missing required dependencies
|
|
468
|
+
- **CredentialValidationError** - API key/credential errors
|
|
469
|
+
- **APIKeyMissingError** - Missing API keys
|
|
470
|
+
- **APIKeyFormatError** - Invalid API key format
|
|
471
|
+
- **APIKeyLengthError** - API key length validation
|
|
472
|
+
|
|
473
|
+
### 🚧 Rate Limiting (mcp_common/middleware/rate_limit_config.py)
|
|
474
|
+
|
|
475
|
+
- **RateLimitConfig** - Configuration model for rate limiting
|
|
476
|
+
- **Needs Migration:** Convert to ACB adapter pattern with MODULE_ID/STATUS/METADATA
|
|
477
|
+
- **Reference:** `crackerjack/mcp/rate_limiter.py` for token bucket implementation
|
|
478
|
+
|
|
479
|
+
## Working Example
|
|
480
|
+
|
|
481
|
+
See `examples/weather_server.py` for a complete working MCP server demonstrating:
|
|
482
|
+
|
|
483
|
+
- HTTPClientAdapter with connection pooling
|
|
484
|
+
- MCPBaseSettings with YAML configuration
|
|
485
|
+
- ServerPanels for startup UI
|
|
486
|
+
- ACB dependency injection
|
|
487
|
+
- FastMCP tool integration
|
|
488
|
+
- Error handling and validation
|
|
489
|
+
|
|
490
|
+
**Run the example:**
|
|
491
|
+
|
|
492
|
+
```bash
|
|
493
|
+
cd examples
|
|
494
|
+
python weather_server.py
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
## Version and Release Information
|
|
498
|
+
|
|
499
|
+
- **Current Version:** 2.0.0 (partially implemented)
|
|
500
|
+
- **Breaking Changes from v1.x:**
|
|
501
|
+
- ACB is now required (was optional)
|
|
502
|
+
- HTTP client is `HTTPClientAdapter` via DI (was `get_http_client()` function)
|
|
503
|
+
- Logging uses ACB Logger (no `MCPLogger` wrapper)
|
|
504
|
+
- Rate limiting will be `RateLimiterAdapter` (migration in progress)
|
|
505
|
+
- Settings extend `acb.config.Settings` (not raw Pydantic)
|
|
506
|
+
|
|
507
|
+
## External Dependencies and Their Roles
|
|
508
|
+
|
|
509
|
+
- **ACB (acb>=0.19.0)** - Core framework (adapters, DI, logger, settings, console) - **editable install from ../acb**
|
|
510
|
+
- **httpx>=0.27.0** - HTTP client with async support (used in HTTPClientAdapter)
|
|
511
|
+
- **pydantic>=2.10.0** - Data validation (used with ACB Settings)
|
|
512
|
+
- **pydantic-settings>=2.7.0** - Settings management
|
|
513
|
+
- **fastmcp>=0.2.0** - MCP protocol implementation
|
|
514
|
+
- **Rich** (via acb.console) - Terminal UI for ServerPanels
|
|
515
|
+
|
|
516
|
+
## Development Dependencies
|
|
517
|
+
|
|
518
|
+
- **pytest>=8.3.0** - Test framework
|
|
519
|
+
- **pytest-asyncio>=0.24.0** - Async test support
|
|
520
|
+
- **pytest-cov>=6.0.0** - Coverage reporting
|
|
521
|
+
- **pytest-mock>=3.14.0** - Mocking utilities
|
|
522
|
+
- **hypothesis>=6.122.0** - Property-based testing
|
|
523
|
+
- **ruff>=0.8.0** - Linting and formatting
|
|
524
|
+
- **mypy>=1.13.0** - Static type checking
|
|
525
|
+
- **bandit>=1.8.0** - Security scanning
|
|
526
|
+
- **respx>=0.21.0** - HTTP mocking for httpx
|
|
527
|
+
- **crackerjack** - Reference implementation
|
|
528
|
+
- **session-mgmt-mcp** - Reference implementation
|