MCP fuer Applikationsingenieure

Zielpublikum

Sie sind Applikationsingenieur und wollen den MCP-Server von ForgeIEC Studio direkt aufrufen, statt nur ueber den Chat-Reiter im Studio selbst zu arbeiten. Typische Einsatzfaelle:

  • Mit einem kleinen Skript (z.B. Shell, Python, PowerShell) wiederkehrende Aktionen automatisieren — etwa abends alle Projektdateien testkompilieren
  • Eine eigene Pruef-Routine anstossen — z.B. nach jedem Deploy einen festen Diagnose-Loop fahren
  • Ein anderes Werkzeug anbinden — z.B. ein Excel- oder Auswertungs-Programm das Live-Werte abholt
  • Verstehen wie der Server intern reagiert wenn etwas schief geht und ein eigener Aufruf-Pfad gebraucht wird

Diese Seite gibt die Protokoll-Details + ablauffaehige Beispiele mit curl (standard auf Linux + Windows).


Protokoll-Lifecycle

MCP folgt strikt einem 3-Phasen-Lifecycle:

1. initialize     →  Server stellt sich vor: protocolVersion,
                      serverInfo, capabilities, instructions
2. tools/list     →  Server liefert komplette Tool-Liste mit Schemas
3. tools/call     →  Client ruft ein Tool auf; Loop fuer alle weiteren
                      Calls

Spec: https://modelcontextprotocol.io/specification.

ForgeIEC implementiert Version 2025-03-26 + capabilities.tools. listChanged: true.


Endpunkte

Der ForgeIEC-MCP-Server hoert standardmaessig auf:

PfadMethodeZweck
/mcp/v1/infoGETHealth-Check (kein Auth noetig)
/mcp/v1/manifestGETStatisches Manifest (Spec-konform fuer Discovery)
/mcp/v1/rpcPOSTJSON-RPC 2.0 Wire-Endpoint
/mcp/v1/eventsGET (SSE)Server-Sent-Events fuer asynchrone Push-Updates (z.B. Live-Monitor-Stream)

Default-Port: 7531 (siehe IT-Seite wenn Sie das aendern muessen).

Lokal-only-Bind (127.0.0.1) wenn kein Profil mit acceptsInboundMcp = true existiert; sonst 0.0.0.0 und Auth zwingend.


Authentifizierung

ForgeIEC unterstuetzt zwei Stufen:

Bearer-Token

Ein 256-bit Token pro Profil. Der Editor zeigt es im Preferences → AI → Profile → Bearer Token-Feld. Setzen Sie es im Authorization-Header:

curl -k https://forgeiec-ws.local:7531/mcp/v1/info \
     -H "Authorization: Bearer <ihr-token-hier>"

-k weil das Server-Cert selbst-signiert ist (siehe naechster Abschnitt fuer Trust-Setup).

mTLS (Mutual TLS, optional)

Wenn Sie ein Team-Setup haben (Caretaker hat Member-Certs ausgestellt), koennen Sie statt Bearer mit einem Client-Cert anmelden:

curl https://forgeiec-ws.local:7531/mcp/v1/info \
     --cacert /pfad/zum/team-ca.pem \
     --cert   /pfad/zum/eigenen-cert.pem \
     --key    /pfad/zum/eigenen-cert.key

Der Server akzeptiert dann entweder Bearer oder Client-Cert.


initialize-Aufruf

Erst die Server-Identitaet abrufen:

curl -sk -X POST https://forgeiec-ws.local:7531/mcp/v1/rpc \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-03-26",
      "clientInfo": { "name": "my-script", "version": "0.1" },
      "capabilities": {}
    }
  }'

Response (gekuerzt):

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-03-26",
    "serverInfo": { "name": "forgeiec-mcp", "version": "v1" },
    "capabilities": { "tools": { "listChanged": true } },
    "instructions": "ForgeIEC MCP server (v1) ..."
  }
}

instructions ist wichtig: Hier steht ForgeIEC’s Sicherheits- Modell, der empfohlene Diagnose-Loop und der Anti-Loop-Hint fuer LLM-Clients. Wenn Sie einen Client schreiben, leiten Sie das in die System-Prompt-Schicht weiter.


Tool-Liste abrufen

curl -sk -X POST https://forgeiec-ws.local:7531/mcp/v1/rpc \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {}
  }'

Die Antwort enthaelt ca. 80 Tools, jedes mit:

{
  "name": "project.summary",
  "description": "Returns project metadata...",
  "inputSchema": { "type": "object", "properties": {}, "required": [] }
}

Zur menschen-lesbaren Uebersicht ueber alle Tools rufen Sie forge.help (gruppiert nach Familie) oder forge.help_for(name) (detailliert pro Tool) auf — letzteres ist gedacht damit ein LLM sich selbst weiterbilden kann ohne dass Sie ihn briefen muessen.


Tool-Aufruf

Beispiel: project.summary (kein Input):

curl -sk -X POST https://forgeiec-ws.local:7531/mcp/v1/rpc \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0", "id": 3, "method": "tools/call",
    "params": {
      "name": "project.summary",
      "arguments": {}
    }
  }'

Response-Struktur (MCP-Spec-konform):

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"ok\": true, \"data\": {\"project_name\": ..., \"pou_count\": ...}}"
      }
    ],
    "isError": false
  }
}

Der inhaltliche Envelope (im text-Feld als JSON-String):

{
  "ok": true,
  "data": { ... },
  "audit": {
    "called_by": "...",
    "timestamp": "2026-05-12T20:13:05Z",
    "tool": "project.summary"
  }
}

Bei Fehler:

{
  "ok": false,
  "error": "FORGE_ERR_NO_PROJECT",
  "message": "no project is open",
  "remediation": {
    "next_steps": ["project.open with path=..."],
    "rule": "..."
  }
}

Die error-Codes sind alle FORGE_ERR_<KIND> (nicht generische HTTP-Codes) — siehe naechster Abschnitt.


Confirmation State Machine

Schreibende Tools (project.write.*, codegen.deploy, runtime.stop, editor.quit, …) returnen beim ersten Aufruf typischerweise:

{
  "ok": false,
  "error": "FORGE_ERR_CONFIRMATION_REQUIRED",
  "confirmation": {
    "id": "cfa63753-0878-47de-8c48-db9e81a7de6d",
    "question": "Add bellows.Bellows.LED_00 (iec_type=BOOL)?",
    "options": ["yes"],
    "context": { "tool": "project.write.add_variable", ... },
    "expires_ms": 1778616326671
  }
}

Ihr Client muss dann editor.confirm mit id + choice aufrufen:

curl -sk -X POST https://forgeiec-ws.local:7531/mcp/v1/rpc \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0", "id": 4, "method": "tools/call",
    "params": {
      "name": "editor.confirm",
      "arguments": {
        "id": "cfa63753-0878-47de-8c48-db9e81a7de6d",
        "choice": "yes"
      }
    }
  }'

Die Response von editor.confirm ist das Ergebnis des urspruenglich aufgerufenen Tools (das Tool wird auf der Server- Seite resumed). Es bedeutet: Sie sehen jetzt das add_variable- Result, nicht eine Confirm-Bestaetigung.

choice = "cancel" bricht ab → FORGE_ERR_USER_CANCELED.

Timeout: 5 Minuten Default; danach choice = "timeout".

Pending-Confirmations koennen ueber editor.pending_confirmations abgefragt werden — nuetzlich wenn Ihr Client die id verliert.


Fehler-Klassen (FORGE_ERR_*)

Die wichtigsten:

CodeBedeutung
FORGE_ERR_NO_PROJECTKein Projekt geoeffnet
FORGE_ERR_NOT_FOUNDPOU/Variable/Topic existiert nicht
FORGE_ERR_ALREADY_EXISTSDoppelter Name
FORGE_ERR_INVALID_INPUTPflichtfeld fehlt oder Format falsch
FORGE_ERR_PERMISSION_DENIEDWrite-Tool in Default-Build, oder mTLS-Cert nicht in peers.toml
FORGE_ERR_CONFIRMATION_REQUIREDState-Machine wartet auf editor.confirm
FORGE_ERR_USER_CANCELEDOperator hat “cancel” gewaehlt
FORGE_ERR_IN_PROGRESSAsync-Operation (z.B. deploy) laeuft schon
FORGE_ERR_TIMEOUTWait-Limit ueberschritten (z.B. Oszi-Trigger)
FORGE_ERR_BRIDGE_INVOKE_FAILEDInterner Bug — bitte als Bug melden

Jeder Error hat typischerweise ein remediation.next_steps-Feld mit konkreten Vorschlaegen — werten Sie das in Ihrem Client aus und zeigen Sie es dem Nutzer.


Beispiel: end-to-end Knight-Rider mit curl

TOKEN="..."
URL="https://forgeiec-ws.local:7531/mcp/v1/rpc"
JQ_RESULT='.result.content[0].text|fromjson'

call() {
  curl -sk -X POST "$URL" \
       -H "Authorization: Bearer $TOKEN" \
       -H "Content-Type: application/json" \
       -d "$1" | jq -r "$JQ_RESULT"
}

# 1) Projekt-Identitaet
call '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"project.summary","arguments":{}}}'

# 2) Variable anlegen (returns FORGE_ERR_CONFIRMATION_REQUIRED)
call '{"jsonrpc":"2.0","id":2,"method":"tools/call",
       "params":{"name":"project.write.add_variable",
                 "arguments":{"name":"LED_00","iecType":"BOOL",
                              "scope_kind":"bellows",
                              "scope_name":"Bellows",
                              "address":"%MX0.0"}}}'
# → extrahieren Sie confirmation.id aus der Response

# 3) Bestaetigen
call '{"jsonrpc":"2.0","id":3,"method":"tools/call",
       "params":{"name":"editor.confirm",
                 "arguments":{"id":"<id-aus-2>","choice":"yes"}}}'

SSE-Stream fuer Live-Werte

monitor.subscribe registriert einen Watch + returnt eine stream_id. Der eigentliche Wert-Push laeuft ueber den SSE- Endpoint /mcp/v1/events:

curl -sk -N -H "Authorization: Bearer $TOKEN" \
     "https://forgeiec-ws.local:7531/mcp/v1/events?stream_id=<id>"

Format: standard-konformer SSE, jede data:-Zeile ist ein JSON- Update mit {address, value, ts_us, forced}.

Stoppen via monitor.unsubscribe(stream_id).


Eigene Tools dazu schreiben?

Aktuell: Das Tool-Set von ForgeIEC Studio ist hartkodiert — es gibt keine Plug-in-API fuer User-defined Tools im Server- Prozess. Wenn Sie eine Aktion brauchen die noch fehlt:

  • Schreiben Sie ein Issue mit Use-Case
  • Fork + Pull-Request ist explizit willkommen — die Tool- Registrierung ist in editor/src/runtime/FMcpServer.cpp an einer Stelle pro Familie (z.B. registerProjectExtraTools)
  • Alternativ ein zweiter MCP-Server der ForgeIEC’s MCP nutzt und seine eigene Tool-Liste anbietet (Aggregator-Pattern)

Eine echte Plug-in-API ist auf der Roadmap, hat aber noch keinen Sprint.


Weiter