DesktopCommanderPy
Provides tools for connecting to and managing SAP HANA Cloud instances, including executing queries, DDL operations, listing schemas and tables, describing table structure, getting row counts, and retrieving system information.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@DesktopCommanderPy show me the files in my Documents folder"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
DesktopCommanderPy
Servidor MCP propio en Python — alternativa segura, extensible y 100% tuya a Desktop Commander.
¿Qué es esto?
DesktopCommanderPy es un servidor Model Context Protocol (MCP) escrito completamente en Python que da a Claude (o cualquier IA compatible con MCP) acceso controlado a tu máquina local y a tus sistemas externos.
Módulos actuales:
Filesystem — lectura, escritura, búsqueda, edición quirúrgica
Terminal — ejecución de comandos bloqueantes y streaming
Procesos — gestión con psutil y sesiones interactivas (REPLs)
SAP HANA Cloud — conexión, consultas, administración vía hdbcli
Construido como alternativa personal a Desktop Commander:
Control total — cada línea de código es tuya, sin cajas negras
Seguridad desde el principio — sandbox de rutas, blacklist de comandos, credenciales por variables de entorno
Extensible — añadir un módulo nuevo es copiar un fichero y registrar las tools en server.py
Multiplataforma — Windows (PowerShell) primario, Linux/macOS con detección automática
Related MCP server: filesystem_sandbox
Estado actual
Componente | Estado |
Tests | ✅ 32/32 passing |
Integración Claude Desktop | ✅ Conectado y verificado (2026-03-26) |
Protocolo MCP negociado | 2025-11-25 |
FastMCP | 3.1.1 |
Python | 3.12.10 |
hdbcli (HANA) | 2.28.17 |
Tools disponibles | 28 |
Estructura del proyecto
DesktopCommanderPy/
├── main.py # Entry point: stdio o HTTP/SSE
├── pyproject.toml # Dependencias, build con hatchling
├── config/
│ ├── security_config.yaml # Sandbox: dirs, blacklist, límites
│ ├── hana_config.yaml # Credenciales HANA (NO en git, ver .gitignore)
│ └── hana_config.yaml.example # Plantilla de configuración HANA
├── core/
│ ├── server.py # FastMCP + registro de las 28 tools
│ └── tools/
│ ├── filesystem.py # 9 tools de sistema de archivos
│ ├── terminal.py # 2 tools de terminal
│ ├── process.py # 2 tools de procesos (psutil)
│ ├── process_sessions.py # 5 tools de sesiones interactivas
│ ├── session_manager.py # SessionManager con asyncio.Queue
│ ├── hana.py # 8 tools SAP HANA Cloud
│ └── utils.py # Seguridad, config, plataforma
└── tests/
└── test_basic.py # 15 tests: seguridad, filesystem, stdioInstalación
cd C:\Users\Edu\DesktopCommanderPy
py -3.12 -m venv .venv
.venv\Scripts\activate
pip install -e .
pip install hdbcli # módulo SAP HANA Cloud
pip install pytest pytest-asyncio # solo para testsConfiguración de seguridad
config/security_config.yaml:
security:
allowed_directories:
- "C:/Users/Edu/Documents"
- "C:/Users/Edu/Desktop"
- "C:/Users/Edu/DesktopCommanderPy"
- "C:/Users/Edu/VerbaSant"
# añadir más según necesidad
blocked_commands:
- "format"
- "diskpart"
- "net user"
- "reg add"
- "reg delete"
- "shutdown"
write_blocked_extensions: [".exe", ".dll", ".sys"]
max_file_size_bytes: 10485760
max_read_lines: 2000
terminal:
default_timeout_seconds: 30
max_output_chars: 500000⚠️ Si
allowed_directoriesestá vacío, el sandbox está desactivado.
Arrancar el servidor
py main.py # stdio — Claude Desktop
py main.py --http --port 8080 # HTTP/SSE — clientes remotos
py main.py --log-level DEBUG # con logs detalladosConfigurar en Claude Desktop
%APPDATA%\Claude\claude_desktop_config.json:
{
"mcpServers": {
"DesktopCommanderPy": {
"command": "C:\\Users\\Edu\\DesktopCommanderPy\\.venv\\Scripts\\python.exe",
"args": ["C:\\Users\\Edu\\DesktopCommanderPy\\main.py"],
"env": {
"PYTHONUTF8": "1",
"PYTHONIOENCODING": "utf-8"
}
}
}
}Para añadir las credenciales HANA directamente aquí (opción recomendada):
"env": {
"PYTHONUTF8": "1",
"PYTHONIOENCODING": "utf-8",
"HANA_HOST": "tu-instancia.hanacloud.ondemand.com",
"HANA_PORT": "443",
"HANA_USER": "DBADMIN",
"HANA_PASSWORD": "tu_password",
"HANA_SCHEMA": ""
}Las 28 tools MCP disponibles
Filesystem + Config (11 tools)
Tool | Descripción |
| Lee fichero con paginación offset/length |
| Escribe o añade contenido. Crea dirs intermedios. |
| Edición quirúrgica find/replace. Solo el fragmento cambiado. |
| Lista con tamaños. Soporta recursivo con max_depth. |
| Búsqueda por glob (*.py) y/o contenido. fnmatch nativo. |
| Metadatos + preview primeras 10 líneas. |
| mkdir -p sandbox-aware. |
| Mueve/renombra dentro del sandbox. |
| Lee N ficheros en una llamada. |
| Devuelve la configuración runtime activa con tipos ( |
| Actualiza y persiste claves de configuración runtime sin editar YAML a mano. |
Terminal (2 tools)
Tool | Descripción |
| Ejecuta y captura stdout+stderr. Timeout configurable. |
| Recoge línea a línea. Para pip install, builds, etc. |
Gestión de procesos psutil (2 tools)
Tool | Descripción |
| Tabla PID/nombre/CPU%/memoria. Filtrable y ordenable. |
| SIGTERM (graceful) o SIGKILL (forzado). |
Sesiones interactivas (5 tools) ⭐
Tool | Descripción |
| Arranca proceso con stdin PIPE. Devuelve PID + output inicial. |
| Lee buffer acumulado sin bloquear. |
| Envía texto al stdin, espera respuesta. REPLs, shells. |
| Tabla de sesiones: PID, estado, tiempo activo, líneas. |
| SIGKILL + limpia sesión del registro. |
Flujo ejemplo — REPL Python interactivo:
start_process("python -i")
→ [PID 4521] Process started (running)
interact_with_process(4521, "import pyswisseph as swe")
interact_with_process(4521, "print(swe.calc_ut(2460000, 0))")
→ ((189.43, 1.0, 0.0, ...), 0)
interact_with_process(4521, "exit()")SAP HANA Cloud — hdbcli (8 tools) 🔷
Tool | Descripción |
| Verifica credenciales. Devuelve versión, usuario, schema, SSL. |
| SELECT / DML / CALL con tabla formateada. Límite de filas. |
| CREATE/ALTER/DROP. Requiere |
| Schemas visibles. Marca los de sistema (_SYS*, SYS, PUBLIC). |
| Tablas, vistas, Calc Views con nº columnas y tipo. |
| Estructura: tipo, longitud, nullable, PK, comentario. |
| Filas de N tablas vía M_TABLE_STATISTICS (rápido, sin full scan). |
| Memoria usada/límite, conexiones activas, alertas del sistema. |
Configurar credenciales SAP HANA Cloud
Las credenciales nunca se hardcodean en código y config/hana_config.yaml está
en .gitignore para que nunca lleguen a GitHub.
Opción A — Variables de entorno en claude_desktop_config.json (recomendada)
Ventajas: no hay fichero de credenciales en disco, fácil de cambiar por entorno.
"env": {
"HANA_HOST": "xxxxxxxx-xxxx.hana.trial-us10.hanacloud.ondemand.com",
"HANA_PORT": "443",
"HANA_USER": "DBADMIN",
"HANA_PASSWORD": "tu_password_aqui",
"HANA_SCHEMA": ""
}Opción B — Fichero local config/hana_config.yaml
hana:
host: "xxxxxxxx-xxxx.hana.trial-us10.hanacloud.ondemand.com"
port: 443
user: "DBADMIN"
password: "tu_password_aqui"
schema: ""
encrypt: true
sslValidateCertificate: true
max_rows: 200Copiar la plantilla y rellenar:
copy config\hana_config.yaml.example config\hana_config.yaml
# editar hana_config.yaml con datos realesCómo obtener el host en BTP Free Tier
Entra en BTP Cockpit
Selecciona tu subaccount → Instances and Subscriptions
Busca tu instancia SAP HANA Cloud
Haz clic en los tres puntos → Open in SAP HANA Database Explorer
El host está en la barra de conexión:
xxxxxxxx-xxxx.hana.trial-us10.hanacloud.ondemand.com(el puerto siempre es 443 en HANA Cloud)
Verificar la conexión tras configurar
Reinicia Claude Desktop y ejecuta:
hana_test_connection()Respuesta esperada:
✓ Conexión exitosa a SAP HANA Cloud
Host: tu-instancia.hanacloud.ondemand.com:443
Usuario: DBADMIN
Schema actual: DBADMIN
Versión HANA: 4.00.000.00.1234567890
Conexiones propias activas: 1
SSL/TLS: activadoFlujo típico de exploración
hana_test_connection() → verifica credenciales
hana_get_system_info() → estado del Free Tier
hana_list_schemas() → schemas disponibles
hana_list_tables("DBADMIN") → tablas del schema
hana_describe_table("MI_TABLA", "DBADMIN") → estructura de la tabla
hana_get_row_count("ORDERS,ITEMS,CUSTOMERS") → filas sin full scan
hana_execute_query("SELECT TOP 10 * FROM ORDERS") → datos
hana_execute_ddl("CREATE TABLE TEST (ID INT)", confirm=True)Límites del Free Tier a tener en cuenta
Memoria: 30 GB RAM total (monitorizeable con
hana_get_system_info)Almacenamiento: 120 GB disco
Conexiones simultáneas: limitadas —
hana_get_system_infomuestra el contadorLa instancia se para sola si no hay actividad en un período —
hana_test_connectionte dirá si está caída con un error de conexión claro
Tests
.venv\Scripts\pytest.exe tests/ -vSalida esperada: 32 passed in ~2-3s
Suite | Tests | Qué cubre |
| 4 | Sandbox de rutas permitidas |
| 3 | Blacklist de comandos peligrosos |
| 7 | read/write/edit/list/search/info |
| 1 | Integridad del canal JSON-RPC (crítico) |
| 2 | Config runtime tipada y persistencia |
Guía operacional — patrones y limitaciones conocidas
Sección de referencia rápida para uso desde Claude Desktop.
P1 — execute_command no encuentra python, python3 ni cmd
Síntoma: python: command not found o similar al ejecutar comandos Python.
Causa: Claude Desktop arranca con un PATH minimal de escritorio, no el PATH
completo de la sesión de usuario. execute_command hereda ese PATH restringido.
Solución A (fix permanente, ya integrado): build_subprocess_env() en utils.py
enriquece automáticamente el PATH del subprocess con los directorios del venv activo,
el Python base y el launcher py.exe. Desde la versión actual esto es transparente.
Solución B (si A falla): usar Desktop Commander:start_process con py explícito:
Desktop Commander:start_process { command: "py script.py", timeout_ms: 25000 }P2 — C:/temp/ bloqueado para escritura
Causa: security_config.yaml tiene una lista explícita de allowed_directories.
C:\temp no está en ella, no es un bug.
Directorios permitidos en este sistema:
C:/Users/Edu/Documents(y subdirectorios, incluidoClaudeWork)C:/Users/Edu/DesktopC:/Users/Edu/DownloadsC:/Users/Edu/DesktopCommanderPyC:/Users/Edu/VerbaSantC:/Users/Edu/AstroExtractoC:/Users/Edu/AstroCompendiumC:/Users/Edu/MetaAstrumC:/Users/Edu/VTTsC:/Users/Edu/astro_cartas
Destino por defecto recomendado: C:/Users/Edu/Documents/
P2b — Paths relativos, ~ y Windows mezclan mal separadores
Estado actual: resuelto en la capa runtime nueva.
Ahora todas las tools principales pasan por un helper común que:
expande
~resuelve rutas relativas contra el
cwdnormaliza separadores y casing en Windows
usa
resolve(strict=False)antes de validar sandbox
Eso evita muchos falsos negativos típicos de Windows cuando una ruta entra como:
~/algo.txt, .\archivo.py, C:/Users/Edu/... o C:\Users\Edu\...
Implementación: core/tools/utils.py → resolve_and_validate_path()
P2c — Config stringly-typed: true/false, números y arrays acababan mal
Estado actual: resuelto con configuración runtime central.
Antes, cada módulo podía releer YAML y varias flags acababan tratándose como texto. Ahora existe una única fuente de verdad:
core/runtime_config.pycore/tools/config_tools.py
Y se exponen dos tools MCP nuevas:
get_config()
set_config_value(key, value)Los tipos se preservan como tipos Python reales:
boolintstrlist[str]
Esto hace el servidor mucho más predecible y evita bugs por valores tipo "false" o "45" tratados como strings.
P3 — Desktop Commander:write_file (Node.js) bloquea la palabra dd
Causa: El servidor Node.js Desktop Commander tiene su propio blacklist de
comandos de shell. La cadena dd coincide como substring, bloqueando cualquier
fichero cuyo contenido incluya esa secuencia (nombres de variable, paths, texto).
Solución: usar DesktopCommanderPy:write_file para escribir ficheros con
contenido arbitrario — no tiene ese filtro. Reservar Desktop Commander:write_file
solo si DesktopCommanderPy no responde por permisos de path.
P4 — Encoding: UnicodeEncodeError con caracteres especiales en Windows
Causa: La consola de Windows usa cp1252 por defecto. Caracteres como ≤, °,
→ causan UnicodeEncodeError si el script no fuerza UTF-8.
Solución A (preferida, ya integrada): build_subprocess_env() fija
PYTHONUTF8=1 y PYTHONIOENCODING=utf-8 en todos los subprocesos.
Solución B: lanzar con py -X utf8 script.py.
Solución C: añadir al inicio del script:
import sys, io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')Solución D (fallback): evitar caracteres especiales en el output:
usar d en vez de °, <= en vez de ≤, -> en vez de →.
P5 — REPL interactivo frágil: no pegar funciones multilínea
Síntoma: errores de indentación o sintaxis al enviar bloques de código
al REPL (py -i + interact_with_process).
Causa: el protocolo de sesiones interactivas no maneja bien los bloques multilínea — el REPL ve las líneas de forma fragmentada.
Solución: siempre escribir el script completo a fichero y ejecutarlo de una sola vez. Nunca intentar pegar funciones o clases enteras en el REPL.
Patrón correcto:
DesktopCommanderPy:write_file → C:/Users/Edu/Documents/script.py
Desktop Commander:start_process → py -X utf8 C:/Users/Edu/Documents/script.pyP6 — present_files solo funciona con rutas /mnt/... del contenedor Claude
Causa: present_files genera enlaces de descarga solo para el filesystem
interno del contenedor Claude (/mnt/user-data/outputs/). No puede crear
enlaces para C:\Users\Edu\....
Solución: indicar al usuario la ruta local donde está guardado el fichero. No hay workaround disponible desde el servidor MCP.
🐛 Bugs críticos resueltos — diario de guerra
Bug 1 — spawn uv ENOENT: Claude Desktop no arrancaba
Período: 8 de marzo al 26 de marzo de 2026.
Síntomas:
%APPDATA%\Claude\logs\mcp-server-*.log→spawn uv ENOENTen buclemain1.log→Request timed out: isGuestConnectedrepetido cada pocos segundosClaude Desktop colgado en la pantalla de carga
Más de 10 procesos de Claude bloqueados en segundo plano (detectados por Gemini CLI)
Causa raíz:
El MCP oficial Desktop Commander usa uv para gestionar su entorno Python.
uv no estaba instalado o no estaba en el PATH que hereda Claude Desktop al
arrancar como aplicación de escritorio — que es diferente al PATH de la terminal.
Solución:
# 1. Instalar uv (script oficial Astral)
# → binario en C:\Users\Edu\.local\bin\uv.exe
# 2. Añadir al PATH de usuario del SISTEMA (no solo de la sesión)
[System.Environment]::SetEnvironmentVariable(
"PATH",
"C:\Users\Edu\.local\bin;" + [System.Environment]::GetEnvironmentVariable("PATH","User"),
"User"
)
# 3. Verificar
[System.Environment]::GetEnvironmentVariable("PATH","User")
# debe empezar por: C:\Users\Edu\.local\bin;...
# 4. Reiniciar Claude DesktopVerificación:
C:\Users\Edu\.local\bin\uv.exe --version
# uv 0.11.1Bug 2 — Banner ASCII de FastMCP: Claude Desktop se colgaba al conectar
Síntomas:
Claude Desktop arrancaba pero nunca terminaba de inicializar el MCP propio
El servidor arrancaba (visible en logs) pero Claude nunca recibía respuesta de
initializeDetectado y diagnosticado por Gemini CLI analizando los logs
Causa raíz:
FastMCP imprime por defecto un banner ASCII decorativo por stdout al arrancar.
Claude Desktop usa JSON-RPC estricto sobre stdout: cualquier byte no-JSON rompe el
protocolo y deja a Claude esperando indefinidamente sin mensaje de error.
╭────────────────────────────╮
│ FastMCP Server v3.x │ ← esto va a stdout y destruye el canal JSON-RPC
╰────────────────────────────╯La regla fundamental del transporte stdio MCP:
stdoutes un canal binario exclusivo para JSON-RPC. Absolutamente nada más puede escribirse en él. Logs, banners y mensajes van astderr.
Solución:
# main.py — CRÍTICO: nunca eliminar este flag
mcp.run(transport="stdio", show_banner=False)Test de regresión: TestStdioTransport::test_server_stdout_is_clean_on_startup
lanza el proceso real y verifica que el primer byte de stdout sea {.
Si una actualización futura de FastMCP cambia el comportamiento, el test falla antes
de llegar a Claude Desktop.
Bug 3 — Deadlock stdin: Python/pytest devolvían output vacío
Síntomas:
Get-Date,where.exe,dir→ funcionaban perfectamenteCualquier proceso Python (incluido pytest) → output vacío, timeout o cuelgue total
El proceso Python aparecía en el gestor de tareas corriendo pero sin terminar
Causa raíz:
Al lanzar subprocesos sin especificar stdin, el hijo hereda el stdin del padre —
que en este caso es el canal JSON-RPC de Claude Desktop. Python y otros intérpretes
leen stdin al arrancar para detectar modo interactivo. Al hacerlo, bloquean esperando
input que nunca llega → deadlock en cascada:
Claude Desktop → [JSON-RPC stdin] → Servidor MCP
↓
asyncio.create_subprocess_exec
↓ (sin stdin=DEVNULL)
Python hijo hereda stdin MCP
↓
Python lee stdin → BLOQUEO ETERNO
↓
Servidor MCP espera al hijo → BLOQUEO
↓
Claude Desktop espera al servidor → BLOQUEOSolución:
proc = await asyncio.create_subprocess_exec(
*shell_args, command,
stdin=asyncio.subprocess.DEVNULL, # ← el hijo ve /dev/null, no el canal MCP
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.STDOUT,
cwd=cwd,
env=env,
)Aplicado en execute_command y execute_command_streaming.
Nota: Las sesiones interactivas (start_process) usan stdin=PIPE deliberadamente
— es lo que permite enviarles input con interact_with_process. La diferencia es que
ahí el stdin lo gestiona el servidor, no lo hereda del canal MCP.
Arquitectura — Gestor de sesiones
session_manager.py implementa un SessionManager singleton con un dict
{pid: ProcessSession} por proceso activo.
Cada ProcessSession contiene:
El objeto
asyncio.subprocess.ProcessUn
asyncio.Queuedonde se acumula todo el outputUn
asyncio.Taskque drenastdouten background línea a líneaMetadatos: comando, timestamp de inicio, líneas emitidas, estado
start_process("python -i")
├── create_subprocess_exec(stdin=PIPE, stdout=PIPE)
├── ProcessSession(pid, queue=Queue())
├── asyncio.create_task(drain_output(session)) ← background forever
└── sessions.register(session)
drain_output [Task en background]:
async for line in process.stdout:
await queue.put(line)
await queue.put(None) ← señal de fin de stream
interact_with_process(pid, "print('hola')"):
├── process.stdin.write(b"print('hola')\n")
├── await process.stdin.drain()
└── read_output(session, timeout=8s)
└── asyncio.wait_for(queue.get(), 0.5s) × N iteracionesHistorial de commits
Hash | Descripción |
| Scaffold inicial: 10 tools, seguridad, 14 tests |
| Fix: fnmatch para glob en search_files → 15/15 tests |
| Config: rutas reales, fix hatch build target |
| Chore: ignorar scripts auxiliares _.bat / _.py |
| Fix: show_banner=False — banner FastMCP rompía JSON-RPC |
| Fix: stdin=DEVNULL — deadlock heredando stdin MCP |
| Docs: README completo en castellano |
| Feat: sesiones interactivas + mkdir/move/multi-read → 18 tools |
| Docs: README con arquitectura, bugs y roadmap detallado |
| Feat: módulo SAP HANA Cloud — hdbcli, 8 tools → 26 total |
| Runtime config central + tools get/set config + path/env robustos → 32/32 tests |
Bug 4 — Matching de substring en blacklist: dd bloqueaba address, adding, hidden…
Detectado: 28 de marzo de 2026.
Síntomas:
Desktop Commander:write_file(Node.js) bloqueaba ficheros con contenido normal que contenía la cadenadd(variables, paths, palabras)Pero también el propio
check_command_allowedde DesktopCommanderPy afectado: comandos legítimos comoblack --reformat .eran bloqueados si contenían subcadenas coincidentes con tokens de la blacklist
Causa raíz:
El matching era blocked.lower() in cmd_lower — búsqueda de substring pura.
El token "dd" en blocked_commands coincidía en cualquier posición:
# Antes del fix — INCORRECTO
"dd" in "address" # True → bloqueaba 'address'
"dd" in "adding" # True → bloqueaba 'adding'
"format" in "reformat" # True → bloqueaba '--reformat'Solución:
# Después del fix — word-boundary regex
pattern = r"\b" + re.escape(blocked.lower()) + r"\b"
re.search(pattern, "address") # None → permitido ✓
re.search(pattern, "dd if=...") # Match → bloqueado ✓
re.search(r"\bformat\b", "--reformat") # None → permitido ✓
re.search(r"\bformat\b", "format C:") # Match → bloqueado ✓Los patrones multi-palabra como "net user" siguen funcionando exactamente igual.
Bug 5 — PATH minimal: subprocesos no encontraban python, python3, pip
Detectado: 28 de marzo de 2026.
Síntomas:
execute_command("python script.py")→python: command not foundexecute_command("pip install X")→ error similarGet-Date,dir,where.exe→ funcionaban sin problema
Causa raíz: Claude Desktop se lanza como aplicación de escritorio de Windows, no desde una terminal de usuario. El PATH que hereda es el PATH del sistema, sin las entradas que el instalador de Python añade al PATH del usuario:
PATH de terminal usuario: C:\Users\Edu\AppData\Local\Programs\Python\Python312\Scripts;...
PATH heredado por Claude: C:\Windows\System32;C:\Windows;... (sin Python)Solución — build_subprocess_env() en utils.py:
def build_subprocess_env(extra=None):
env = os.environ.copy()
env["PYTHONUTF8"] = "1"
env["PYTHONIOENCODING"] = "utf-8"
# Prepend: venv Scripts, base Python Scripts, C:\Windows (py.exe), LOCALAPPDATA Python
...
return envAplicado en execute_command y execute_command_streaming. Los subprocesos
ahora reciben el PATH completo independientemente de cómo arrancó Claude Desktop.
Roadmap| Feature | Prioridad |
|---------|-----------|
| Tests para módulo HANA (mock de hdbcli) | 🔴 Alta |
| get_config / set_config_value en runtime | 🟡 Media |
| Audit log con rotación | 🟡 Media |
| copy_file | 🟡 Media |
| start_search asíncrono con paginación | 🟡 Media |
| Restricciones allowed_dirs por tool | 🟢 Baja |
| Modo multi-IA: HTTP + auth token | 🟢 Baja |
| Tools astrología (pyswisseph, VTTs) | 🟢 Baja |
| Tools SAP adicionales (pyrfc, RFC ping) | 🟢 Baja |
Licencia
MIT — haz lo que quieras, conserva la nota de copyright.
Available Tools
28 toolscreate_directoryA
Crea un directorio (y todos los intermedios necesarios).
Equivale a mkdir -p. Si el directorio ya existe, no falla. La ruta debe estar dentro de los directorios permitidos.
Inputs: path (required). Returns: result
edit_file_diffA
Edit a file by replacing an exact text snippet with new content.
This is the preferred editing approach: send only the changed part instead of rewriting the whole file. The old_string must match exactly (whitespace, indentation) and should include enough context to be unique.
Raises ValueError if old_string is not found or found more/fewer times than expected_replacements.
Inputs: path (required), old_string (required), new_string (required), expected_replacements. Returns: result
execute_commandA
Execute a shell command and return its combined stdout+stderr output.
Uses PowerShell on Windows, bash/zsh on Linux/macOS. The command is checked against the security blacklist before execution. Output is captured and returned as a string (truncated if too large).
Returns the combined output. On non-zero exit code, output includes the exit code so the caller can detect failures.
Inputs: command (required), working_directory, timeout_seconds, environment. Returns: result
execute_command_streamingA
Execute a long-running command and return output incrementally.
Intended for commands that produce output over time (builds, tests, long scripts). Output is collected line by line and returned as a single string; for true streaming, the MCP client would use SSE.
The command is blocked if it matches the security blacklist.
Inputs: command (required), working_directory, timeout_seconds, environment. Returns: result
force_terminateA
Mata un proceso inmediatamente sin esperar a que termine limpiamente.
Equivale a SIGKILL en Linux o TerminateProcess en Windows. Usa kill_process con force=False para un cierre más limpio (SIGTERM). Limpia la sesión del registro tras terminar.
Inputs: pid (required). Returns: result
get_configA
Return the active runtime configuration with type metadata.
Inputs: no named parameters. Returns: object
get_file_infoA
Return metadata about a file or directory.
Includes: type, size, creation time, modification time, permissions, and a content preview for text files (first 10 lines).
Inputs: path (required). Returns: result
hana_describe_tableA
Describe la estructura de una tabla en SAP HANA Cloud.
Devuelve columnas con tipo de dato, longitud, nullable, clave primaria y comentario de columna si existe. Equivale a DESC table en SQL*Plus.
Inputs: table_name (required), schema. Returns: result
hana_execute_ddlA
Ejecuta una sentencia DDL en SAP HANA Cloud (CREATE, ALTER, DROP, GRANT...).
REQUIERE confirm=True explícito — protección contra ejecuciones accidentales. DROP y TRUNCATE son irreversibles. Úsalo con cuidado.
Inputs: sql (required), confirm. Returns: result
hana_execute_queryA
Ejecuta una sentencia SQL en SAP HANA Cloud y devuelve los resultados.
Para consultas SELECT devuelve una tabla formateada con los resultados. Para INSERT/UPDATE/DELETE devuelve las filas afectadas. Para CALL (stored procedures) devuelve el resultado del procedure.
El número de filas está limitado para evitar volcar tablas enteras. Usa max_rows para ajustar el límite.
Inputs: sql (required), schema, max_rows. Returns: result
hana_get_row_countA
Devuelve el número de filas de una o varias tablas.
Rápido para monitorización — usa M_TABLE_STATISTICS en lugar de COUNT(*).
Inputs: tables (required), schema. Returns: result
hana_get_system_infoA
Devuelve información del sistema SAP HANA Cloud: memoria, CPU, alertas activas.
Útil para monitorización básica del Free Tier (que tiene límites de recursos).
Inputs: no named parameters. Returns: result
hana_list_schemasA
Lista los schemas visibles para el usuario actual en SAP HANA Cloud.
Muestra nombre del schema, propietario y si es un schema de sistema.
Inputs: filter_name. Returns: result
hana_list_tablesA
Lista tablas, vistas y Calculation Views de un schema en SAP HANA Cloud.
Muestra nombre, tipo, número de columnas y comentario si existe.
Inputs: schema (required), filter_name, table_type. Returns: result
hana_test_connectionA
Prueba la conexión a SAP HANA Cloud y devuelve información del servidor.
Verifica credenciales, versión de HANA, usuario conectado y schema actual. No devuelve nunca la contraseña ni datos sensibles.
Inputs: no named parameters. Returns: result
interact_with_processA
Envía input a un proceso activo y devuelve su respuesta.
Ideal para REPLs interactivos: Python (-i), Node.js (-i), shells, etc. El input se escribe en el stdin del proceso y se espera output nuevo.
Ejemplo de flujo:
start_process('python -i') → PID 1234
interact_with_process(1234, 'import pandas as pd')
interact_with_process(1234, 'df = pd.read_csv("datos.csv")')
interact_with_process(1234, 'print(df.describe())')
kill_process(1234)
Inputs: pid (required), input_text (required), timeout_seconds, max_lines. Returns: result
kill_processA
Terminate a running process by PID.
By default sends SIGTERM (graceful shutdown). Set force=True to immediately kill the process (SIGKILL on Linux, TerminateProcess on Windows).
Returns confirmation or error message.
Inputs: pid (required), force. Returns: result
list_directoryA
List the contents of a directory with file sizes and types.
Returns a formatted tree showing [DIR] and [FILE] entries with sizes. Respects the allowed_directories sandbox.
Inputs: path (required), recursive, max_depth. Returns: result
list_processesA
List running processes with PID, name, CPU%, and memory usage.
Uses psutil for cross-platform compatibility (Windows, Linux, macOS). Results are filtered and sorted as requested.
Returns a formatted table of processes.
Inputs: filter_name, sort_by. Returns: result
list_sessionsA
Lista todas las sesiones de proceso activas (start_process).
Muestra PID, comando, estado, tiempo activo y líneas emitidas. Las sesiones terminadas se limpian automáticamente al listarlas.
Inputs: no named parameters. Returns: result
move_fileA
Mueve o renombra un fichero o directorio.
Funciona entre rutas dentro de los directorios permitidos. Si el destino es un directorio existente, mueve el origen dentro de él. Si el destino no existe, renombra el origen a ese nombre.
Inputs: source (required), destination (required). Returns: result
read_fileA
Read a text file and return its contents, with optional pagination.
Pagination via offset and length allows reading large files in chunks without loading everything into the LLM context. The security sandbox is enforced: the path must be inside an allowed directory.
Returns the file text. Raises PermissionError or FileNotFoundError on error.
Inputs: path (required), offset, length. Returns: result
read_multiple_filesA
Lee varios ficheros de texto en una sola llamada.
Útil para comparar ficheros o cargar múltiples módulos de una vez. Devuelve el contenido de cada fichero separado por cabeceras claras.
Inputs: paths (required), max_lines_each. Returns: result
read_process_outputA
Lee el output acumulado de un proceso activo.
Espera hasta timeout_seconds por output nuevo. Si el proceso ha terminado, devuelve todo el output pendiente en el buffer. Llama a esta tool repetidamente para leer output de forma incremental.
Devuelve el output y el estado del proceso (running/finished).
Inputs: pid (required), timeout_seconds, max_lines. Returns: result
search_filesA
Search for files by name pattern and/or content substring.
pattern is matched against file names using glob syntax OR substring match.
content_search scans file contents (text files only, skips binary).
Returns a list of matching absolute paths with optional match context.
Inputs: root (required), pattern (required), content_search, case_sensitive, +1 more. Returns: result
set_config_valueA
Update a runtime config value and persist it to YAML.
Inputs: key (required), value (required). Returns: object
start_processA
Arranca un proceso en segundo plano y devuelve su PID.
A diferencia de execute_command, el proceso queda vivo y con su stdout/stderr siendo capturados en un buffer interno. Usa read_process_output para leer el output acumulado e interact_with_process para enviar input (ideal para REPLs).
Devuelve el PID y el output inicial (primeros segundos de arranque).
Inputs: command (required), working_directory, timeout_seconds. Returns: result
write_fileA
Write or append text content to a file.
The parent directory is created automatically if it doesn't exist. The path must be inside an allowed directory and the extension must not be in the blocked list.
Returns a success message with the number of lines written.
Inputs: path (required), content (required), mode. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 28 tools
Most tools have distinct purposes, e.g., file vs. process vs. database. Minor overlap between kill_process and force_terminate, and execute_command vs. execute_command_streaming, but descriptions clarify the differences.
All tool names follow a consistent verb_noun snake_case pattern (e.g., create_directory, execute_command, hana_describe_table). No mixing of styles or unexpected variations.
With 28 tools, the count is high but still manageable. It spans file operations, process management, SAP HANA, and config, which may justify the count, but it feels slightly heavy for a single MCP server.
The file tools cover create, read, write, edit, move, list, search, but notably lack delete and copy operations, which are obvious gaps for a desktop commander. Process and HANA tools are more complete.
Related MCP Connectors
Augments MCP Server - A comprehensive framework documentation provider for Claude Code
Shared memory MCP server for Claude Code, Codex, Gemini CLI and Cursor. Cited, editable.
MCP server unifying ERPs, CRMs, APIs and knowledge base for Claude, ChatGPT and Gemini.
Remote MCP server exposing your Node Command fleet (files, shell, processes, browser) to AI hosts.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceMCP server that enables Claude to control your computer, similar to Anthropic's computer use but easy to set up locally.4,118 npm396MIT
- FlicenseAqualityDmaintenanceA safe MCP server for sandboxed filesystem operations (list, move, create directories, delete files) via pure Python, designed for Claude Desktop.5-
- AlicenseNot gradedqualityDmaintenanceA secure MCP server that allows Claude to read and write local files on your machine with explicit approval gating for each access.MIT
- AlicenseAqualityCmaintenanceRuns as an MCP server providing file system operations, shell execution, and system information tools, allowing Claude or any MCP client to edit files and control the machine.7MIT