Voltar para lista de artigos

Janela de editor com trecho do servidor MCP em Python

Implementação básica de um servidor MCP para monitorar processos em Python

Recentemente comecei a brincar mais com MCP para integrar automações locais com assistentes de IA. Uma necessidade comum no dia a dia e monitorar processos da máquina (CPU, RAM, status e PID) sem sair do chat com o agente.

Neste post, vou montar um servidor MCP básico em Python para:

  • listar processos em execução;
  • consultar detalhes de um processo específico;
  • encerrar um processo por PID (com um mínimo de proteção).

Bom, chega de enrolar e vamos ao que interessa.

O que vamos usar

  • Python 3.11 ou superior
  • mcp[cli] (SDK Python oficial do MCP)
  • psutil para leitura de métricas de processos

Preparando o projeto

mkdir mcp-process-monitor
cd mcp-process-monitor
python3 -m venv .venv
source .venv/bin/activate
pip install "mcp[cli]" psutil

Código do servidor

Crie um arquivo server.py com o seguinte conteúdo:

from __future__ import annotations
from typing import Any

import psutil
from mcp.server.fastmcp import FastMCP

mcp = FastMCP(
    "Process Monitor",
    instructions="Servidor MCP para monitoramento de processos locais",
)


def _bytes_para_mb(valor: int) -> float:
    return round(valor / (1024 * 1024), 2)


def _serializar_processo(proc: psutil.Process) -> dict[str, Any]:
    with proc.oneshot():
        memoria = proc.memory_info()
        return {
            "pid": proc.pid,
            "nome": proc.name(),
            "status": proc.status(),
            "usuario": proc.username(),
            "cpu_percent": proc.cpu_percent(interval=0.05),
            "memoria_rss_mb": _bytes_para_mb(memoria.rss),
            "memoria_vms_mb": _bytes_para_mb(memoria.vms),
        }


@mcp.tool()
def listar_processos(limite: int = 15) -> list[dict[str, Any]]:
    """Lista processos ativos ordenados por uso de memoria (RSS)."""
    processos: list[dict[str, Any]] = []

    for proc in psutil.process_iter():
        try:
            processos.append(_serializar_processo(proc))
        except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
            continue

    processos.sort(key=lambda item: item["memoria_rss_mb"], reverse=True)
    return processos[: max(1, min(limite, 100))]


@mcp.tool()
def detalhes_processo(pid: int) -> dict[str, Any]:
    """Retorna detalhes de um PID especifico."""
    try:
        proc = psutil.Process(pid)
        with proc.oneshot():
            return {
                **_serializar_processo(proc),
                "cmdline": proc.cmdline(),
                "threads": proc.num_threads(),
                "aberto_em": proc.create_time(),
            }
    except psutil.NoSuchProcess:
        return {"erro": f"Processo PID={pid} nao encontrado"}
    except psutil.AccessDenied:
        return {"erro": f"Acesso negado ao processo PID={pid}"}


@mcp.tool()
def encerrar_processo(pid: int, forcar: bool = False) -> str:
    """Encerra um processo. Use forcar=True para kill imediato."""
    try:
        processo_atual = psutil.Process()
        if pid == processo_atual.pid:
            return "Operacao bloqueada: o servidor nao pode encerrar a si proprio."

        alvo = psutil.Process(pid)
        if forcar:
            alvo.kill()
        else:
            alvo.terminate()

        alvo.wait(timeout=3)
        return f"Processo PID={pid} encerrado com sucesso."
    except psutil.NoSuchProcess:
        return f"Processo PID={pid} nao existe."
    except psutil.AccessDenied:
        return f"Sem permissao para encerrar PID={pid}."
    except psutil.TimeoutExpired:
        return f"Timeout ao encerrar PID={pid}. Tente novamente com forcar=True."


if __name__ == "__main__":
    mcp.run()

Perceba que o servidor ficou pequeno, mas funcional e útil:

  • listar_processos: visão geral da máquina;
  • detalhes_processo: inspeção de um PID específico;
  • encerrar_processo: ação de controle.

Rodando localmente

Com o arquivo pronto, execute:

python server.py

Instalando no cliente MCP

Para integrar em um cliente compatível (ex.: Claude Desktop):

pip install server.py --name "Process Monitor"

Depois disso, o cliente já consegue chamar as tools desse servidor.

Boas práticas antes de usar em produção

  • Nunca exponha encerrar_processo sem controle de permissão.
  • Adicione whitelist de comandos/processos permitidos.
  • Registre auditoria de quem chamou cada tool e quando.
  • Considere remover a tool de encerramento em ambientes críticos.

Fechando

Com poucas linhas de Python, você cria um servidor MCP funcional para observabilidade local. Esse é um bom primeiro passo para evoluir para um agente operacional: monitorar processos, abrir alertas e, com cuidado, executar correções automatizadas.

Se fizer essa base no seu ambiente, o proximo passo natural é incluir coleta histórica (CPU e RAM ao longo do tempo) e alertas proativos quando um PID ultrapassar limites definidos.