Pohoda MCP
Servidor MCP para el software de contabilidad Pohoda (checo) - leer y crear facturas, pedidos, inventario, contactos a través de la API XML de mServer.
Documentación
Servidor MCP Pohoda
Servidor MCP para el software contable Pohoda de Stormware. Se comunica con Pohoda a través de mServer XML API.
Conecta a tu asistente de IA directamente con la contabilidad. Pregunta por facturas, navega por el directorio, verifica el inventario, crea nuevos documentos o imprime una factura en PDF. Solo escribe lo que necesitas y el servidor MCP se encargará de la comunicación con Pohoda.
Requisitos
- PHP 8.1+
- ext-curl, ext-dom, ext-simplexml
- Pohoda con mServer activo (esquema versión 2)
Configuración de mServer en Pohoda
Antes de usar el servidor MCP, es necesario activar y configurar mServer en Pohoda.
1. Apertura de la administración de mServer
En el programa Pohoda, abre la agenda Unidades contables, en el menú selecciona Base de datos > POHODA mServer.
2. Administración de configuraciones
Se abre un cuadro de diálogo con la lista de configuraciones de mServer. Para cada configuración se muestra el nombre, puerto, estado de ejecución, host y PID.
3. Creación de una nueva instancia
Haz clic en Nuevo y en la pestaña Básico configura:
- Nombre del mServer
- Unidad contable con la que se comunicará el mServer
- Puerto para la comunicación (por defecto 444)
En la pestaña HTTPS se puede activar la comunicación segura:
En la pestaña Monitoreo se puede activar el registro de comunicación:
4. Ejecución
Selecciona la configuración y haz clic en Ejecutar (o haz doble clic en el registro). mServer comenzará a escuchar en el puerto configurado.
Alternativamente, mServer se puede controlar desde la línea de comandos usando el interruptor /HTTP sobre pohoda.exe. Como último parámetro se indica el nombre de la configuración (entre comillas si contiene espacios):
& "C:\Program Files (x86)\STORMWARE\POHODA\Pohoda.exe" /HTTP start "eShop-1"
& "C:\Program Files (x86)\STORMWARE\POHODA\Pohoda.exe" /HTTP stop "eShop-1"
& "C:\Program Files (x86)\STORMWARE\POHODA\Pohoda.exe" /HTTP restart "eShop-1"
& "C:\Program Files (x86)\STORMWARE\POHODA\Pohoda.exe" /HTTP list
Otros comandos: stop /f (terminación forzada), list:xml (listado de configuraciones en XML). Para el inicio automático al arrancar el sistema, Stormware recomienda el Programador de tareas de Windows (no un servicio de Windows).
Para más detalles, consulta la documentación de Stormware.
Instalación del servidor MCP
git clone https://github.com/dg/pohoda-mcp.git
cd pohoda-mcp
composer install
Configuración
El servidor se configura mediante variables de entorno:
| Variable | Descripción | Valor por defecto |
|---|---|---|
POHODA_URL | URL del mServer | http://localhost:444 |
POHODA_ICO | ICO de la unidad contable | |
POHODA_USERNAME | Nombre de usuario para mServer | |
POHODA_PASSWORD | Contraseña | |
POHODA_EXE_PATH | Ruta a Pohoda.exe para el inicio automático de mServer (opcional) | |
POHODA_CONFIG_NAME | Nombre de la configuración de mServer para el inicio automático (opcional) |
Si se configuran POHODA_EXE_PATH y POHODA_CONFIG_NAME, el servidor verificará antes de la primera llamada a una herramienta que mServer esté en ejecución; si no lo está, lo iniciará automáticamente mediante pohoda.exe /HTTP start. Al finalizar el servidor MCP, lo detendrá nuevamente, pero solo si fue él quien lo inició (si mServer ya estaba en ejecución, lo dejará corriendo). Solo Windows (mServer es parte de Pohoda).
Uso en agentes (p. ej., Claude Code)
La configuración lista está en el archivo .mcp.json.example. Cópialo y completa la ruta absoluta a server.php y las credenciales de acceso. Las dos últimas variables son opcionales y sirven para el inicio automático de mServer en la primera llamada a una herramienta (ver arriba). Dónde va el archivo depende de la herramienta:
| Herramienta | Ubicación |
|---|---|
| Claude Code | .mcp.json en la raíz del proyecto |
| Claude Desktop | contenido en %APPDATA%\Claude\claude_desktop_config.json |
| Cursor | .cursor/mcp.json en el proyecto, o ~/.cursor/mcp.json para todos los proyectos |
| Gemini CLI | .gemini/settings.json en el proyecto, o ~/.gemini/settings.json |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
VS Code (Copilot) usa la clave servers y puede solicitar la contraseña al iniciar, por lo que no tiene que estar en el archivo. En .vscode/mcp.json:
{
"inputs": [
{"type": "promptString", "id": "pohoda-password", "description": "Heslo k mServeru", "password": true}
],
"servers": {
"pohoda": {
"type": "stdio",
"command": "php",
"args": ["/cesta/k/pohoda-mcp/server.php"],
"env": {
"POHODA_URL": "http://localhost:444",
"POHODA_ICO": "12345678",
"POHODA_USERNAME": "Admin",
"POHODA_PASSWORD": "${input:pohoda-password}"
}
}
}
}
OpenAI Codex CLI tiene la configuración en TOML, en ~/.codex/config.toml:
[mcp_servers.pohoda]
command = "php"
args = ["/cesta/k/pohoda-mcp/server.php"]
env = { POHODA_URL = "http://localhost:444", POHODA_ICO = "12345678", POHODA_USERNAME = "Admin", POHODA_PASSWORD = "" }
Nunca subas el archivo con la contraseña al repositorio. Si guardas la configuración en el proyecto, agrégala a .gitignore.
Herramientas disponibles
status
Verifica si mServer está en ejecución y responde. La llamada básica devuelve solo un texto breve de GET /status (Pohoda responde con una cadena simple, no XML). Con el parámetro companyDetail=true además, mediante una consulta autenticada, devuelve el nombre de la unidad contable, el nombre de la base de datos y el año contable actual.
| Parámetro | Descripción |
|---|---|
companyDetail | true / false — devolver también datos de la unidad contable activa (por defecto false) |
list_documents, list_stock, list_contacts
Tres herramientas de lectura divididas según el tipo de registro. Las agendas específicas/de listas (centre, activity, store, bankAccount, cashRegister, numericalSeries) no están disponibles mediante una herramienta dedicada; usa raw_xml.
list_documents
Documentos. Parámetro agenda — uno de los siguientes:
| Agenda | Descripción | Agenda | Descripción | |
|---|---|---|---|---|
invoice | facturas* | prijemka | recibos de entrada | |
order | pedidos | vydejka | albaranes de salida | |
voucher | documentos de caja | prodejka | tickets de venta | |
bank | banco | prevodka | transferencias | |
contract | proyectos | vyroba | producción | |
intDoc | documentos internos | accountancy | diario contable | |
offer | ofertas | |||
enquiry | solicitudes de presupuesto |
* La agenda invoice requiere el parámetro invoiceType: issuedInvoice o receivedInvoice.
Filtros: id, dateFrom, dateTill, company, ico, number (coincidencia exacta del valor completo, no subcadena), lastChanges (registros modificados desde YYYY-MM-DDThh:mm:ss), limit (por defecto 100, recorte del cliente).
list_stock
Inventario. Filtros: id, code, name, ean, storage (ruta en la estructura del almacén, p. ej., "ZBOZI/Elektro"), store (abreviatura del almacén), internet (true/false), lastChanges, limit.
list_contacts
Directorio. Filtros: id, company, ico, lastChanges, limit.
create_invoice
Creación de una factura emitida o recibida. Admite:
- dirección del socio directamente o vínculo al directorio (
partnerId) - símbolo variable, fecha de vencimiento, fecha de devengo
- precontabilización, método de pago, cuenta bancaria
- centro, actividad, proyecto
- moneda extranjera con tipo de cambio
- partidas con vínculo a la ficha de almacén (
stockCode)
create_address
Creación de un registro en el directorio (empresa/contacto).
create_stock
Creación de una ficha de almacén. Además de los datos básicos (código, nombre, precio), admite:
- EAN, PLU para cajas registradoras
- indicadores para venta y tienda en línea
- descripción, complemento del nombre, nombre corto
- stock mínimo y máximo, peso
- proveedor, garantía
create_order
Creación de un pedido recibido o emitido con partidas.
Impresión o exportación a PDF de cualquier registro. Puede:
- imprimir en impresora (predeterminada o específica)
- exportar a archivo PDF en el servidor (
pdfPathes obligatorio para la ruta del PDF) - devolver el PDF como Base64 directamente en la respuesta (
pdfBase64=true, requierepdfPath)
La agenda se especifica en checo: vydane_faktury, prijate_faktury, zasoby, adresar, pokladna, banka, interni_doklady, zakazky, vydejky, prijemky, prodejky, vydane_objednavky, prijate_objednavky, vydane_nabidky, prijate_nabidky, etc.
El ID del informe de impresión (reportId) varía según la instalación y las personalizaciones. En Pohoda puedes encontrarlo en el Editor de informes de impresión (menú Archivo → Informes de impresión), donde en cada informe ves la columna ID, o mediante clic derecho en el informe en el diálogo de impresión → Propiedades. Los informes estándar incluidos tienen ID en el rango de cientos a miles (típicamente 200–3000+).
raw_xml
Envío de XML arbitrario. Cubre los casos en los que las demás herramientas no son suficientes. El XML se inserta directamente en el sobre <dat:dataPackItem>, por lo que debe contener sus propias declaraciones de namespace.
Recursos de referencia (recursos MCP)
Los listados de valores permitidos se exponen como recursos MCP, por lo que el cliente puede obtenerlos sin una llamada a herramienta:
| URI | Contenido |
|---|---|
pohoda://enums/agendas | lista de agendas dividida según qué herramienta de listado las cubre |
pohoda://enums/vat-rates | valores permitidos de vatRate en partidas (none, low, high) |
pohoda://enums/payment-types | valores de paymentType de facturas (draft, cash, card, compensation) |
pohoda://enums/print-agendas | nombres checos de agendas aceptados por print |
Uso desde código PHP (sin MCP)
La biblioteca también se puede usar directamente como cliente PHP para mServer, independientemente de MCP. Es útil para scripts propios, cronjobs o integración en una aplicación existente.
use DG\Pohoda\PohodaClient;
$client = new PohodaClient(
url: 'http://localhost:444',
ico: '12345678',
username: 'Admin',
password: '',
);
// Najdi fakturu podle čísla dokladu
$list = $client->listRecords('invoice', ['number' => '26010192'], 'issuedInvoice');
$faId = (int) $list->items[0]->data['invoice'][0]['invoiceHeader']['id'];
// Vytiskni ji do PDF
$client->printRecord([
'agenda' => 'vydane_faktury',
'recordId' => $faId,
'reportId' => 3000,
'pdfPath' => 'C:\\tmp\\faktura.pdf',
]);
Métodos públicos de PohodaClient: getStatus(), listRecords(), createInvoice(), createAddress(), createStock(), createOrder(), printRecord(), sendRawXml().
Iniciar y detener mServer
Si el script no puede asumir que mServer ya está en ejecución, la clase MServerController es útil. Es un envoltorio delgado sobre pohoda.exe /HTTP start|stop que inicia Pohoda sin bloqueo y, tras el inicio, consulta PohodaClient::getStatus() hasta que mServer comienza a responder. Solo Windows.
La forma más sencilla es pasarlo a PohodaClient — este iniciará automáticamente mServer de forma diferida antes de la primera solicitud HTTP y lo detendrá al destruirse (solo si fue él quien lo inició; si ya estaba en ejecución, lo dejará corriendo):
use DG\Pohoda\MServerController;
use DG\Pohoda\PohodaClient;
$client = new PohodaClient(url: 'http://127.0.0.1:555', ico: '12345678', username: 'Admin', password: '');
$client->setController(new MServerController(
exePath: 'C:\Program Files (x86)\STORMWARE\POHODA\Pohoda.exe',
configName: 'mServer1',
));
// ... práce s $client — autostart se postará o sebe ...
Si quieres gestionar el ciclo de vida manualmente, el controlador puede hacer lo mismo directamente:
$ctrl = new MServerController(exePath: '...', configName: 'mServer1');
$wasRunning = false;
try {
$client->getStatus();
$wasRunning = true;
} catch (\RuntimeException) {
$ctrl->start($client); // vrátí se až když mServer odpovídá (nebo vyhodí po timeoutu)
}
// ... práce s $client ...
if (!$wasRunning) {
$ctrl->stop();
}
Al llamar a los endpoints HTTP, usa http://127.0.0.1:555, no http://localhost:555 — el resolver de PHP intenta primero IPv6 para localhost (::1), donde mServer no escucha, y se espera innecesariamente hasta el tiempo de espera.
Métodos públicos de MServerController:
start(PohodaClient $client, int $timeoutSeconds = 30)— inicia Pohoda con/HTTP start, espera hasta que el estado de la API HTTP responda. En caso de tiempo de espera, lanzaRuntimeException.stop()— envía/HTTP stopfire-and-forget, no espera la finalización.
Solución de problemas
| Síntoma | Causa probable |
|---|---|
Curl Error: Connection refused | mServer no está en ejecución; inícialo en Pohoda o mediante pohoda.exe /HTTP start |
HTTP 401 | POHODA_USERNAME / POHODA_PASSWORD incorrectos |
| La respuesta es HTML con página de inicio de sesión | El usuario en Pohoda no tiene permisos para mServer o la agenda está abierta por otra instancia |
state="error" + note="Nepodařila se validace dokumentu podle schématu" | Estructura XML incorrecta — típicamente namespace intercambiado o elemento obligatorio faltante; el texto del error indica el elemento |
listRecords devuelve lista vacía | mServer está conectado a una unidad contable/año diferente al del documento (verifica status con companyDetail=true) |
pdfPath se crea pero no se puede abrir (0 B) | mServer no tiene permisos para escribir en esa ubicación — prueba el D:\Data\ucto\Tisk\ predeterminado o el directorio temporal del usuario bajo el que se ejecuta Pohoda |
Print devuelve OK pero el PDF no se genera | reportId no existe en la instalación; verifica el ID en el Editor de informes de impresión |
Estructura del proyecto
server.php vstupní bod MCP serveru (stdio transport)
.mcp.json.example vzorová konfigurace MCP klienta
src/
McpTools.php tenký MCP adaptér (#[McpTool] atributy)
PohodaClient.php HTTP klient a doménové metody pro mServer API
XmlBuilder.php stavba XML požadavků přes XMLWriter
Response.php parsovaná odpověď z mServeru
ResponseItem.php jeden záznam z odpovědi
MServerController.php spouštění a zastavování mServeru přes pohoda.exe




