You probably heard about Model Context Protocol (MCP), which is basically a standard for connecting Tools to LLMs. It was released November 2024 and a few months later we have a good list of MCP Clients and MCP Servers.
Building MCP Server is easy with Quarkus and there are a few good servers available with one single jbang command. Check the Quarkiverse MCP Servers project!
For the client I did find myself with some difficult finding a good lightweight open MCP Client. Don't get me wrong, I know there are good alternatives, but I only use ollama locally and I don't want to fell in the multiverse of LLM Clients to find one that fits my needs. I wanted to build my own MCP Client!
In this post let's take a look at MCP Java SDK to build our own client.
MCP Java SDK
MCP provides a good modern Java SDK for building MCP applications. Quarkus and langchain4j are also a good alternative, but this time I needed something low level.
To get started with the MCP Java SDK you need a single maven dependency io.modelcontextprotocol.sdk:mcp and it comes from a BOM (Bill of Materials). All of it is well explained on the MCP Java SDK page.
The goal of this SDK is allow users to connect their Intelligent Java application to a MCP Server, so the application can let LLMs invoke the Tools for their needs.
Listing Tools available in a MCP Server
Using the SDK you can list the tools and its parameters form a given MCP Server. The Java code required to do that is minimal: you basically need to configure the connection to the server and you can programatically call the available functions.var params = ServerParameters.builder("jbang")
.args(SERVER_PARAMS)
.build();
var transport = new StdioClientTransport(params);
var client = McpClient.sync(transport).build();
client.initialize();
In our case we are using jbang command to install the server, so you must have it installed! You can use any of the server that is in Quarkus MCP Server page. There are other multiple parameters that can be used to connect to the server, explore them according to your needs!
Once the client is connected, then we can list tools:
System.out.println("Available tools:");
client.listTools()
.tools()
.stream()
.map(tool -> tool.name() + ": " + tool.description())
.forEach(System.out::println);
Running this for the jdbc@quarkiverse/quarkus-mcp-servers MCP Server we will have the following result:
Available tools:
create_table: Create new table in the jdbc database
database_info: Get information about the database. Run this before anything else to know the SQL dialect, keywords etc.
describe_table: Describe table
list_tables: List all tables in the jdbc database
read_query: Execute a SELECT query on the jdbc database
write_query: Execute a INSERT, UPDATE or DELETE query on the jdbc database
We can also list the Tool Input Schema:
client.listTools()
.tools()
.stream()
.forEach(tool -> {
System.out.println(tool.name() + "\n-");
var properties = tool.inputSchema().properties();
properties.forEach((k, v) -> {
System.out.println(k + ": " + v);
});
if(properties.isEmpty()) {
System.out.println("no params");
}
System.out.println("-----");
});
Running this will return:
create_table:
-
query: {type=string, description=CREATE TABLE SQL statement}
-----
database_info:
-
no params
-----
describe_table:
-
catalog: {type=string, description=Catalog name}
schema: {type=string, description=Schema name}
table: {type=string, description=Table name}
-----
list_tables:
-
no params
-----
read_query:
-
query: {type=string, description=SELECT SQL query to execute}
-----
write_query:
-
query: {type=string, description=INSERT, UPDATE or DELETE SQL query to execute}
-----
Now we have this information we can go ahead and invoke a function.
JDBC stands for Java Database Connectivity and it is an almost 30 years old Java API to connect to databases! The JDBC MCP server starts with an empty database in memory H2 database, so we need to create a table. This is how we do it:
var sql = """
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(100),
age INT
);
""";
var result = client.callTool(new CallToolRequest("write_query",
Map.of("query", sql))).content();
if (result.size() > 0 &&
result.get(0) instanceof TextContent content) {
System.out.println(content.text());
}
Running this code you should see the text Query executed successfully in console!
Conclusion
In this post we shared the basics of how to use Java to connect to MCP Server. Next post let's to build something useful! Check the code on my github!
Comentários
Postar um comentário