Initial commit
This commit is contained in:
473
mcp-server/README.md
Normal file
473
mcp-server/README.md
Normal file
@@ -0,0 +1,473 @@
|
||||
# Acai Code MCP Server
|
||||
|
||||
Servidor MCP (Model Context Protocol) para Acai que permite a Claude y otros agentes IA acceder y manipular el código, módulos, tablas y registros de proyectos Acai.
|
||||
|
||||
## 📋 Contenido
|
||||
|
||||
- [Instalación Local](#instalación-local)
|
||||
- [Docker (Producción)](#docker-producción)
|
||||
- [Configuración de Clientes](#configuración-de-clientes)
|
||||
- [Desarrollo](#desarrollo)
|
||||
- [Estructura del Proyecto](#estructura-del-proyecto)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Instalación Local
|
||||
|
||||
### Requisitos
|
||||
|
||||
- Node.js >= 16
|
||||
- npm o yarn
|
||||
|
||||
### Pasos
|
||||
|
||||
1. **Instalar dependencias**
|
||||
|
||||
```bash
|
||||
cd server
|
||||
npm install
|
||||
```
|
||||
|
||||
2. **Iniciar el servidor en modo desarrollo**
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
El servidor estará disponible en `http://localhost:3000/sse`
|
||||
|
||||
3. **Iniciar con watch mode** (recarga automática)
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
4. **Verificar que funciona**
|
||||
|
||||
```bash
|
||||
curl http://localhost:3000/health
|
||||
```
|
||||
|
||||
Deberías ver:
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"activeSessions": 0,
|
||||
"mode": "sse"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🐳 Docker (Producción)
|
||||
|
||||
### Requisitos
|
||||
|
||||
- Docker instalado
|
||||
- Docker Compose (opcional pero recomendado)
|
||||
|
||||
### Construcción de la imagen
|
||||
|
||||
```bash
|
||||
# Desde la carpeta server/
|
||||
docker build -t acai-mcp-server .
|
||||
```
|
||||
|
||||
### Ejecución
|
||||
|
||||
**Opción 1: Docker Compose (Recomendado)**
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
Esto inicia:
|
||||
- Servidor MCP en puerto 3000
|
||||
- Monitor UI en puerto 4545 (opcional)
|
||||
- Auto-restart habilitado
|
||||
|
||||
Detener:
|
||||
```bash
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
**Opción 2: Docker directo**
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name acai-mcp-server \
|
||||
--restart unless-stopped \
|
||||
-p 3000:3000 \
|
||||
acai-mcp-server
|
||||
```
|
||||
|
||||
### Ver logs
|
||||
|
||||
```bash
|
||||
docker logs acai-mcp-server -f
|
||||
```
|
||||
|
||||
### Parar/Reiniciar
|
||||
|
||||
```bash
|
||||
docker stop acai-mcp-server
|
||||
docker start acai-mcp-server
|
||||
docker restart acai-mcp-server
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Configuración de Clientes
|
||||
|
||||
### Claude Code (Recomendado)
|
||||
|
||||
Crea el archivo `.mcp.json` en la raíz de tu proyecto:
|
||||
|
||||
#### Opción A: Con X-User-Token (Simple)
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"acai-code": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"mcp-remote",
|
||||
"http://localhost:3000/sse",
|
||||
"--header",
|
||||
"X-User-Token: {TU_TOKEN_AQUI}"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Opción B: Con X-Acai-Token (Completo)
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"acai-code": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"mcp-remote",
|
||||
"http://localhost:3000/sse",
|
||||
"--header",
|
||||
"X-Acai-Token: {TU_TOKEN_AQUI}",
|
||||
"--header",
|
||||
"X-Acai-Token-Hash: {TU_TOKEN_HASH_AQUI}",
|
||||
"--header",
|
||||
"X-Acai-Website: {TU_DOMINIO_AQUI}"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Obtener credenciales
|
||||
|
||||
1. Abre `https://cms.acaisuite.com/admin.php?debug=1`
|
||||
2. Busca en la consola o en los Network headers:
|
||||
- **X-User-Token**: Token único (contiene el dominio automáticamente)
|
||||
- **X-Acai-Token**: Token de sesión
|
||||
- **X-Acai-Token-Hash**: Hash de validación
|
||||
- **X-Acai-Website**: Tu dominio
|
||||
|
||||
### Servidor remoto
|
||||
|
||||
Si el Docker está en otra máquina:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"acai-code": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"mcp-remote",
|
||||
"http://192.168.1.100:3000/sse",
|
||||
"--header",
|
||||
"X-User-Token: {TU_TOKEN_AQUI}"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 👨💻 Desarrollo
|
||||
|
||||
### Estructura
|
||||
|
||||
```
|
||||
server/
|
||||
├── tools/
|
||||
│ ├── modules/ # Herramientas para módulos
|
||||
│ ├── tables/ # Herramientas para tablas
|
||||
│ ├── records/ # Herramientas para registros
|
||||
│ ├── files/ # Herramientas para archivos
|
||||
│ ├── media/ # Herramientas para media
|
||||
│ ├── auth/ # Herramientas de autenticación
|
||||
│ └── helpers/ # Utilidades compartidas
|
||||
├── auth/
|
||||
│ ├── apiClient.js # Cliente HTTP con auto-login
|
||||
│ ├── credentials.js # Gestión de credenciales
|
||||
│ └── index.js # Exportaciones
|
||||
├── utils/
|
||||
│ ├── moduleParser.js # Parser de componentes Acai
|
||||
│ └── remoteParser.js # Parser remoto (appParser)
|
||||
├── resources/ # Guías y documentación
|
||||
├── server.js # Punto de entrada principal
|
||||
├── httpServer.js # Servidor HTTP/SSE
|
||||
└── package.json
|
||||
```
|
||||
|
||||
### Agregar una nueva herramienta
|
||||
|
||||
1. **Crear archivo** `tools/category/toolname.js`:
|
||||
|
||||
```javascript
|
||||
import { z } from "zod";
|
||||
import { withAuth, getSessionCredentials, getApiClient } from "../../auth/index.js";
|
||||
import { handleToolError, validateRequired, handleApiResponse } from "../helpers/errorHandler.js";
|
||||
|
||||
export function registerMyToolTool(server) {
|
||||
server.tool(
|
||||
"my_tool",
|
||||
"Descripción de la herramienta",
|
||||
{
|
||||
param1: z.string().describe("Descripción del parámetro"),
|
||||
},
|
||||
withAuth(async ({ param1 }, extra) => {
|
||||
try {
|
||||
const credentials = getSessionCredentials(extra.sessionId);
|
||||
const client = await getApiClient(extra.sessionId);
|
||||
|
||||
// Tu lógica aquí
|
||||
const response = await client.post("/endpoint", {
|
||||
action_ws: "mi_accion",
|
||||
});
|
||||
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }],
|
||||
};
|
||||
} catch (error) {
|
||||
return handleToolError(error, 'my_tool', { param1 });
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
2. **Registrar en** `tools/category/index.js`:
|
||||
|
||||
```javascript
|
||||
import { registerMyToolTool } from './toolname.js';
|
||||
|
||||
export function registerCategoryTools(server) {
|
||||
// ... otras herramientas
|
||||
registerMyToolTool(server);
|
||||
}
|
||||
```
|
||||
|
||||
3. **Probar**
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Scripts disponibles
|
||||
|
||||
```bash
|
||||
npm start # Iniciar servidor
|
||||
npm run dev # Desarrollo con watch
|
||||
npm test # Ejecutar tests
|
||||
npm run lint # Verificar linting
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Herramientas Disponibles
|
||||
|
||||
### Módulos (6)
|
||||
- `list_modules` - Listar módulos
|
||||
- `get_module` - Obtener contenido
|
||||
- `save_module` - Crear/actualizar
|
||||
- `check_module` - Validar sintaxis
|
||||
- `check_module_usage` - Ver dónde se usa
|
||||
- `delete_module` - Eliminar
|
||||
|
||||
### Tablas (6)
|
||||
- `list_tables` - Listar tablas
|
||||
- `get_table_schema` - Ver estructura
|
||||
- `create_table` - Crear tabla
|
||||
- `edit_table_field` - Editar campo
|
||||
- `delete_table_field` - Eliminar campo
|
||||
- `get_table_templates` - Obtener templates
|
||||
|
||||
### Registros (5)
|
||||
- `list_records` - Listar registros
|
||||
- `get_record` - Obtener uno
|
||||
- `create_record` - Crear
|
||||
- `update_record` - Actualizar
|
||||
- `delete_record` - Eliminar
|
||||
|
||||
### Archivos (4)
|
||||
- `list_files` - Listar archivos
|
||||
- `read_file` - Leer contenido
|
||||
- `write_file` - Crear/actualizar
|
||||
- `delete_file` - Eliminar
|
||||
|
||||
### Media (3)
|
||||
- `list_media` - Listar media
|
||||
- `upload_media` - Subir archivo
|
||||
- `delete_media` - Eliminar
|
||||
|
||||
### Auth (1)
|
||||
- `get_session_info` - Info de sesión
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Autenticación
|
||||
|
||||
### X-User-Token (Recomendado)
|
||||
|
||||
- Token único por usuario
|
||||
- Incluye automáticamente el dominio
|
||||
- Simplifica la configuración
|
||||
- Trigger auto-login en primera petición
|
||||
|
||||
### X-Acai-Token + X-Acai-Token-Hash + X-Acai-Website
|
||||
|
||||
- Más flexible
|
||||
- Permite cambiar dominio
|
||||
- Requiere 3 headers
|
||||
- Más control
|
||||
|
||||
### Auto-login
|
||||
|
||||
Si solo envías X-User-Token:
|
||||
1. Se detecta en la conexión SSE
|
||||
2. En la primera petición a una herramienta, se hace login
|
||||
3. Las credenciales se cachean en la sesión
|
||||
4. Las peticiones posteriores usan el token cacheado
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Puerto 3000 en uso
|
||||
|
||||
```bash
|
||||
# Encontrar proceso en puerto 3000
|
||||
lsof -i :3000
|
||||
|
||||
# Matar proceso
|
||||
kill -9 <PID>
|
||||
|
||||
# O cambiar puerto
|
||||
MCP_PORT=3001 npm start
|
||||
```
|
||||
|
||||
### Error: "Token no válido" (403)
|
||||
|
||||
- Verifica que el token no ha expirado
|
||||
- Obtén uno nuevo desde `https://cms.acaisuite.com/admin.php?debug=1`
|
||||
- Revisa los logs: `docker logs acai-mcp-server -f`
|
||||
|
||||
### Error: "window is not defined"
|
||||
|
||||
- Asegúrate de pasar `listTables` a `parseComponents()`
|
||||
- Revisa que `remoteParser.js` tiene las variables seteadas correctamente
|
||||
|
||||
### Conexión rechazada
|
||||
|
||||
```bash
|
||||
# Verifica que está corriendo
|
||||
curl http://localhost:3000/health
|
||||
|
||||
# Ver logs
|
||||
npm run dev
|
||||
# o
|
||||
docker logs acai-mcp-server -f
|
||||
```
|
||||
|
||||
### Tools no disponibles
|
||||
|
||||
- Verifica headers en `.mcp.json`
|
||||
- Comprueba que el token es válido
|
||||
- Revisa los logs del servidor
|
||||
|
||||
---
|
||||
|
||||
## 📝 Variables de entorno
|
||||
|
||||
```bash
|
||||
MCP_PORT=3000 # Puerto del servidor MCP
|
||||
MCP_MONITOR_PORT=4545 # Puerto del Monitor UI
|
||||
MCP_MONITOR_DISABLED=0 # Desactivar Monitor UI
|
||||
ACAI_TOKEN=... # Token por defecto (no recomendado)
|
||||
ACAI_WEBSITE=... # Dominio por defecto
|
||||
ACAI_TOKEN_HASH=... # Hash por defecto
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Actualizar
|
||||
|
||||
### Versión local
|
||||
|
||||
```bash
|
||||
git pull origin main
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
```bash
|
||||
# Reconstruir imagen
|
||||
docker build -t acai-mcp-server .
|
||||
|
||||
# Reiniciar contenedor
|
||||
docker restart acai-mcp-server
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📖 Recursos
|
||||
|
||||
- **Guía Acai**: `resources/guia-programacion-acai.md`
|
||||
- **Atributos**: `resources/guia-atributos-acai.md`
|
||||
- **Twig Filters**: `resources/guia-twig-filters.md`
|
||||
- **Builder Vars**: `resources/guia-builder-vars.md`
|
||||
- **PHP Hooks**: `resources/guia-php-hooks.md`
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Contribuir
|
||||
|
||||
1. Fork el proyecto
|
||||
2. Crea una rama: `git checkout -b feature/nueva-herramienta`
|
||||
3. Haz commit: `git commit -am 'Agregar nueva herramienta'`
|
||||
4. Push: `git push origin feature/nueva-herramienta`
|
||||
5. Abre un Pull Request
|
||||
|
||||
---
|
||||
|
||||
## 📞 Soporte
|
||||
|
||||
Para problemas o preguntas:
|
||||
1. Revisa los logs: `docker logs acai-mcp-server -f`
|
||||
2. Verifica la configuración en `.mcp.json`
|
||||
3. Abre un issue en el repositorio
|
||||
|
||||
---
|
||||
|
||||
## 📄 Licencia
|
||||
|
||||
Igual que el proyecto principal de Acai.
|
||||
|
||||
---
|
||||
|
||||
**Última actualización**: Diciembre 2025
|
||||
Reference in New Issue
Block a user