In modernen KI-Anwendungen ist die effiziente Kommunikation zwischen Modellen und Anwendungen ein entscheidender Faktor. Entwicklerinnen und Entwickler stoßen dabei oft auf Probleme bei der Integration unterschiedlicher Tools und Technologien, insbesondere wenn es darum geht, Kontextinformationen zuverlässig und flexibel auszutauschen. Das Model Context Protocol (MCP) [1] schafft hier Abhilfe, indem es eine einheitliche und sprachunabhängige Schnittstelle definiert, über die Anwendungen Kontextinformationen an KI-Modelle liefern und deren Antworten empfangen können.
Ursprünglich von Anthropic entwickelt [2], orientiert sich MCP an Konzepten des Language Server Protocols (LSP) und bietet damit eine vergleichbar universelle und flexible Basis für KI-basierte Systeme. MCP-Server lassen sich dabei vielfältig betreiben: als OCI-Container (aus dem Katalog von Docker [3]), als WebAssembly-Modul (z. B. via mcp.run) oder als gewöhnliche Anwendung, die in einer beliebigen Programmiersprache implementiert ist.
Spring AI [4], das kürzlich das MCP integriert hat, bietet Entwicklerinnen und Entwicklern nun auf Java-Basis eine komfortable Möglichkeit, MCP-Server direkt in Spring-Boot-Anwendungen zu konsumieren und eigene MCP-Server zu implementieren.
Technische Grundlagen des MCP
Das Model Context Protocol soll eine einheitliche, klar definierte Schnittstelle für die Kommunikation zwischen Anwendungen und KI-Modellen schaffen. MCP folgt dabei einer Client-Server-Architektur, ähnlich dem Language Server Protocol (LSP), das sich bereits als Standard in Entwicklungsumgebungen etabliert hat. Dabei definiert das MCP eine klare Rollenverteilung zwischen Client und Server:
- MCP-Server: Verarbeitet eingehende Anfragen und liefert Kontextinformationen oder Ergebnisse zurück. Typische Aufgaben eines MCP-Servers sind beispielsweise das Bereitstellen von Daten aus Datenbanken, Dateisystemen, Ticketing-Systemen oder externen KI-Modellen.
- MCP-Client: Stellt Anfragen an den MCP-Server und verarbeitet die Antworten. Beispiele für MCP-Clients sind Entwicklungsumgebungen, Webapplikationen oder andere KI-Tools, die Kontextinformationen zur Bearbeitung von Aufgaben benötigen.
Zur Kommunikation zwischen Client und Server unterstützt MCP mehrere Transporttypen (Abb. 1). Für die Kommunikation mit lokalen Prozessen und Kommandozeilentools bietet MCP den Transporttyp Standard Input/Output (stdio) an, der Anfragen und Antworten über die standardisierten Ein- und Ausgabeströme (stdin/stdout) austauscht. Alternativ steht für HTTP-basierte Kommunikation der Transporttyp Server-sent Events (SSE) zur Verfügung, mit dem sich MCP-Clients und -Server auch über das Netzwerk miteinander verbinden können.
MCP verwendet ein standardisiertes, in der Regel auf JSON-RPC basierendes Protokollformat. Dadurch wird die Entwicklung neuer MCP-Clients und -Server vereinfacht und gleichzeitig eine breite Kompatibilität mit unterschiedlichen Systemen sichergestellt.
Abb.1: MCP-Client- und -Serveraufbau
Flexibles Deployment von MCP-Servern
Ein großer Vorteil des Model Context Protocol liegt in der Flexibilität bei den Betriebsformen von MCP-Servern. Entwicklerinnen und Entwickler können MCP optimal in bestehende Systemlandschaften integrieren und dabei genau jene Technologien verwenden, die ihren Anforderungen entsprechen. Auch lassen sich bestehende Softwaresysteme über einen MCP-Server für KI-Anwendungen verfügbar machen.
Sie lassen sich sowohl lokal als Kommandozeilenanwendungen als auch remote über HTTP einsetzen. Durch die standardisierten Schnittstellen lassen sich MCP-Server nahtlos, wie oft in Demos gezeigt, in Entwicklungsumgebungen wie Visual Studio Code oder IntelliJ IDEA sowie in Applikationsframeworks wie Spring Boot mit Spring AI integrieren. MCP-Server können situationsabhängig als sogenannte Content Retriever eingesetzt werden, um KI-Modelle mit den jeweils benötigten Kontextdaten zu versorgen.
Integration von MCP in Spring AI
Das MCP Java SDK [5] bietet eine vollständige Implementierung des Model Context Protocol für Java. Es ermöglicht die standardisierte Kommunikation zwischen KI-Modellen und externen Tools und unterstützt dabei sowohl synchrone als auch asynchrone Kommunikationsmuster. Entwicklerinnen und Entwickler können mit dem SDK eigene MCP-Clients und -Server erstellen.
Spring AI MCP erweitert das MCP Java SDK um eine enge Integration mit dem Spring-Ökosystem. Mit den bereitgestellten Startern für Spring Boot lassen sich sowohl MCP-Clients als auch -Server einfach und effizient entwickeln. Das erleichtert die Anbindung bestehender Tools an KI-Modelle und die Bereitstellung eigener Kontextquellen im Rahmen von KI-Anwendungen.
Über den Spring Initializer können Projekte schnell mit der benötigten Spring-AI-MCP-Unterstützung konfiguriert werden. Entwicklerinnen und Entwickler profitieren dabei von den gewohnten Mechanismen von Spring Boot wie der automatischen Konfiguration und dem einfachen Management von Verbindungen und Services.
Integration eines Node-basierten MCP-Servers in Spring AI
Spring AI unterstützt auch die Einbindung externer MCP-Server, die in anderen Sprachen implementiert sind – etwa mit Node.js. In diesem Beispiel wird ein MCP-Server zur Wetterabfrage (@h1deya/mcp-server-weather) über stdio in eine Spring-Boot-Anwendung integriert und über einen Chatendpunkt angesprochen.
Damit die Anwendung mit MCP-Servern kommunizieren und OpenAI-Modelle ansteuern kann, werden zwei Abhängigkeiten benötigt (Listing 1):
- spring-ai-starter-mcp-client: Ermöglicht die Kommunikation mit MCP-Servern über das MCP Java SDK.
- spring-ai-starter-model-openai: Bindet OpenAI-Modelle wie GPT-4o-mini in die Spring-AI-Infrastruktur ein.
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-mcp-client</artifactId> </dependency> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-openai</artifactId> </dependency>
Die application.yaml (Listing 2) konfiguriert die Verbindung zu einem lokalen, Node-basierten MCP-Server, der automatisch über npx gestartet wird: command: npx und args: -y,@h1deya/mcp-server-weather [6] startet den MCP-Server direkt aus dem Java-Prozess mit dem Node.js-Modul.
Diese Konfiguration sorgt dafür, dass der MCP-Server beim Start der Anwendung automatisch bereitgestellt wird und über stdio ansprechbar ist. Mit dem dazugehörigen Java API kann man den MCP-Client auch programmatisch konfigurieren und verwenden.
spring: application: name: mcp-client-weather ai: openai: api-key: ${OPENAI_API_KEY} chat: options: model: gpt-4o-mini mcp: client: stdio: connections: weather: command: npx args: -y,@h1deya/mcp-server-weather
Der WeatherController (Listing 3) implementiert einen REST-Endpunkt, der Benutzeranfragen entgegennimmt und über Spring AI verarbeitet:
- Im Konstruktor wird ein ChatClient aufgebaut, der standardmäßig auf Wetterfragen spezialisiert ist.
- Über defaultTools wird der externe MCP-Server als Tool (MCP-Client) angebunden.
- Der /ask-Endpunkt nimmt eine Frage entgegen und gibt eine KI-generierte Antwort zurück, die gegebenenfalls durch den MCP-Server ergänzt wird.
Dieses Set-up verbindet das generische Sprachmodell von OpenAI mit der domänenspezifischen Intelligenz eines MCP-gestützten Wetterdienstes, flexibel erweiterbar durch weitere Tools.
@RestController public class WeatherController { private final ChatClient chatClient; public WeatherController( ChatClient.Builder chatClientBuilder, List<McpSyncClient> mcpSyncClients) { this.chatClient = chatClientBuilder .defaultSystem("You are a weather assistant ...") .defaultTools(new SyncMcpToolCallbackProvider(mcpSyncClients)) .build(); } @PostMapping("/ask") public Answer ask(@RequestBody Question question) { return chatClient.prompt() .user(question.question()) .call() .entity(Answer.class); } }
Aufbau eines eigenen MCP-Servers mit Spring Boot
Neben dem Konsumieren externer MCP-Server ermöglicht Spring AI auch die Entwicklung eigener MCP-Server auf Basis von Spring Boot. In diesem Beispiel wird ein einfacher Wetterdienst aufgebaut, der Wetterdaten über das API des Deutschen Wetterdienstes (DWD) bereitstellt. Für die Entwicklung eines MCP-Servers wird die folgende Maven-Abhängigkeit benötigt:
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId> </dependency>
Sie stellt die notwendigen Komponenten bereit, um Anfragen gemäß dem Model Context Protocol über HTTP (SSE) zu empfangen und zu verarbeiten.
Die Konfiguration des MCP-Servers erfolgt über die application.yaml (Listing 4), wobei name und version die Metadaten des Servers definieren, die bei der Kommunikation über MCP übertragen werden.
spring: ai: mcp: server: name: dwd-weather-server version: 0.0.1
Die folgende Konfigurationsklasse (Listing 5) registriert die angebotenen Tools:
- Die Methode weatherTools registriert den WeatherService als Sammlung von Tools, die über MCP aufrufbar sind.
- Zusätzlich wird mit toUpperCase ein einfaches Tool definiert, das Texte in Großbuchstaben umwandelt – ein Beispiel für generische Funktionalität.
@Bean ToolCallbackProvider weatherTools(WeatherService weatherService) { return MethodToolCallbackProvider.builder() .toolObjects(weatherService) .build(); } @Bean ToolCallback toUpperCase() { return FunctionToolCallback.builder("toUpperCase", (TextInput input) -> input.input().toUpperCase()) .inputType(TextInput.class) .description("Put the text to upper case.") .build(); }
Die eigentliche Logik wird im WeatherService bereitgestellt (Listing 6). Beide Methoden sind mit der Annotation @Tool versehen, was sie automatisch für die Kommunikation über MCP verfügbar macht. Eingabeparameter werden mittels @ToolParam beschrieben, um eine präzisere semantische Beschreibung gegenüber KI-Modellen zu ermöglichen.
@Service public class WeatherService { @Tool(description = "Find and retrieve the station_id for weather stations") public String getStationIds(@ToolParam( description = "Station is typically just city") String station){ // business logic return stationId; } @Tool(description = "Retrieve current and forecast weather information.") public String getStationOverview(@ToolParam( description = "List of station ids to resolve weather forecast.") List<String> stationIds){ // business logic return stationOverview; } }
Der erstellte MCP-Server stellt die registrierten Tools standardmäßig über SSE auf dem HTTP-Port 8080 (Standardport von Spring Boot) bereit. Eingehende Anfragen erfolgen gemäß dem MCP, wobei sowohl Anfragen als auch Antworten im definierten JSON-Format ausgetauscht werden.
Mit Hilfe eines beliebigen MCP-Clients, der SSE unterstützt, können nun die angebotenen Tools konsumiert werden. Durch die Verwendung von SSE ermöglicht der MCP-Server eine effiziente, bidirektionale Kommunikation mit KI-Modellen und anderen Anwendungen, unabhängig von deren Implementierungssprache oder Umgebung.
Anreicherung des Prompts
Mit der Bereitstellung spezialisierter Tools über einen eigenen MCP-Server lässt sich das Model Context Protocol gezielt zur Anreicherung von Prompts einsetzen. In vielen KI-Anwendungen reicht es nicht aus, dem Modell nur die eigentliche Benutzeranfrage zu übergeben. Die Qualität und Relevanz der Antworten verbessern sich deutlich, wenn zusätzliche Kontextinformationen bereitgestellt werden. Diese Technik wird als „Prompt Stuffing“ oder „Anreicherung des Prompts“ bezeichnet. Besonders wichtig ist das bei Echtzeitdaten oder privaten Daten. Tools, die als MCP-Server eingebunden sind, können Informationen aus externen Systemen liefern, um das Modell bei der Beantwortung zu unterstützen.
Wie bereits im vorherigen Abschnitt gezeigt, helfen Spring AI und Spring Boot dabei, die Konfiguration der Clients bzw. der Server zu vereinfachen. Ein typisches Beispiel ist der zuvor vorgestellte Wetterdienst. Hier wird das Sprachmodell vor der Antwortgenerierung mit aktuellen Wetterdaten ergänzt. Spring AI nutzt dafür das Konzept der Tools im ChatClient. Tools können lokal definierte Services oder externe MCP-Server sein.
Beim Erstellen eines Prompts ruft der ChatClient zuerst die definierten Tools auf und reichert den Benutzerinput mit den Ergebnissen an. Erst danach wird der vollständige, angereicherte Prompt an das KI-Modell übergeben.
Beispielhafter Ablauf
Ein typischer Ablauf stellt sich wie folgt dar:
- Benutzerfrage: „Wie wird das Wetter morgen in Kempten?“
- LLM: Das Modell selektiert die MCP-Schnittstellen, um die Daten zu beschaffen.
- Tool-Aufruf: Der MCP-Server liefert aktuelle Wetterdaten für Kempten.
- Anreicherung: Die Wetterdaten werden zusammen mit der ursprünglichen Frage in den Prompt integriert.
- Antwortgenerierung: Das KI-Modell erzeugt eine fundierte Antwort auf Basis des angereicherten Prompts. Das könnte auch wieder ein Sprung zu Schritt 2 sein.
Spring AI bietet über seine Logging-Funktionalität Einblicke in diesen Prozess. In den Logs lässt sich nachvollziehen, wie der ursprüngliche Benutzerinput durch die Ergebnisse der Tools ergänzt wurde (Listing 7).
2025-05-12T10:47:05.303+02:00 DEBUG 3175 --- [mcp-client-weather-sse] [nio-8081-exec-2] o.s.web.client.DefaultRestClient : Writing [ChatCompletionRequest[messages=[ChatCompletionMessage[rawContent=Wie ist die Wettervorhersage für Kempten für morgen?, role=USER, name=null, toolCallId=null, toolCalls=null, refusal=null, audioOutput=null], ChatCompletionMessage[rawContent=Du bist ein Assistent für die Analyse von Wetterdaten. Du erhältst strukturierte Vorhersagedaten von verschiedenen Wetterstationen. Dateneinheiten: - Temperatur in 0,1 °C - Startzeit Unixzeit (ms) - Zeitintervall (ms) - Niederschlag gesamt in 0,1 mm/h - Niederschlag pro Tag in 0,1 mm/d - Sonnenschein in 0,1 min - Luftfeuchtigkeit in 0,1 % - Taupunkt in 0,1 °C (2 m Höhe) - Luftdruck in 0,1 hPa (Bodenhöhe) Anweisungen: - Wandle alle Werte in lesbare Einheiten um. - Erkenne und beschreibe Trends. - Kommentiere fehlende Werte (null). - Fasse Temperatur, Niederschlag, Sonnenschein, Feuchtigkeit, Taupunkt, Wind (falls vorhanden) und Luftdruck separat zusammen. - Erstelle am Schluss eine kurze Wetterzusammenfassung (Wetterlage, Temperaturverlauf, Komfort, besondere Ereignisse). Formuliere deine Antworten klar, schrittweise und in vollständigen Sätzen. Halte sie freundlich, präzise und aufschlussreich. , role=SYSTEM, name=null, toolCallId=null, toolCalls=null, refusal=null, audioOutput=null], ChatCompletionMessage[rawContent=Wie ist die Wettervorhersage für Kempten für morgen? Your response should be in JSON format. Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation. Do not include markdown code blocks in your response. Remove the ```json markdown from the output. Here is the JSON Schema instance your output must adhere to: ```{ "$schema" : "https://json-schema.org/draft/2020-12/schema", "type" : "object", "properties" : { "answer" : { "type" : "string" } }, "additionalProperties" : false }``` , role=USER, name=null, toolCallId=null, toolCalls=null, refusal=null, audioOutput=null], ChatCompletionMessage[rawContent=null, role=ASSISTANT, name=null, toolCallId=null, toolCalls=[ToolCall[index=null, id=call_4ggmsbY1Kg3WwopK6JEtlldc, type=function, function=ChatCompletionFunction[name=spring_ai_mcp_client_weather_getStationIds, arguments={"station":"Kempten"}]]], refusal=null, audioOutput=null], ChatCompletionMessage[rawContent=[{"text":"\"StationId: 02559, Stationsname: Kempten, Bundesland: Bayern\\n\""}], role=TOOL, name=spring_ai_mcp_client_weather_getStationIds, toolCallId=call_4ggmsbY1Kg3WwopK6JEtlldc, toolCalls=null, refusal=null, audioOutput=null], ChatCompletionMessage[rawContent=null, role=ASSISTANT, name=null, toolCallId=null, toolCalls=[ToolCall[index=null, id=call_3Q3csYoAzo2qPsHKFOMbFQ1L, type=function, function=ChatCompletionFunction[name=spring_ai_mcp_client_weather_getStationOverview, arguments={"stationIds":["02559"]}]]], refusal=null, audioOutput=null], ChatCompletionMessage[rawContent=[{"text":"\"StationOverview{stations={02559=StationData[forecast1=Forecast[stationId=02559, start=1747000800000, timeStep=3600000, temperature=[…, 115, 123, 133, …], windSpeed=null, windDirection=null, windGust=null, precipitationTotal=[32767, 32767, …], sunshine=[32767, 32767, 32767, 32767,…], dewPoint2m=[46, 41, 39,…], surfacePressure=[10216, 10218, 10217, …], isDay=[false, false, …], cloudCoverTotal=[], temperatureStd=[…, 12, 14, 14, 13, 12,…], icon=[32767, 32767,…], icon1h=[4, 4, …], precipitationProbablity=null, precipitationProbablityIndex=null], forecast2=Forecast[stationId=02559, start=1747260000000, timeStep=10800000, temperature=[], windSpeed=null, windDirection=null, windGust=null, precipitationTotal=[0, 0, …], sunshine=[32767, 32767, …], surfacePressure=[10145, 10145, …], isDay=[false, false,…], cloudCoverTotal=[], temperatureStd=[], icon=[…], precipitationProbablity=null, precipitationProbablityIndex=null], forecastStart=null, warnings=[], threeHourSummaries=null]}}\""}], role=TOOL, name=spring_ai_mcp_client_weather_getStationOverview, toolCallId=call_3Q3csYoAzo2qPsHKFOMbFQ1L, toolCalls=null, refusal=null, audioOutput=null]], model=gpt-4o-mini, store=null, metadata=null, frequencyPenalty=null, logitBias=null, logprobs=null, topLogprobs=null, maxTokens=null, maxCompletionTokens=null, n=null, outputModalities=null, audioParameters=null, presencePenalty=null, responseFormat=null, seed=null, serviceTier=null, stop=null, stream=false, streamOptions=null, temperature=0.7, topP=null, tools=[org.springframework.ai.openai.api.OpenAiApi$FunctionTool@372faade, org.springframework.ai.openai.api.OpenAiApi$FunctionTool@5c334418, org.springframework.ai.openai.api.OpenAiApi$FunctionTool@23b4be7c], toolChoice=null, parallelToolCalls=null, user=null, reasoningEffort=null]] as "application/json" with org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
Dieses Beispiel zeigt auch, dass manchmal der Kontext im System-Prompt definiert werden muss, damit das LLM die Daten korrekt auswerten kann. Das Erstellen solcher Prompts ist nicht immer einfach. Ein iteratives Vorgehen und die Überprüfung des Prompts mit dem LLM helfen dabei wesentlich.
Fazit und Ausblick
Das Model Context Protocol bietet einen strukturierten, sprachunabhängigen und erweiterbaren Ansatz für die Kommunikation zwischen KI-Modellen und externen Tools. Durch die klare Trennung zwischen Client und Server sowie die Unterstützung standardisierter Transportmechanismen wie stdio und SSE lässt sich MCP in unterschiedlichsten Szenarien einsetzen: von lokalen Entwicklungsumgebungen bis hin zu Cloud-basierten Anwendungen.
Mit dem MCP Java SDK und der Spring-AI-Integration steht Entwicklerinnen und Entwicklern ein leistungsfähiges, standardisiertes Werkzeug zur Verfügung, um sowohl bestehende MCP-Server zu konsumieren als auch eigene Services bereitzustellen. Die nahtlose Einbindung in Spring Boot ermöglicht eine schnelle Umsetzung, ohne auf bewährte Spring-Konzepte verzichten zu müssen.
Der gezeigte Wetterdienst illustriert, wie einfach sich domänenspezifische Funktionalität mit klaren Schnittstellen als MCP-Server implementieren lässt: Annotationen für Tool-Beschreibungen und automatische Bereitstellung über HTTP. Die im Artikel gezeigten Codebeispiele und weitere sind vollständig auf GitHub verfügbar [7].
Mit der zunehmenden Verbreitung KI-gestützter Anwendungen ist zu erwarten, dass sich MCP als standardisiertes Bindeglied zwischen Modellen und Werkzeugen etablieren wird. Perspektivisch bietet das Protokoll Potenzial für weitere Integrationen, etwa in IDEs, DevOps-Werkzeuge oder spezialisierten Businessanwendungen, sowohl lokal als auch in verteilten Systemlandschaften.
Links & Literatur
[1] Model Context Protocol: https://modelcontextprotocol.io
[2] Introduction the Model Context Protocol: https://www.anthropic.com/news/model-context-protocol
[3] Docker MCP Catalog and Toolkit: https://www.docker.com/products/mcp-catalog-and-toolkit/
[4] Spring AI: https://docs.spring.io/spring-ai/reference/api/mcp/mcp-overview.html
[5] MCP Java SDK: https://modelcontextprotocol.io/sdk/java/mcp-overview
[6] Simple Weather MCP-Server: https://github.com/hideya/mcp-server-weather-js
[7] Spring AI MCP Examples: https://github.com/patbaumgartner/spring-ai-mcp-entwickler.de