personal-lifecycle-tracker / mcp-server / server.py
server.py
Raw
#!/usr/bin/env python3
"""Lightweight stdio Model Context Protocol (MCP) server for project inspection.

Zero-dependency standard library implementation compliant with MCP JSON-RPC
specifications.
"""

import json
import os
import subprocess
import sys


def read_message():
  line = sys.stdin.readline()
  if not line:
    return None
  return json.loads(line)


def write_message(obj):
  sys.stdout.write(json.dumps(obj) + "\n")
  sys.stdout.flush()


def tool_inspect_health(args):
  service = args.get("service")
  try:
    cmd = ["docker", "compose", "ps", "--format", "json"]
    proc = subprocess.run(cmd, capture_output=True, text=True, check=False)
    if proc.returncode == 0:
      output = proc.stdout.strip()
      return {
          "status": "success",
          "containers": output or "No active containers",
      }
    return {
        "status": "unknown",
        "message": "Docker Compose not running or available",
    }
  except Exception as e:
    return {"status": "error", "error": str(e)}


def tool_inspect_contract(args):
  contract_path = os.path.join(os.getcwd(), "contracts", "openapi.yaml")
  if not os.path.exists(contract_path):
    return {
        "status": "missing",
        "message": "No contracts/openapi.yaml found in project root",
    }
  try:
    with open(contract_path, "r", encoding="utf-8") as f:
      content = f.read(2048)  # Sample first 2KB
    return {
        "status": "found",
        "path": "contracts/openapi.yaml",
        "preview": content,
    }
  except Exception as e:
    return {"status": "error", "error": str(e)}


def main():
  while True:
    try:
      msg = read_message()
      if msg is None:
        break

      req_id = msg.get("id")
      method = msg.get("method")
      params = msg.get("params", {})

      if method == "initialize":
        write_message({
            "jsonrpc": "2.0",
            "id": req_id,
            "result": {
                "protocolVersion": "2024-11-05",
                "capabilities": {"tools": {}},
                "serverInfo": {"name": "project-mcp-server", "version": "1.0.0"},
            },
        })
      elif method == "tools/list":
        write_message({
            "jsonrpc": "2.0",
            "id": req_id,
            "result": {
                "tools": [
                    {
                        "name": "inspect_project_health",
                        "description": (
                            "Checks the status of project containers and API"
                            " endpoints"
                        ),
                        "inputSchema": {
                            "type": "object",
                            "properties": {
                                "service": {
                                    "type": "string",
                                    "description": (
                                        "Optional specific service to check"
                                    ),
                                }
                            },
                        },
                    },
                    {
                        "name": "inspect_openapi_contract",
                        "description": (
                            "Reads and summarizes endpoints from"
                            " contracts/openapi.yaml"
                        ),
                        "inputSchema": {"type": "object", "properties": {}},
                    },
                ]
            },
        })
      elif method == "tools/call":
        tool_name = params.get("name")
        arguments = params.get("arguments", {})
        if tool_name == "inspect_project_health":
          res = tool_inspect_health(arguments)
        elif tool_name == "inspect_openapi_contract":
          res = tool_inspect_contract(arguments)
        else:
          res = {"error": f"Unknown tool: {tool_name}"}

        write_message({
            "jsonrpc": "2.0",
            "id": req_id,
            "result": {
                "content": [{"type": "text", "text": json.dumps(res, indent=2)}]
            },
        })
      elif method == "ping":
        write_message({"jsonrpc": "2.0", "id": req_id, "result": {}})
      else:
        write_message({
            "jsonrpc": "2.0",
            "id": req_id,
            "error": {"code": -32601, "message": f"Method {method} not found"},
        })
    except Exception as ex:
      write_message({
          "jsonrpc": "2.0",
          "id": None,
          "error": {"code": -32603, "message": str(ex)},
      })


if __name__ == "__main__":
  main()