MCP servers dla księgowości — Comarch Optima i Symfonia w praktyce
Model Context Protocol (MCP) to standard ogłoszony przez Anthropic pod koniec 2024, w 2025 stał się fundamentem integracji AI z systemami biznesowymi. Pokazujemy konkretne przykłady MCP serverów dla Comarch Optima i Symfonia — kod, konfiguracja, błędy do uniknięcia, doświadczenia z 6 wdrożeń.
MCP (Model Context Protocol) pozwala AI bezpośrednio gadać z Waszym ERP-em, bazą danych, systemem CRM. Brzmi technicznie, ale po dwóch miesiącach praktyki widzimy: to jest najważniejsza warstwa integracji AI w polskiej księgowości. Pokazujemy jak wygląda MCP server do Comarch Optima i Symfonia — z kodem, błędami i lekcjami.
Po co MCP w księgowości
Bez MCP musicie pisać dedykowane integracje dla każdego scenariusza: jedna do raportu miesięcznego, inna do reconciliacji, trzecia do analizy faktur. Z MCP — jeden serwer udostępnia "tools" (akcje, które AI może wywołać) i wszystkie scenariusze działają w jednolitym interfejsie. Po naszej stronie: 1 raz piszemy konektor do Optimy, AI może go używać do 47 różnych zadań.
MCP server do Comarch Optima — architektura
Optima nie ma oficjalnego API w sensie REST — ma SDK COM/.NET, dostęp przez bazę SQL Server, i webservice (CDN_API) który nie wszyscy mają wykupiony. Najczęściej spotykane podejście: bezpośrednio do bazy SQL Server (read-only) + zewnętrzny moduł do operacji modyfikujących.
// claude-mcp-optima/src/server.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import sql from "mssql";
import { z } from "zod";
const pool = await sql.connect({
server: process.env.OPTIMA_SERVER,
database: process.env.OPTIMA_DB,
user: process.env.OPTIMA_USER,
password: process.env.OPTIMA_PASS,
options: { trustServerCertificate: true }
});
const server = new McpServer({ name: "comarch-optima", version: "1.2.0" });
server.tool(
"list_invoices",
{
nip: z.string().regex(/^\d{10}$/).describe("NIP kontrahenta (10 cyfr)"),
date_from: z.string().describe("Data od, format YYYY-MM-DD"),
date_to: z.string().describe("Data do, format YYYY-MM-DD")
},
async ({ nip, date_from, date_to }) => {
const result = await pool.request()
.input("nip", sql.VarChar, nip)
.input("df", sql.Date, date_from)
.input("dt", sql.Date, date_to)
.query(`
SELECT TOP 500
TrN_NumerString as numer,
TrN_DataOpe as data,
TrN_NettoSystem as netto,
TrN_BruttoSystem as brutto,
TrN_Status as status
FROM CDN.TraNag
WHERE TrN_PodKodKreskowy = @nip
AND TrN_DataOpe BETWEEN @df AND @dt
ORDER BY TrN_DataOpe DESC
`);
return { content: [{ type: "text", text: JSON.stringify(result.recordset) }] };
}
);
server.tool(
"get_unpaid_total",
{ nip: z.string().regex(/^\d{10}$/) },
async ({ nip }) => {
const r = await pool.request()
.input("nip", sql.VarChar, nip)
.query(`
SELECT SUM(TrN_BruttoSystem) as total
FROM CDN.TraNag
WHERE TrN_PodKodKreskowy = @nip AND TrN_Status = 'N'
`);
return { content: [{ type: "text", text: `Niezapłacone: ${r.recordset[0].total} PLN` }] };
}
);
Tools które warto wystawić
list_invoices(nip, date_from, date_to)— lista fakturget_unpaid_total(nip)— niezapłaconeget_company_details(nip)— dane kontrahentalist_documents_by_type(type, period)— np. wszystkie WZ z lipcaget_vat_register(month)— rejestr VAT za miesiącsearch_payments(amount, tolerance)— wyszukiwanie po kwocie z tolerancją
MCP server do Symfonia
Symfonia (linia Mała Księgowość / Handel / Premium) ma własne API REST od wersji 2023, znacznie wygodniejsze niż Optima. Konfiguracja jest prostsza:
// claude-mcp-symfonia/src/server.ts
server.tool(
"list_invoices",
{ nip: z.string(), month: z.string() },
async ({ nip, month }) => {
const r = await fetch(`${SYMFONIA_API}/v1/invoices?nip=${nip}&month=${month}`, {
headers: { "Authorization": `Bearer ${TOKEN}` }
});
return { content: [{ type: "text", text: await r.text() }] };
}
);
Pięć błędów, które popełniliśmy w pierwszych wdrożeniach
1. Brak limitu wyników
Nasze pierwsze list_invoices nie miało TOP 500. Claude przy pytaniu "wszystkie faktury klienta X" dostawał 8 000 rekordów, kontekst się rozjeżdżał, koszt zapytania skakał do 7 USD. Lekcja: każde query MUSI mieć limit + paginację.
2. Zwracanie wszystkich kolumn
SELECT * dawał Claude'owi 47 kolumn z każdej faktury — większość niepotrzebnych. Wyciągnęliśmy 6 kluczowych. Koszty tokenów spadły o 70%.
3. Brak walidacji NIP po stronie tool
Claude czasem wywoływał list_invoices("123") — krótkie NIP. Bez walidacji query trafiał do bazy i zwracał błąd SQL, Claude próbował go "naprawić" w pętli. Schema z z.string().regex(/^\d{10}$/) zatrzymuje to wcześniej.
4. Logowanie zapytań
Bez logu nie wiedzieliśmy co AI robi z bazą. Teraz każde wywołanie tool zapisuje: timestamp, model, tool name, parametry, czas, koszt. Audyt obowiązkowy w wdrożeniach księgowych.
5. Brak read-only
W jednym wdrożeniu eksperymentalnie daliśmy Claude'owi tool do modyfikacji faktur. Po 3 dniach AI "poprawił" 12 faktur (na szczęście dev środowisko). Lekcja: produkcyjnie tylko READ. Modyfikacje — przez UI z potwierdzeniem człowieka.
Realne metryki z 6 wdrożeń
| Klient | System | Tools | Zapytań / dzień | Czas avg |
|---|---|---|---|---|
| Biuro księgowe A (18 os.) | Comarch Optima | 14 | ~340 | 2,1 s |
| Biuro księgowe B (8 os.) | Symfonia Mała | 8 | ~120 | 1,4 s |
| Kancelaria prawna (11 os.) | Symfonia + custom | 11 | ~80 | 1,8 s |
| Firma logistyczna (45 os.) | Comarch ERP XL | 22 | ~620 | 2,4 s |
| Produkcja (52 os.) | Symfonia Handel | 18 | ~280 | 1,9 s |
| E-commerce (24 os.) | Comarch Optima + WooCommerce | 26 | ~480 | 2,2 s |
Kierunek na 2025/2026
Standard MCP rośnie szybko — w sierpniu 2025 mamy już ponad 240 publicznych MCP serverów (GitHub, bazy danych, narzędzia analityczne). Anthropic, Google, OpenAI — wszyscy wspierają. To znaczy, że to jest standardowa warstwa integracji AI na najbliższe lata. Inwestycja w MCP zwraca się długoterminowo.
Mamy gotowe MCP servery dla Comarch Optima, Symfonia, WAPRO, Sage, oraz custom integracje. Pokażemy je w działaniu na Waszych danych testowych.
Chcesz przetestować, jak AI rozwiąże to u Ciebie?
30 minut rozmowy + pokaz działającego wdrożenia u klienta. Bez NDA.
Umów demo