Created
April 2, 2025 20:39
-
-
Save glaforge/e1b75653aaeb4742a7fe74dead3ee52f to your computer and use it in GitHub Desktop.
Raw MCP client / server example with the MCP JAVA SDK and LangChain4j's MCP client module
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import dev.langchain4j.agent.tool.ToolExecutionRequest; | |
import dev.langchain4j.mcp.McpToolProvider; | |
import dev.langchain4j.mcp.client.DefaultMcpClient; | |
import dev.langchain4j.mcp.client.McpClient; | |
import dev.langchain4j.mcp.client.transport.McpTransport; | |
import dev.langchain4j.mcp.client.transport.http.HttpMcpTransport; | |
import dev.langchain4j.model.vertexai.VertexAiGeminiChatModel; | |
import dev.langchain4j.service.AiServices; | |
import dev.langchain4j.service.SystemMessage; | |
import dev.langchain4j.service.tool.ToolProvider; | |
import java.io.IOException; | |
import java.util.List; | |
import static ai.patterns.utils.Ansi.blue; | |
import static ai.patterns.utils.Ansi.green; | |
public class CustomMcpClient { | |
public static void main(String[] args) throws IOException { | |
try ( | |
VertexAiGeminiChatModel model = VertexAiGeminiChatModel.builder() | |
.project("genai-playground24") | |
.location("us-central1") | |
.modelName("gemini-2.0-flash-001") | |
.build(); | |
McpTransport transport = new HttpMcpTransport.Builder() | |
.sseUrl("http://0.0.0.0:45450/sse") | |
.logRequests(true) | |
.logResponses(true) | |
.build()) { | |
McpClient mcpClient = new DefaultMcpClient.Builder() | |
.transport(transport) | |
.build(); | |
ToolProvider toolProvider = McpToolProvider.builder() | |
.mcpClients(List.of(mcpClient)) | |
.build(); | |
System.out.println(blue("LIST TOOLS")); | |
mcpClient.listTools().forEach(System.out::println); | |
record WeatherForecast(String location, String forecast) {} | |
interface WeatherAssistant { | |
@SystemMessage(""" | |
If the user asks about the weather forecast for a particular location, | |
use the `weather-forecast` tool. | |
Otherwise, respond with your internal knowledge. | |
""") | |
WeatherForecast request(String message); | |
} | |
WeatherAssistant meteo = AiServices.builder(WeatherAssistant.class) | |
.chatLanguageModel(model) | |
.toolProvider(toolProvider) | |
.build(); | |
System.out.println(blue("WEATHER")); | |
var response = meteo.request("What is the weather in Paris?"); | |
System.out.println(green(response.toString())); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.fasterxml.jackson.databind.ObjectMapper; | |
import io.modelcontextprotocol.server.McpServer; | |
import io.modelcontextprotocol.server.McpServerFeatures; | |
import io.modelcontextprotocol.server.McpSyncServer; | |
import io.modelcontextprotocol.server.transport.HttpServletSseServerTransportProvider; | |
import io.modelcontextprotocol.spec.McpSchema; | |
import org.eclipse.jetty.ee10.servlet.ServletContextHandler; | |
import org.eclipse.jetty.ee10.servlet.ServletHolder; | |
import org.eclipse.jetty.server.Server; | |
import org.eclipse.jetty.server.ServerConnector; | |
import org.eclipse.jetty.util.thread.QueuedThreadPool; | |
import java.util.Map; | |
import java.util.List; | |
import static ai.patterns.utils.Ansi.blue; | |
public class CustomMcpServer { | |
public static void main(String[] args) throws Exception { | |
HttpServletSseServerTransportProvider transportProvider = | |
new HttpServletSseServerTransportProvider(new ObjectMapper(), "/", "/sse"); | |
McpSyncServer syncServer = McpServer.sync(transportProvider) | |
.serverInfo("custom-server", "0.0.1") | |
.capabilities(McpSchema.ServerCapabilities.builder() | |
.tools(true) | |
.resources(false, false) | |
.prompts(false) | |
.build()) | |
.build(); | |
McpServerFeatures.SyncToolSpecification syncToolSpecification = | |
new McpServerFeatures.SyncToolSpecification( | |
new McpSchema.Tool("weather-forecast", "gives today's weather forecast for a given location", | |
new McpSchema.JsonSchema("object", Map.of( | |
"location", new McpSchema.JsonSchema("string", null, null, false), | |
"forecast", new McpSchema.JsonSchema("string", null, null, false) | |
), List.of("location", "forecast"), false) | |
/* | |
""" | |
{ | |
"type": "object", | |
"properties": { | |
"location": { | |
"type": "string" | |
}, | |
"forecast": { | |
"type": "string" | |
} | |
}, | |
"required": ["location", "forecast"] | |
} | |
""" | |
*/ | |
), | |
(mcpSyncServerExchange, stringObjectMap) -> { | |
System.out.println(blue("Incoming request: ") + stringObjectMap); | |
return new McpSchema.CallToolResult(List.of(new McpSchema.TextContent(""" | |
{"location": "Paris", "forecast": "sunny"} | |
""" | |
)), false); | |
} | |
); | |
syncServer.addTool(syncToolSpecification); | |
QueuedThreadPool threadPool = new QueuedThreadPool(); | |
threadPool.setName("server"); | |
Server server = new Server(threadPool); | |
ServerConnector connector = new ServerConnector(server); | |
connector.setPort(45450); | |
server.addConnector(connector); | |
ServletContextHandler context = new ServletContextHandler(); | |
context.setContextPath("/"); | |
context.addServlet(new ServletHolder(transportProvider), "/*"); | |
server.setHandler(context); | |
server.start(); | |
// syncServer.close(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment