feat(mcp): implement MCP server integration over stdio JSON-RPC #88

Merged
fuzzy merged 4 commits from feature/0026-implement-mcp-server into main 2026-07-05 14:16:05 +00:00
Owner

What

Implement MCP server integration: spawn server processes via stdio, perform JSON-RPC initialize handshake, list tools, and convert to OpenAI function-calling format for the LLM client.

Why

MCP servers provide external tools that the LLM can use during job execution.

Testing

  • 70 unit tests pass (12 new for MCP)
  • Pre-commit hooks pass
  • Coverage: 86%

Breaking Changes

None.

Closes #0023
Closes #0024
Closes #0025
Closes #0026

## What Implement MCP server integration: spawn server processes via stdio, perform JSON-RPC initialize handshake, list tools, and convert to OpenAI function-calling format for the LLM client. ## Why MCP servers provide external tools that the LLM can use during job execution. ## Testing - [x] 70 unit tests pass (12 new for MCP) - [x] Pre-commit hooks pass - [x] Coverage: 86% ## Breaking Changes None. Closes #0023 Closes #0024 Closes #0025 Closes #0026
- Spawn server process, initialize handshake, list tools
- Convert MCP tool definitions to OpenAI function-calling format
- Error handling for missing command, connection failures, JSON-RPC errors
Closes #0023
Closes #0024
LLM client now accepts optional tool definitions for OpenAI
function-calling in the completion request.
Closes #0025
Cover tool format conversion, server init, connect, get_tools,
error cases, and process lifecycle.
docs: mark Phase 2 Task 3 complete
All checks were successful
CI / test (pull_request) Successful in 52s
CI / lint (pull_request) Successful in 1m17s
79346ec7dc
MCP server integration with stdio JSON-RPC client, tool
format conversion, and LLM tools support done.
Closes #0026
the.auditor left a comment

Automated Review — PR #88

Result: APPROVED


Strong MCP implementation. The stdio JSON-RPC pattern is correctly implemented with initialize handshake, notifications, and tool listing.

  • Correctness: JSON-RPC 2.0 compliance, proper stdio subprocess management, MCP-to-OpenAI tool format conversion, initialize handshake with clientInfo.
  • Completeness: Closes #23–#26. ROADMAP updated. llm.py changed minimally to accept tools param — nice encapsulation.
  • Test coverage: 12 tests covering tool conversion (basic, empty, multiple, missing fields), server init, connect (initialize handshake, missing command, not found), get_tools, close.
  • Error handling: MCPError for missing command, FileNotFoundError, disconnected state, server errors, closed connections.
  • Maintainability: Clean separation of concerns. _send_request/_send_notification/_send_initialize pattern is readable.

Suggestions (non-blocking)

  1. src/kronai/mcp.py:56,84 — Docstrings still use Raises/Returns without trailing colon (same issue as PR #72). Inconsistent with the rest of the codebase:

    # Current
    Raises
        MCPError: ...
    
    # Everywhere else
    Raises:
        MCPError: ...
    
  2. src/kronai/mcp.py:149-158_send_request reads a single stdout line. If the server writes enough stderr output before responding, the pipe buffer could fill and deadlock. Consider stderr=subprocess.DEVNULL if stderr isn't needed during normal operation, or read stderr asynchronously.

  3. src/kronai/mcp.py:169-174json.loads() on the response line is not wrapped. If the server returns malformed JSON, a json.JSONDecodeError propagates instead of MCPError. Wrap in a try/except.

  4. src/kronai/mcp.py:75-88_send_initialize() doesn't validate the response. If the server returns {"result": {}} (empty), it logs and continues. Consider checking for expected fields like serverInfo or protocolVersion.

## Automated Review — PR #88 **Result: APPROVED** --- Strong MCP implementation. The stdio JSON-RPC pattern is correctly implemented with initialize handshake, notifications, and tool listing. - **Correctness**: JSON-RPC 2.0 compliance, proper stdio subprocess management, MCP-to-OpenAI tool format conversion, initialize handshake with clientInfo. - **Completeness**: Closes #23–#26. ROADMAP updated. `llm.py` changed minimally to accept `tools` param — nice encapsulation. - **Test coverage**: 12 tests covering tool conversion (basic, empty, multiple, missing fields), server init, connect (initialize handshake, missing command, not found), get_tools, close. - **Error handling**: `MCPError` for missing command, FileNotFoundError, disconnected state, server errors, closed connections. - **Maintainability**: Clean separation of concerns. `_send_request`/`_send_notification`/`_send_initialize` pattern is readable. ### Suggestions (non-blocking) 1. **`src/kronai/mcp.py:56,84`** — Docstrings still use `Raises`/`Returns` without trailing colon (same issue as PR #72). Inconsistent with the rest of the codebase: ```python # Current Raises MCPError: ... # Everywhere else Raises: MCPError: ... ``` 2. **`src/kronai/mcp.py:149-158`** — `_send_request` reads a single stdout line. If the server writes enough stderr output before responding, the pipe buffer could fill and deadlock. Consider `stderr=subprocess.DEVNULL` if stderr isn't needed during normal operation, or read stderr asynchronously. 3. **`src/kronai/mcp.py:169-174`** — `json.loads()` on the response line is not wrapped. If the server returns malformed JSON, a `json.JSONDecodeError` propagates instead of `MCPError`. Wrap in a try/except. 4. **`src/kronai/mcp.py:75-88`** — `_send_initialize()` doesn't validate the response. If the server returns `{"result": {}}` (empty), it logs and continues. Consider checking for expected fields like `serverInfo` or `protocolVersion`.
fuzzy merged commit 79346ec7dc into main 2026-07-05 14:16:05 +00:00
fuzzy deleted branch feature/0026-implement-mcp-server 2026-07-05 14:16:05 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
thwap/kronai!88
No description provided.