Klient pyta: “Czy mogę gadać z moim Subiektem przez Claude?”. Stary stack = 8-16h prace. Z MCP = 2h. Pokazuję tutorial step-by-step.
Wymagania techniczne
- Python 3.11+ (lub TypeScript jeśli wolisz, mcp-typescript SDK)
- Subiekt GT klienta (wersja 1.50+, COM/ADO accessible)
- Claude Desktop u klienta ($20/mc Pro)
- 2h Twojego czasu skupionego
Stack rekomendowany: Python + mcp-python SDK + pyodbc dla połączenia z bazą Sybase / SQL Server Subiekta.
Krok 1 (15 min): Setup projektu
mkdir subiekt-mcp-{client_name}
cd subiekt-mcp-{client_name}
python -m venv .venv
source .venv/bin/activate # macOS/Linux
# .venv\Scripts\activate # Windows
pip install mcp pyodbc python-dotenv
Plik .env:
SUBIEKT_DSN=Subiekt_GT_DSN_Name
SUBIEKT_USER=Szef
SUBIEKT_PASS=hasło_klienta
SUBIEKT_DB_PATH=C:\InsERT\Subiekt GT\Dane\Klient
Krok 2 (30 min): MCP server stub
subiekt_mcp_server.py:
import os
from mcp import Server
from mcp.types import TextContent
import pyodbc
from dotenv import load_dotenv
load_dotenv()
server = Server("subiekt-mcp-client")
def _connect():
"""Połączenie z bazą Subiekta GT przez DSN."""
conn_str = f"DSN={os.getenv('SUBIEKT_DSN')};UID={os.getenv('SUBIEKT_USER')};PWD={os.getenv('SUBIEKT_PASS')}"
return pyodbc.connect(conn_str)
@server.tool()
def query_invoices(year: int, month: int = None) -> dict:
"""
Pobierz faktury sprzedaży z Subiekta GT.
Args:
year: rok (np. 2026)
month: opcjonalnie miesiąc 1-12
Returns: lista faktur z numerem, datą, klientem, kwotą netto/brutto
"""
conn = _connect()
cursor = conn.cursor()
sql = """
SELECT dok_NrPelny, dok_DataWyst, kh_Symbol, dok_NettoVPLN, dok_BruttoVPLN
FROM tw__Dokument
INNER JOIN kh__Kontrahent ON dok_KhID = kh_Id
WHERE dok_Typ = 1 AND YEAR(dok_DataWyst) = ?
"""
params = [year]
if month:
sql += " AND MONTH(dok_DataWyst) = ?"
params.append(month)
sql += " ORDER BY dok_DataWyst DESC"
cursor.execute(sql, params)
invoices = [dict(zip([col[0] for col in cursor.description], row)) for row in cursor.fetchall()]
return {"count": len(invoices), "invoices": invoices[:100]} # truncate dla LLM context
@server.tool()
def query_stock_below_minimum() -> dict:
"""Lista SKU poniżej minimum (jeśli klient ma ustawione minima)."""
conn = _connect()
cursor = conn.cursor()
cursor.execute("""
SELECT tw_Symbol, tw_Nazwa, sl_Stan, tw_StanMin
FROM tw__Towar
INNER JOIN sl__Stan ON tw_Id = sl_TwId
WHERE sl_Stan < tw_StanMin AND tw_StanMin > 0
ORDER BY (tw_StanMin - sl_Stan) DESC
""")
items = [dict(zip([col[0] for col in cursor.description], row)) for row in cursor.fetchall()]
return {"count": len(items), "items": items}
@server.tool()
def query_clients_with_arrears(days_overdue: int = 30) -> dict:
"""Klienci B2B z należnościami przeterminowanymi."""
conn = _connect()
cursor = conn.cursor()
cursor.execute(f"""
SELECT kh_Symbol, kh_Nazwa,
SUM(dok_BruttoVPLN - ISNULL(zap_Kwota, 0)) AS suma_zaleglosci,
MIN(dok_DataPlatnosc) AS najstarsza_data
FROM tw__Dokument
INNER JOIN kh__Kontrahent ON dok_KhID = kh_Id
LEFT JOIN zp__Zaplata ON dok_Id = zap_DokId
WHERE dok_Typ = 1
AND DATEDIFF(day, dok_DataPlatnosc, GETDATE()) > {days_overdue}
GROUP BY kh_Symbol, kh_Nazwa
HAVING SUM(dok_BruttoVPLN - ISNULL(zap_Kwota, 0)) > 0
ORDER BY suma_zaleglosci DESC
""")
clients = [dict(zip([col[0] for col in cursor.description], row)) for row in cursor.fetchall()]
return {"count": len(clients), "clients": clients}
# Dodaj kolejne tools w miarę potrzeb klienta
if __name__ == "__main__":
server.run(transport="stdio")
Krok 3 (15 min): Test lokalny przed Claude Desktop
Sprawdź czy server startuje:
python subiekt_mcp_server.py
# Powinno działać bez błędów (czeka na stdin)
# Ctrl+C
Test query bezpośrednio:
python -c "
from subiekt_mcp_server import query_invoices
result = query_invoices(2026, 5)
print(f'Found {result[\"count\"]} invoices')
print(result['invoices'][:2])
"
Jeśli zwraca dane, server działa. Jeśli pyodbc.Error, sprawdź:
- DSN skonfigurowany w ODBC Administrator (Windows)
- Subiekt GT zainstalowany na tym komputerze
- Login/hasło klienta poprawne
Krok 4 (15 min): Claude Desktop config
U klienta ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) lub %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"subiekt-client": {
"command": "python",
"args": ["C:\\Path\\To\\subiekt_mcp_server.py"],
"env": {
"SUBIEKT_DSN": "Subiekt_GT_DSN_Name",
"SUBIEKT_USER": "Szef",
"SUBIEKT_PASS": "hasło"
}
}
}
}
Restart Claude Desktop. W chat icon kluczyka → powinieneś widzieć subiekt-client tools.
Krok 5 (45 min): Test promptów + dokumentacja
Test 5 promptów na realnej bazie klienta:
- “Pokaż mi faktury sprzedaży z maja 2026”
- “Top 10 klientów po obrocie w 2026”
- “Klienci z zaległościami >60 dni”
- “SKU poniżej minimum”
- “Co sprzedaliśmy wczoraj?”
Jeśli wszystko działa, dokumentacja dla klienta (1-strona PDF): - Jak zadawać pytania (przykłady) - 10 gotowych promptów do skopiowania - Co AI umie / nie umie - Kontakt do Ciebie w razie problemów
Krok 6 (opcjonalnie): Multi-tenant + auth
Dla wielu klientów, niech każdy klient ma swój katalog z .env:
clients/
├── client_a/
│ ├── .env
│ └── subiekt_mcp_server.py (link symboliczny)
└── client_b/
├── .env
└── subiekt_mcp_server.py (link symboliczny)
Plus dla bezpieczeństwa: read-only login w Subiekcie (Szef ma full access, ale dla MCP daj user z tylko SELECT permissions na tabele tw__*, kh__*, zp__*).
Realna wycena projektu
Wycena freelancera dla typowego klienta MŚP:
- Bazowy MCP server (5-10 tools, read-only): 800-1500 zł netto jednorazowo
- Custom tools per workflow klienta (np. integracja z BaseLinkerem, własne raporty marży): +500-2000 zł per custom
- Setup u klienta (Meet 90 min + dokumentacja PDF): 300-500 zł (możesz wliczyć w cenę bazowego)
- Maintenance (update Subiekta klienta, bug fix, nowe tools): 150-300 zł netto/mc
Albo partner program SubiektMCP: polecasz klientom gotowy SubiektMCP (Basic 99 zł netto/mc), dostajesz 20% prowizji rekurencyjnej (~19.80 zł/mc per klient). Przy 20 klientach = 400 zł/mc pasywnego dochodu, bez maintenance.
Pułapki
Pułapka 1: Subiekt update. InsERT czasem zmienia schemat bazy w update’ach. MCP server może przestać działać. Mitigacja: trzymaj 2 wersje bazowych queries (legacy + nowy), wykrywaj wersję w _connect().
Pułapka 2: LLM truncation. Claude ma context limit ~200k tokens. Jeśli zwracasz 10k faktur, Claude może truncatować. Mitigacja: zawsze LIMIT w SQL, returnuj summary + top N.
Pułapka 3: Klient nie pamięta hasła do Subiekta. Mitigacja: poproś o admin account, zrób mu dedykowany read-only login z silnym hasłem przechowanym w password manager.
Pułapka 4: Klient ma niestandardowy schemat (customy InsERT Sfera). Mitigacja: 30 min discovery przed wyceną. Custom schematy = +500-1500 zł.
Spróbuj SubiektMCP albo partner program
- Trial 14 dni: subiektgt.chat/trial
- Partner program 20% prowizji: napisz nikodem@subiektgt.chat
- 3-min formularz: subiektgt.chat/qualification
Powiązane
- MCP vs REST: przewaga dla freelancera, architektura
- Subiekt GT Sfera vs MCP, porównanie z InsERT Sfera