Das Update der vorhandenen Version ging leider nicht. Deshalb war eine neu Installation von Eclipse nötig.

Was es so neues gibt, ist hier bei Heise beschrieben.
Dann mal ein Java Programm für die Demo von MCP geschrieben, um die Client – Serververbindung per MCP zu testen.
Die Anwendung verdeutlicht das zentrale Prinzip von MCP:
Eine KI-Anwendung kann über ein standardisiertes Protokoll auf externe Werkzeuge und Datenquellen zugreifen, ohne dass die jeweilige Funktionalität direkt in der KI-Anwendung implementiert sein muss.
Zum Testen der Client-Server-Kommunikation wurde ein kleines Java-Programm erstellt. Die Demo kommt ohne zusätzliche Bibliotheken aus und verwendet ausschließlich Standardklassen aus dem JDK. Voraussetzung ist Java 21, da im Programm virtuelle Threads verwendet werden.
Das Beispiel besteht aus zwei Komponenten:
-einem einfachen MCP-Server, der auf TCP-Port 8080 auf eingehende Verbindungen wartet,
-einer Swing-Oberfläche, die als MCP-Client beziehungsweise Host dient.
Die Kommunikation orientiert sich dabei an JSON-RPC 2.0. Der Client kann zunächst die verfügbaren Werkzeuge abfragen und anschließend ein Werkzeug mit einem Textargument aufrufen.
Was zeigt die Anwendung?
Die Demo bildet die wesentlichen Schritte einer MCP-Kommunikation vereinfacht nach:
1. Der Server wird gestartet und wartet auf TCP-Verbindungen.
2. Der Client verbindet sich mit localhost:8080 .
3. Mit tools/list fragt der Client die verfügbaren Werkzeuge ab.
4. Der Server meldet das Werkzeug string_transformer .
5. Mit tools/call kann der Client dieses Werkzeug aufrufen.
6. Der Server verarbeitet den übergebenen Text und gibt ihn in Großbuchstaben zurück.
Das registrierte Werkzeug ist bewusst einfach gehalten. Es konvertiert den übergebenen Text in Großbuchstaben. Dadurch lässt sich der Nachrichtenaustausch leicht nachvollziehen, ohne dass die eigentliche Funktionalität durch komplexe Geschäftslogik überlagert wird.
Um mal zu zeigen, wie die KI per MCP auf Server zugreift:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
package de.wenzlaff.mcp; import java.awt.BorderLayout; import java.awt.Color; import java.awt.FlowLayout; import java.awt.Font; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingUtilities; /** * Didaktische MCP-Demonstration (Zero-Dependencies). * * * Zeigt JSON-RPC 2.0 Nachrichtenaustausch, Capability Discovery und Tool * Execution. * * @author Thomas Wenzlaff */ public class SimpleMcpDemo { private static final int PORT = 8080; public static void main(String[] args) { // 1. MCP Server via Java 21 Virtual Thread starten startMcpServer(); // 2. Swing GUI auf dem Event Dispatch Thread (EDT) initialisieren SwingUtilities.invokeLater(McpClientGui::new); } // ========================================================================= // MCP SERVER (Simuliert eine KI-Werkzeug-Schnittstelle) // ========================================================================= private static void startMcpServer() { Thread.ofVirtual().start(() -> { try (ServerSocket serverSocket = new ServerSocket(PORT)) { System.out.println("[MCP-Server] Wartet auf eingehende Verbindungen auf Port " + PORT); while (true) { Socket clientSocket = serverSocket.accept(); // Pro Client-Verbindung ein leichtgewichtiger Virtual Thread Thread.ofVirtual().start(() -> handleMcpClient(clientSocket)); } } catch (IOException e) { System.err.println("[MCP-Server Fehler] " + e.getMessage()); } }); } private static void handleMcpClient(Socket socket) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter writer = new PrintWriter(socket.getOutputStream(), true)) { String rawJsonRpc; while ((rawJsonRpc = reader.readLine()) != null) { String response = processMcpProtocolRequest(rawJsonRpc); writer.println(response); } } catch (IOException e) { System.out.println("[MCP-Server] Client-Sitzung beendet."); } } // Nachrichten-Dispatcher nach MCP / JSON-RPC 2.0 Spezifikation private static String processMcpProtocolRequest(String jsonRequest) { // Primitive Capability Discovery: Client fragt verfügbare Tools ab if (jsonRequest.contains("\"method\":\"tools/list\"")) { return """ {"jsonrpc":"2.0","id":1,"result":{"tools":[{"name":"string_transformer","description":"Konvertiert Eingabetext in Großbuchstaben"}]}} """ .strip(); } // Primitive Tool Execution: Ausführen der registrierten Funktion if (jsonRequest.contains("\"method\":\"tools/call\"")) { String payload = jsonRequest.contains("message") ? jsonRequest.replaceAll(".*\"message\":\"([^\"]+)\".*", "$1") : "Standard-Payload"; String resultText = payload.toUpperCase(); return """ {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"Server-Transformation: %s"}]}} """.formatted(resultText).strip(); } // Fallback: JSON-RPC Standardfehler "Method not found" (-32601) return "{\"jsonrpc\":\"2.0\",\"id\":null,\"error\":{\"code\":-32601,\"message\":\"Method not found\"}}"; } // ========================================================================= // MCP CLIENT / HOST (Swing GUI) // ========================================================================= static class McpClientGui extends JFrame { private static final long serialVersionUID = 1L; private final JTextArea consoleLog = new JTextArea(16, 200); private final JTextField inputPayload = new JTextField("quick eclipse update check mit mcp", 100); private PrintWriter outStream; private BufferedReader inStream; public McpClientGui() { super("MCP Host - Swing Inspector"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new BorderLayout(5, 5)); consoleLog.setEditable(false); consoleLog.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); consoleLog.setBackground(new Color(30, 30, 30)); consoleLog.setForeground(new Color(220, 220, 220)); JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); JButton btnListTools = new JButton("1. tools/list"); JButton btnCallTool = new JButton("2. tools/call"); controlPanel.add(new JLabel("Argument:")); controlPanel.add(inputPayload); controlPanel.add(btnListTools); controlPanel.add(btnCallTool); add(controlPanel, BorderLayout.NORTH); add(new JScrollPane(consoleLog), BorderLayout.CENTER); pack(); setLocationRelativeTo(null); setVisible(true); initNetworkConnection(); // Event-Handling: MCP Abfragen generieren btnListTools.addActionListener(e -> { String request = """ {"jsonrpc":"2.0","id":1,"method":"tools/list"} """; transmitMcpFrame(request); }); btnCallTool.addActionListener(e -> { String arg = inputPayload.getText(); String request = """ {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"string_transformer","arguments":{"message":"%s"}}} """ .formatted(arg); transmitMcpFrame(request); }); } private void initNetworkConnection() { try { Socket socket = new Socket("localhost", PORT); outStream = new PrintWriter(socket.getOutputStream(), true); inStream = new BufferedReader(new InputStreamReader(socket.getInputStream())); appendLog("[SYSTEM] TCP-Verbindung zu MCP-Server etabliert (Port " + PORT + ")\n"); } catch (IOException e) { appendLog("[FEHLER] Serververbindung fehlgeschlagen: " + e.getMessage()); } } private void transmitMcpFrame(String jsonFrame) { String singleLineJson = jsonFrame.replaceAll("\\s+", " ").trim(); appendLog(">>> REQUEST (TX):\n" + singleLineJson); outStream.println(singleLineJson); try { String response = inStream.readLine(); appendLog("<<< RESPONSE (RX):\n" + response + "\n"); } catch (IOException e) { appendLog("[FEHLER] I/O-Fehler beim Empfang: " + e.getMessage()); } } private void appendLog(String message) { consoleLog.append(message + "\n"); consoleLog.setCaretPosition(consoleLog.getDocument().getLength()); } } } |
Nach dem start, erscheint das obige Programmfenster wo die Funktionen getestet werden können.
Das einfache Werkzeug zur Textumwandlung kann später problemlos durch realistischere Funktionen ersetzt werden, beispielsweise durch:
-das Auslesen eines Systemstatus,
-die Abfrage von Sensordaten,
-den Zugriff auf eine Datenbank,
-die Suche in Dokumenten,
-die Ausführung definierter Linux-Kommandos,
-oder den Zugriff auf eine eigene REST- beziehungsweise MQTT-Anwendung.
Damit bildet die Demo eine gute Grundlage für weitere Experimente mit Java, MCP, JSON-RPC, virtuellen Threads und selbst entwickelten Serverwerkzeugen.
Hier noch eine Visualisierung der Funktionsweise:

