mcp-infra-readonly
by senseicoder
README.md
# mcp-infra-readonly
Serveur MCP (Model Context Protocol) Python donnant à Claude Code un accès **strictement en lecture** à l'infrastructure Epiconcept — logs, état des services, métriques, facts Ansible, état Docker.
**Repos liés :**
- Ce repo : https://github.com/senseicoder/mcp-infra-readonly
- Sandbox Docker Claude Code : https://github.com/senseicoder/claude-sandbox
## Principe de sécurité
- **Zéro écriture** : aucun outil ne peut modifier l'état d'un serveur
- **Double validation** : `validation.py` (regex strictes + blocage des caractères d'injection) avant toute commande SSH
- **Liste blanche** : seules les commandes listées dans `config/allowlist.yml` sont exécutables — rechargement à chaud, pas de redémarrage nécessaire
- **Filtre de sortie** : `output_filter.py` bloque les clés privées, masque les mots de passe/tokens avant retour à Claude
- **Pas de sudo** : toutes les commandes s'exécutent avec les droits de l'utilisateur SSH
- **Transport stdio** : le serveur tourne en local, communique via stdin/stdout avec Claude Code
- **Pas de credentials en dur** : la configuration SSH utilise les clés SSH existantes de l'hôte
## Outils MCP exposés
| Outil | Description | Commande SSH sous-jacente |
|---|---|---|
| `list_hosts` | Liste les hosts Ansible connus | lecture inventory |
| **Services** | | |
| `get_service_status` | État d'un service systemd | `systemctl status <service>` |
| `get_failed_services` | Services systemd en état failed | `systemctl --failed` |
| `get_process_list` | Top processus CPU/RAM | `ps aux --sort=-%cpu \| head -20` |
| `get_system_info` | Uptime, mémoire, version OS | `uptime`, `free -h`, `uname -a` |
| `get_open_ports` | Ports TCP en écoute | `ss -tlnp` |
| **Logs** | | |
| `get_log_tail` | Dernières N lignes d'un log | `tail -n N <path>` |
| `get_journal` | Logs systemd via journalctl | `journalctl -u <service> -n N` |
| `list_log_files` | Liste un répertoire de logs | `ls -lh <path>` |
| **Disque** | | |
| `get_disk_usage` | Utilisation disque | `df -h` |
| `get_inode_usage` | Utilisation inodes | `df -i` |
| **Docker** | | |
| `get_docker_status` | État des containers | `docker ps -a` |
| `get_docker_stats` | CPU/RAM des containers (snapshot) | `docker stats --no-stream` |
| `get_docker_logs` | Logs d'un container | `docker logs --tail N <container>` |
| `get_docker_inspect` | Config/volumes/réseau d'un container | `docker inspect <container>` |
| **Ansible** | | |
| `get_ansible_facts` | Facts Ansible d'un host | `ansible <host> -m setup` |
## Installation
```bash
pip install -e .
```
## Configuration
```bash
cp config/hosts.yml.example config/hosts.yml
# Éditer config/hosts.yml avec les hosts réels
```
L'allowlist (`config/allowlist.yml`) est rechargée à chaque appel — aucun redémarrage du serveur MCP n'est nécessaire après modification.
## Utilisation avec Claude Code
Ajouter dans `.mcp.json` du projet ou dans `~/.claude/settings.json` :
```json
{
"mcpServers": {
"infra": {
"command": "python",
"args": ["-m", "mcp_infra.server"],
"cwd": "/chemin/vers/mcp-infra-readonly"
}
}
}
```
Dans la sandbox Docker, ce MCP est configuré dans `config/mcp.json` du repo `claude-sandbox`.
## Architecture
```
mcp-infra-readonly/
├── src/mcp_infra/
│ ├── server.py # point d'entrée MCP — tous les outils déclarés ici
│ ├── config.py # chargement config + allowlist (rechargement à chaud)
│ ├── validation.py # validation paramètres — regex strictes + anti-injection
│ ├── output_filter.py # filtre sortie — BLOCK clés privées, REDACT tokens
│ └── tools/
│ ├── ssh.py # helper SSH lecture seule (asyncssh, request_pty=False)
│ ├── services.py # get_service_status, get_failed_services, get_process_list
│ │ # get_system_info, get_open_ports
│ ├── logs.py # get_log_tail, get_journal, get_disk_usage
│ │ # get_inode_usage, list_log_files
│ ├── docker.py # get_docker_status, get_docker_stats, get_docker_logs
│ │ # get_docker_inspect
│ └── ansible.py # get_ansible_facts, list_hosts
├── config/
│ ├── hosts.yml.example # template — ne pas committer hosts.yml
│ └── allowlist.yml # liste blanche des commandes autorisées (rechargement à chaud)
├── docs/
│ ├── capabilities.md # ce que Claude peut/ne peut pas faire avec ce MCP
│ └── adr/
│ ├── ADR-001-validation-parametres.md
│ ├── ADR-002-filtre-sortie.md
│ └── ADR-003-architecture-allowlist.md
├── tests/
│ └── test_tools.py
└── SECURITY.md
```
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing