Build an MCP Server With Quarkus: Tools and Client Tests

Quarkus includes an MCP server extension that lets you expose Java tools over a standard connection with minimal boilerplate. This guide covers setup, tool registration, transport, client verification, and how to keep framework choices and debugging lessons for later sessions.

Updated 4 min read

Quarkus provides an MCP server extension that handles the protocol layer automatically, letting you annotate plain Java methods to expose them as tools that AI apps like Claude and Cursor can call. The extension manages JSON-RPC, capability negotiation, and transport; you write the business logic. Tools like fenbs preserve the framework choices, implementation decisions, and debugging lessons your team learns along the way, so a coding assistant returning to the project starts with the reasoning behind the current design rather than inferring it from code.

Check whether an existing server from the MCP server directory already covers your use case. A custom Quarkus server is the right choice when you need tools backed by Java services, existing Quarkus beans, or JVM-only libraries.

Set up the Quarkus MCP server extension

  1. Add the Quarkus MCP server extension to your project. In Maven, add io.quarkiverse.mcp:quarkus-mcp-server-core as a dependency. You can also use the Quarkus CLI (opens in a new tab) with quarkus extension add mcp-server-core.
  2. Annotate a CDI bean method with @Tool to expose it. Give it a description string that tells the AI what the tool does and what arguments it expects.
  3. Define parameters with @ToolArg annotations. Each parameter needs a description; required parameters must be declared explicitly.
  4. Choose a transport. Quarkus MCP server supports stdio and HTTP (SSE). Stdio runs the server as a subprocess; HTTP lets multiple clients connect and works behind a reverse proxy.
  5. Build and run the server, then add it to your AI client's config. See MCP server configuration for the config format.
Quarkus MCP tool example
@ApplicationScoped
public class BuildTools {

  @Tool(description = "Return the build status for the given module")
  public String getBuildStatus(
    @ToolArg(description = "The module name, e.g. api or web") String module
  ) {
    return buildService.getStatus(module);
  }
}

Write descriptions the AI will use correctly

The description on each @Tool and @ToolArg is what the AI reads when deciding whether and how to call the tool. Write the tool description as a plain sentence: what it returns, under what conditions, and what it does not do. Write the argument description as a short phrase stating the expected value and format.

Poor descriptions produce wrong calls. If the AI consistently sends arguments in the wrong format or calls a tool in contexts where it should not, the description is usually the cause. Iterate on descriptions before adding more tools.

Choose a transport and test the connection

Stdio transport runs the server as a subprocess started by the AI client. It is the simplest option for local development: no port, no TLS, no proxy. The Quarkus dev mode works well here because hot reload keeps the tools in sync with your code.

HTTP transport (SSE) is better for team deployments or when the server must run independently. The MCP server hosting guide covers deployment options. The MCP server spec defines which transport versions are supported across spec releases.

Use the MCP Inspector to test the server before connecting an AI client. Run npx @modelcontextprotocol/inspector and point it at your server. Verify each tool lists correctly, accepts valid arguments, and returns a useful error for invalid ones.

What can go wrong

The most common issue is a CDI scope mismatch: a @RequestScoped bean injected into a tool method that needs a longer-lived context. Quarkus will log a clear error. Make sure beans that hold state across tool calls are @ApplicationScoped or @Singleton.

If the client starts the server but no tools appear, check that the extension dependency is present and the annotated bean is in a package Quarkus scans. Quarkus only scans classes within the application's package hierarchy by default. See MCP server architecture for how the protocol registers tools on connection.

Quarkus supports native compilation with GraalVM, which produces a binary that starts faster and uses less memory than the JVM version. An MCP server compiled to a native image is a leaner subprocess for the AI client to start. The Quarkus MCP extension handles most native configuration automatically, but custom code that uses reflection or runtime class loading needs explicit configuration. Add the necessary metadata to src/main/resources/META-INF/native-image/ and run quarkus build --native early in the project to catch issues before the implementation grows large. Record which Quarkus version and GraalVM version the project targets as a rule in fenbs, since native compilation behavior can change between releases. Including the native build in your regular test pipeline means you catch GraalVM incompatibilities early rather than at deploy time. Keep the GraalVM version pinned in the build tooling rather than floating on the latest release.

How fenbs helps

Preserve framework choices and debugging lessons across sessions

Record the Quarkus extension version, transport choice, CDI scope decisions, and tool-naming conventions as Decisions and rules in fenbs. Add debugging lessons when you resolve a tricky issue. The next coding session reads those records first and does not re-hit the same problems or re-litigate choices already made.

Create a free account

Free for one person · No credit card · Works with Claude, ChatGPT, Cursor and more

How to do this with fenbs

  1. Create a free account and add a project for your Quarkus MCP server.
  2. Record key decisions as Decisions and rules: extension version, transport choice, CDI scope conventions, and any tool that required a non-obvious implementation.
  3. Add open tasks to the board for each tool still to build, each test to write, and each integration to verify.
  4. Connect your coding assistant to fenbs at Integrations. It reads the rules and task status at the start of each session.
  5. When you resolve a tricky bug or a framework gotcha, add it as a lesson. The next session that touches the same area reads it before working.

fenbs does not read your Java source files. It holds the project decisions and lessons your coding assistant needs between sessions. Connecting it also lets you switch between coding tools without losing that context.

Questions people ask.

Is there an official Quarkus MCP server extension?

Yes. The Quarkus MCP server extension is maintained in the Quarkiverse hub at quarkus.io. You can add it with the Quarkus CLI or by adding the Maven dependency directly. Check the Quarkus extensions catalog for the current version.

What transports does the Quarkus MCP extension support?

The extension supports stdio (subprocess) and HTTP with Server-Sent Events. Stdio is the simplest for local development; HTTP is better for shared or cloud-deployed servers.

How do I test a Quarkus MCP server locally?

Use the MCP Inspector (npx @modelcontextprotocol/inspector) to connect directly to the server, list tools, and call them with test arguments. In Quarkus dev mode, changes to tool methods reload without restarting the server.

What CDI scope should a tool bean use?

Use @ApplicationScoped or @Singleton for beans that hold state or resources across tool calls. Use @RequestScoped only for per-call state, and be aware that request scope is created and destroyed with each tool invocation.

How do I keep framework decisions available across coding sessions?

Save them as Decisions and rules in a fenbs project linked to your coding assistant. The assistant reads them at the start of each session and treats agreed choices as rules, so it does not propose conflicting approaches.

More in Connect your AI tools

All Connect your AI tools articles

Start with one thing.

Free for one person · No credit card · Works with Claude, ChatGPT, Cursor and more

There is nothing to set up first. Write one line and you’ve started.