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:

  1. “Pokaż mi faktury sprzedaży z maja 2026”
  2. “Top 10 klientów po obrocie w 2026”
  3. “Klienci z zaległościami >60 dni”
  4. “SKU poniżej minimum”
  5. “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


Powiązane