Pular para o conteúdo principal

Connecting to MCP Servers using Java

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

Postagens mais visitadas deste blog

Dancing lights with Arduino - The idea

I have been having fun with Arduino these days! In this article I am going to show how did I use an electret mic with Arduino to create a Dancing Lights circuit. Dancing Lights   I used to be an eletronician before starting the IT college. I had my own electronics maintenance office to fix television, radios, etc. In my free time I used to create electronic projects to sell and I made a few "reais" selling a version of Dancing lights, but it was too limited: it simply animated lamps using a relay in the output of a 4017 CMOS IC. The circuit was a decimal counter  controlled by a 555. 4017 decimal counter. Source in the image When I met Arduino a few years ago, I was skeptical because I said: I can do this with IC, why should I use a microcontroller. I thought that Arduino was for kids. But now my pride is gone and I am having a lot of fun with Arduino :-) The implementation of Dancing Lights with Arduino uses an electret mic to capture the sound and light leds...

Simplest JavaFX ComboBox autocomplete

Based on this Brazilian community post , I've created a sample Combobox auto complete. What it basically does is: When user type with the combobox selected, it will work on a temporary string to store the typed text; Each key typed leads to the combobox to be showed and updated If backspace is type, we update the filter Each key typed shows the combo box items, when the combobox is hidden, the filter is cleaned and the tooltip is hidden:   The class code and a sample application is below. I also added the source to my personal github , sent me PR to improve it and there are a lot of things to improve, like space and accents support.

Creating Fat JARs for JavaFX Applications

A FAT JAR is a type of Java application distribution where a single JAR contains all other dependencies, so no additional file is required to run the JAR besides the Java Virtual Machine. For any Java maven based application, creating a FAR JAR could be solved by using Maven Shade Plugin . However, creating FAT Jars using JavaFX may be a challenge because JavaFX uses modules. Fortunately this subject was intensely discussed in the WEB, and a good explanation and a solution was provided by Jose Pereda in this StackOverflow response. In this post I want to briefly share the steps to make a FAT JAR and post an example on my github so I can point others to check the example. How to create a FAT JAR for a JavaFX application? 1- Create a main class that will run your application. This class must have the main method and call your actual application static launch method; 2- Add the Shade Plugin to your project. For those using Gradle notice that Jose Pereda also provided an answer about it i...