We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/bitflight-devops/mcp-json-yaml-toml'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
---
phase: 09-logging-infrastructure
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- packages/mcp_json_yaml_toml/logging.py
- packages/mcp_json_yaml_toml/__init__.py
- pyproject.toml
- uv.lock
autonomous: true
requirements:
- LOG-02
- LOG-03
- LOG-06
must_haves:
truths:
- "configure_logging() creates JSONL file sink with rotation at XDG data dir by default"
- "configure_logging() respects MCP_JYT_LOG_LEVEL, MCP_JYT_LOG_FILE, MCP_JYT_LOG_CONSOLE environment variables"
- "InterceptHandler captures mcp_json_yaml_toml.* namespace stdlib loggers and routes to loguru sinks"
- "No log output ever goes to stdout (MCP protocol safety)"
- "configure_logging() is idempotent and auto-called on package import"
- "File sink is suppressed when running under pytest"
artifacts:
- path: "packages/mcp_json_yaml_toml/logging.py"
provides: "Centralized logging configuration with InterceptHandler"
contains: "configure_logging"
- path: "packages/mcp_json_yaml_toml/__init__.py"
provides: "Auto-configuration on package import"
contains: "configure_logging"
key_links:
- from: "packages/mcp_json_yaml_toml/__init__.py"
to: "packages/mcp_json_yaml_toml/logging.py"
via: "import and call configure_logging()"
pattern: "from mcp_json_yaml_toml\\.logging import configure_logging"
- from: "packages/mcp_json_yaml_toml/logging.py"
to: "logging.getLogger('mcp_json_yaml_toml')"
via: "_install_intercept_handler attaches InterceptHandler to namespace logger"
pattern: "logging\\.getLogger.*mcp_json_yaml_toml"
---
<objective>
Install loguru, create the centralized logging module with configure_logging() and InterceptHandler, wire auto-configuration into package __init__.py, and verify type checkers pass.
Purpose: Establish all logging infrastructure so Phase 10 can migrate modules one-by-one without any setup work.
Output: `logging.py` module with configure_logging(), InterceptHandler, environment variable configuration; `__init__.py` wired for auto-configuration; loguru dependency added.
</objective>
<execution_context>
@/home/ubuntulinuxqa2/.claude/get-shit-done/workflows/execute-plan.md
@/home/ubuntulinuxqa2/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/09-logging-infrastructure/09-RESEARCH.md
@.planning/phases/09-logging-infrastructure/09-CONTEXT.md
@packages/mcp_json_yaml_toml/__init__.py
@packages/mcp_json_yaml_toml/backends/binary_manager.py
</context>
<tasks>
<task type="auto">
<name>Task 1: Install loguru and create logging.py module</name>
<files>
packages/mcp_json_yaml_toml/logging.py
pyproject.toml
uv.lock
</files>
<action>
1. Install loguru: `uv add "loguru>=0.7.3"`
2. Create `packages/mcp_json_yaml_toml/logging.py` with:
**Module-level stdlib import (CRITICAL for shadowing safety):**
The file is named `logging.py` which shadows stdlib `logging`. Import stdlib `logging` at the very top of the file BEFORE any other imports. Store it as a module-level reference so InterceptHandler and \_install_intercept_handler can use it reliably.
**\_is_testing() function:**
Detects pytest environment via `"pytest" in sys.modules or "PYTEST_CURRENT_TEST" in os.environ`. Returns bool.
**configure_logging() function:**
- Idempotent via module-level `_CONFIGURED` flag (use `global` with `# noqa: PLW0603`)
- Calls `logger.remove()` first to clear loguru's default stderr handler
- Reads `MCP_JYT_LOG_LEVEL` env var (default: `"WARNING"`, `.upper()`)
- Reads `MCP_JYT_LOG_FILE` env var (override for log file path)
- Default log file: `~/.local/share/mcp-json-yaml-toml/logs/server.jsonl` (use `Path.home()` for portability; platformdirs is available but Path.home() matches the XDG convention directly)
- Creates log directory with `mkdir(parents=True, exist_ok=True)`
- **File sink** (skip if `_is_testing()` returns True):
- `logger.add(log_file, level=level, serialize=True, rotation="10 MB", retention=5, enqueue=True, diagnose=False)`
- **Optional stderr console sink** (only when `MCP_JYT_LOG_CONSOLE` env var is `"1"`, `"true"`, or `"yes"`):
- `logger.add(sys.stderr, level=level, format="<green>{time:HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan> - <level>{message}</level>", colorize=True, diagnose=False, enqueue=False)`
- **NEVER add a stdout sink** -- stdout is the MCP JSON-RPC protocol channel
- Calls `_install_intercept_handler()` at the end
**InterceptHandler class (extends logging.Handler):**
- `emit(self, record)` method:
- Maps stdlib level name to loguru level via `logger.level(record.levelname).name`, falling back to `record.levelno` on ValueError
- Walks call frames to find original caller depth (skip stdlib logging and importlib bootstrap frames)
- Calls `logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())`
- Use the stdlib logging reference captured at module top for `logging.Handler` base class and `logging.__file__` comparison
**\_install_intercept_handler() function:**
- Creates InterceptHandler instance
- Gets namespace logger: `logging.getLogger("mcp_json_yaml_toml")` (using stdlib reference)
- Sets `ns_logger.handlers = [handler]`
- Sets `ns_logger.setLevel(logging.DEBUG)` -- let loguru handle filtering
- Sets `ns_logger.propagate = False` -- don't bubble to root logger
**Type hints:** Use `from __future__ import annotations`. Use `TYPE_CHECKING` block for `loguru` type imports if needed. Follow existing codebase pattern.
**Exports:** `__all__ = ["configure_logging"]` -- InterceptHandler and \_install_intercept_handler are private implementation details.
</action>
<verify>
`uv run python -c "from mcp_json_yaml_toml.logging import configure_logging; print('import OK')"` succeeds.
`uv run python -c "import logging; logging.getLogger('mcp_json_yaml_toml.test').warning('hello')"` does not crash.
</verify>
<done>
logging.py exists with configure_logging(), InterceptHandler, \_install_intercept_handler(), \_is_testing(). loguru is in pyproject.toml dependencies. Module imports cleanly.
</done>
</task>
<task type="auto">
<name>Task 2: Wire auto-configuration and verify type checkers</name>
<files>
packages/mcp_json_yaml_toml/__init__.py
</files>
<action>
1. Edit `packages/mcp_json_yaml_toml/__init__.py`:
- Add import: `from mcp_json_yaml_toml.logging import configure_logging`
- Call `configure_logging()` after the import (before `__all__`)
- Do NOT add `configure_logging` to `__all__` -- it is auto-called, not a public API for external consumers
2. Run type checkers:
- `uv run mypy packages/ --show-error-codes` -- must pass cleanly
- `uv run basedpyright packages/` -- must pass cleanly
- If either fails due to loguru type stubs, fix the issue. loguru ships with PEP 484 `.pyi` stubs so both checkers should work out of the box.
3. Verify stdlib logging still works through InterceptHandler:
- `uv run python -c "import mcp_json_yaml_toml; import logging; l = logging.getLogger('mcp_json_yaml_toml.test'); l.warning('bridge test')"` should not crash and should route through loguru.
4. Verify no stdout pollution:
- `uv run python -c "import mcp_json_yaml_toml" 2>/dev/null` should produce zero stdout output (stdout must remain clean for MCP protocol).
5. Run verification: `uv run prek run --files packages/mcp_json_yaml_toml/logging.py packages/mcp_json_yaml_toml/__init__.py`
</action>
<verify>
`uv run mypy packages/ --show-error-codes` exits 0.
`uv run basedpyright packages/` exits 0.
`uv run python -c "import mcp_json_yaml_toml" 2>/dev/null | wc -c` outputs `0` (no stdout).
`uv run prek run --files packages/mcp_json_yaml_toml/logging.py packages/mcp_json_yaml_toml/__init__.py` passes.
</verify>
<done>
**init**.py auto-calls configure_logging() on import. Both mypy and basedpyright pass with zero errors. No stdout output on package import. InterceptHandler bridges stdlib logging for mcp_json_yaml_toml.\* namespace.
</done>
</task>
</tasks>
<verification>
1. `uv run python -c "from mcp_json_yaml_toml.logging import configure_logging; configure_logging(); print('OK')"` -- import and call succeeds
2. `uv run python -c "import mcp_json_yaml_toml" 2>/dev/null | wc -c` -- zero bytes on stdout
3. `uv run mypy packages/ --show-error-codes` -- exits 0
4. `uv run basedpyright packages/` -- exits 0
5. `uv run python -c "import logging; import mcp_json_yaml_toml; l=logging.getLogger('mcp_json_yaml_toml.backends.binary_manager'); l.warning('test')"` -- routes through loguru without error
</verification>
<success_criteria>
- loguru>=0.7.3 is a declared dependency in pyproject.toml
- packages/mcp_json_yaml_toml/logging.py exists with configure_logging(), InterceptHandler, \_install_intercept_handler()
- configure_logging() creates JSONL file sink (when not testing) and optional stderr sink
- InterceptHandler targets only mcp_json_yaml_toml namespace (not root logger)
- **init**.py calls configure_logging() on import
- mypy and basedpyright pass with zero errors
- No stdout output from package import
</success_criteria>
<output>
After completion, create `.planning/phases/09-logging-infrastructure/09-01-SUMMARY.md`
</output>