Funktionsweise

Wie der MCP-Server technisch aufgebaut ist: Endpunkt, Transport, Authentifizierung, interner Aufbau und eine bekannte Einschränkung.

Endpunkt

FunctionMcp (DataBridge/Functions/McpApi.cs)
RoutePOST /api/mcp (JSON-RPC-Austausch); GET /api/mcp liefert bewusst 405 — siehe Bekannte Einschränkung
Auth-LevelFunction (Function Key als ?code=-Query-Parameter)
ProtokollMCP über Streamable HTTP, stateless — jede POST-Anfrage ist ein eigenständiger JSON-RPC-Austausch, es gibt keine langlebige Server-Session

Der Server ist damit direkt an einer laufenden Function App (lokal oder in Azure) ansprechbar, ohne eigenen Prozess oder zusätzliche Infrastruktur. Da die Authentifizierung über den normalen Azure-Functions-Mechanismus läuft (Function Key), lässt sich der Server ohne zusätzliche Identity-Provider-Konfiguration einrichten — der Key kann als Query-Parameter oder als Header übergeben werden, je nachdem, was der jeweilige Client unterstützt (siehe Nutzung).


Interner Aufbau

Der Mcp-Function-Trigger baut pro HTTP-Anfrage einen eigenen StreamableHttpServerTransport auf und delegiert die eigentliche Tool-Logik an den IMcpToolService (DataBridge.Core/Services/Mcp/), der wiederum dieselben Service-Interfaces (IJobService, IMappingService, IServiceBusService, IConnectionService) aufruft wie die klassischen HTTP-Funktionen — es gibt keine internen Selbstaufrufe zwischen den Functions. McpApi.cs bleibt dadurch auf die reine Protokoll-Anbindung beschränkt (Tool-Registrierung, Transport), analog zum dünnen Zuschnitt von JobApi/MappingApi. Die eigentliche Tool-Logik (Init-Guard, Job-/Mapping-Lesezugriff, Service-Bus-Delegation, Connector-Auflösung) liegt in IMcpToolService, testbar unabhängig vom Protokoll-Layer. Details zur Service-Schicht: Architektur.

Die [Description]-Attribute und Standardwerte für die Tool-Parameter liegen bewusst auf den Methoden von IMcpToolService selbst (reines System.ComponentModel, keine Abhängigkeit von ModelContextProtocol in DataBridge.Core) — McpApi.cs bindet die Tools direkt auf diese Service-Methoden, ohne zusätzliche Wrapper-Methoden.


Bekannte Einschränkung: GET auf /api/mcp

Manche MCP-Clients (typischerweise Remote-Clients, die den Endpunkt über eine echte Azure-Deployment-URL statt lokal ansprechen) versuchen nach dem initialize-POST zusätzlich einen GET auf denselben Endpunkt, um einen optionalen Server-zu-Client-SSE-Stream zu öffnen (Teil der Streamable-HTTP-Spezifikation).

Da dieser Server stateless ist (keine Session, kein Server-Push), unterstützt er diesen Stream bewusst nicht. Die Route ist deshalb zusätzlich zum POST-Handler mit einem eigenen GET-Handler registriert, der spezifikationskonform mit 405 Method Not Allowed (statt einem nicht aussagekräftigen, von Azure Functions automatisch erzeugten 404) antwortet:

[Function("McpGet")]
public IActionResult HandleMcpGetRequest(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = "mcp")] HttpRequest req)
{
    req.HttpContext.Response.Headers.Append("Allow", "POST");
    return new StatusCodeResult(StatusCodes.Status405MethodNotAllowed);
}

Manche Clients interpretieren 405 als „kein SSE-Support, aber Server ist erreichbar" und fallen automatisch auf reines POST zurück; ein 404 liest sich dagegen wie „Endpunkt existiert nicht" und lässt die Verbindung fehlschlagen. Ohne diesen Handler tritt das Problem nur bei Remote-/Azure-Deployments zuverlässig auf — lokal (Claude Code über .mcp.json) sendet der Client i. d. R. keinen GET-Probe-Request, daher blieb es dort unbemerkt.