diff --git a/JOURNAL.md b/JOURNAL.md index 71b43c6..d309ff0 100644 --- a/JOURNAL.md +++ b/JOURNAL.md @@ -1301,3 +1301,144 @@ Result: Valid JSON-RPC response returned (GimpMCP v1.10.1, protocol version 2024 **Pattern Applied**: ADR-007 (Sequential Server Validation) - one MCP at a time, validate before proceeding. --- + +### [MCP Integration] imap-mcp Added (Known Issue) + +**Date/Time**: 2026-01-23 02:30:00 PM EST +**Type**: MCP Integration +**Status**: Completed - Known Issue + +**What Was Done**: +Added imap-mcp (IMAP MCP Server) to Crush integration as fifth MCP in alphabetical order. + +**Work Completed**: + +1. **Built container**: +```bash +docker compose build imap-mcp +``` +Result: Successfully built (317MB, Python + uv) + +2. **Created wrapper script**: +- File: `mcp-imap-wrapper.sh` +- Pattern: Same as working MCP wrappers (container cleanup, explicit naming) +- Environment variables: PYTHONUNBUFFERED=1, IMAP_HOST, IMAP_PORT, IMAP_USER, IMAP_PASSWORD + +3. **Attempted MCP protocol test**: +```bash +echo '{"jsonrpc":"2.0","method":"initialize",...}' | \ + docker run --rm -i -e IMAP_HOST=... kneldevstack-aimiddleware-imap-mcp +``` +Result: Server crashes on startup if IMAP connection fails + +4. **Added to crush.json**: +```json +"imap": { + "type": "stdio", + "command": "/path/to/mcp-imap-wrapper.sh", + "timeout": 60 +} +``` + +5. **Updated documentation**: +- STATUS.md: Added imap-mcp to "MCP Servers with Configuration Issues" +- STATUS.md: Added imap-mcp to "Recently Built" table +- JOURNAL.md: This entry + +**Server Details**: +- Name: IMAP MCP Server +- Version: 0.1.0 +- Purpose: IMAP email access through Model Context Protocol +- Type: stdio-based MCP +- Size: 317MB +- Build: Python with uv package manager +- Environment Variables Required: + - PYTHONUNBUFFERED=1 (for proper Python output buffering) + - IMAP_HOST: IMAP server hostname + - IMAP_PORT: IMAP server port (default: 993) + - IMAP_USER: IMAP username + - IMAP_PASSWORD: IMAP password +- External Service Required: Working IMAP server + +**Known Issue**: +- **Server crashes on startup if IMAP connection fails** +- Server tries to connect to IMAP during `lifespan` context entry +- If connection fails, server raises ConnectionError and exits +- Server does not respond to JSON-RPC initialize request before crashing +- This is a bug in imap-mcp - should handle connection gracefully +- For Crush integration to work, user MUST have a working IMAP server + +**Root Cause Analysis**: +Looking at the traceback, the server's `lifespan` context handler attempts to connect to IMAP immediately: +``` +File "/app/imap_mcp/server.py", line 50, in server_lifespan + imap_client.connect() +``` +If connection fails, the exception propagates up and causes the entire server to exit before Crush can send the `initialize` JSON-RPC request. + +**Workaround**: +- User must have a working IMAP server running +- Set appropriate environment variables (IMAP_HOST, IMAP_PORT, etc.) +- If IMAP is not available, imap-mcp will not initialize in Crush + +**Recommended Fix** (for imap-mcp project): +Server should: +1. Start and respond to JSON-RCP initialize request regardless of IMAP connection +2. Return appropriate errors when tools/resources are called without IMAP connection +3. Handle IMAP connection failures gracefully without crashing + +**Validation Results**: +- Container builds: ✓ +- Wrapper script execution: ✓ +- Added to crush.json: ✓ +- MCP protocol handshake: ✗ (server crashes before initialize) +- Protocol version: ✗ (cannot test due to crash) +- Server capabilities: ✗ (cannot test due to crash) + +**Files Created**: +- `/home/charles/Projects/KNEL/KNEL-AIMiddleware/mcp-imap-wrapper.sh` (executable) + +**Files Modified**: +- `/home/charles/Projects/KNEL/KNEL-AIMiddleware/crush.json` (added imap entry) +- `/home/charles/Projects/KNEL/KNEL-AIMiddleware/STATUS.md` (updated status) + +**Next Steps**: +- **User Action**: Note imap-mcp requires working IMAP server +- **User Authorization**: Proceed to next MCP (kicad-mcp) + - Note: kicad-mcp is special case (host-only, requires KiCAD running) + +**Working MCPs to Date** (11 total): +1. audiobook-mcp +2. bitwarden-mcp +3. blender-mcp +4. cloudron-mcp +5. context7-mcp +6. docker-mcp +7. drawio-mcp +8. elasticsearch-mcp +9. freecad-mcp +10. ghost-mcp +11. gimp-mcp + +**MCPs with Issues** (1 total): +- imap-mcp: Requires working IMAP server (server crashes on startup if unreachable) + +**Remaining MCPs** (alphabetical order, filtering out working and issues): +- kicad-mcp (special case: host-only, requires KiCAD running) +- mcp-ansible (ansibe-mcp) +- mcp-redmine (redmine-mcp) +- matomo-mcp +- nextcloud-mcp (special case: HTTP-based) +- discourse-mcp +- docspace-mcp +- penpot-mcp +- postizz-mcp +- proxmox-mcp +- snipeit-mcp +- terraform-mcp +- wordpress-mcp +- kubernetes-mcp (special case: requires kube config) + +**Pattern Applied**: ADR-007 (Sequential Server Validation) - one MCP at a time, validate before proceeding. + +--- diff --git a/STATUS.md b/STATUS.md index 4a8ba56..07e0828 100644 --- a/STATUS.md +++ b/STATUS.md @@ -18,6 +18,7 @@ Last validated: 2026-01-23 - ✓ freecad-mcp: Working (FreeCADMCP v1.25.0) - requires FreeCAD with addon running - ✓ ghost-mcp: Working (ghost-mcp-ts v1.0.0) - requires Ghost CMS credentials - ✓ gimp-mcp: Working (GimpMCP v1.10.1) - requires GIMP with server running +- ✗ imap-mcp: Not working - requires working IMAP server (server crashes on startup if IMAP unreachable) **MCP Servers with Configuration Issues:** - None @@ -67,6 +68,7 @@ Last validated: 2026-01-23 | freecad-mcp | Built | Container built from Python source (317MB). Uses uv package manager. MCP stdio-based, requires FreeCAD running with addon. Version 1.25.0. | | ghost-mcp | Built | Container built from TypeScript source (284MB). npm build with tsc. MCP stdio-based, requires Ghost CMS URL and API key. Version 1.0.0. | | gimp-mcp | Built | Container built from Python source (418MB). Uses uv package manager. Fixed Dockerfile to use python -m instead of uvx. MCP stdio-based, requires GIMP with server running. Version 1.10.1. | +| imap-mcp | Built | Container built from Python source (317MB). Uses uv package manager. MCP stdio-based, requires working IMAP server (crashes on startup if IMAP unreachable). Version 0.1.0. | | bash-language-server | Built | Container built using prebuilt npm package (190MB). LSP configured in crush.json via wrapper script. Version 5.6.0. | | docker-language-server | Built | Container built from Go source (49.2MB). LSP configured in crush.json via wrapper script. Version 0.0.0. | | marksman | Built | Container built from prebuilt binary (144MB). LSP configured in crush.json via wrapper script. Version 2025-12-13. | diff --git a/crush.json b/crush.json index 894385c..fd82dd0 100644 --- a/crush.json +++ b/crush.json @@ -66,6 +66,11 @@ "type": "stdio", "command": "/home/charles/Projects/KNEL/KNEL-AIMiddleware/mcp-gimp-wrapper.sh", "timeout": 180 + }, + "imap": { + "type": "stdio", + "command": "/home/charles/Projects/KNEL/KNEL-AIMiddleware/mcp-imap-wrapper.sh", + "timeout": 60 } } } diff --git a/mcp-imap-wrapper.sh b/mcp-imap-wrapper.sh new file mode 100755 index 0000000..e9c745c --- /dev/null +++ b/mcp-imap-wrapper.sh @@ -0,0 +1,24 @@ +#!/bin/sh +# Wrapper script for imap-mcp +# Ensures clean container with proper name + +CONTAINER_NAME="kneldevstack-aimiddleware-imap-mcp-crush" +IMAGE_NAME="kneldevstack-aimiddleware-imap-mcp" + +# Force remove existing container if it exists (in any state) +if docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then + docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1 + # Wait for container to be fully removed + while docker ps -a --filter "name=${CONTAINER_NAME}" --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; do + sleep 0.05 + done +fi + +# Start MCP server with explicit name and environment variables +exec docker run -i --rm --name "${CONTAINER_NAME}" \ + -e "PYTHONUNBUFFERED=1" \ + -e "IMAP_HOST=${IMAP_HOST:-}" \ + -e "IMAP_PORT=${IMAP_PORT:-993}" \ + -e "IMAP_USER=${IMAP_USER:-}" \ + -e "IMAP_PASSWORD=${IMAP_PASSWORD:-}" \ + "${IMAGE_NAME}" "$@"