ScreenshotNeo

BlogHow-to

How to Build a Quarkus MCP Server with HTTP

Build a Java MCP server with Quarkus Streamable HTTP: add the extension, expose a tool, run it locally, and test it with MCP Inspector.

By the ScreenshotNeo team1 October 20267 min read

To expose a Quarkus MCP server over HTTP, add the io.quarkiverse.mcp:quarkus-mcp-server-http extension, annotate a Java method with @Tool, start Quarkus, and connect an MCP client to http://localhost:8080/mcp. This guide uses the Streamable HTTP transport and extension version 2.0.1. The registry lists 2.0.1 as released September 11, 2026; the getting-started guide’s Maven command uses 2.0.0. Check the registry and your Quarkus platform compatibility before copying the version into a project.

1. Prerequisites and transport choice

You need Java 17 or later and Maven 3.9+ or Gradle. The Quarkiverse guide identifies Streamable HTTP as the preferred HTTP transport. It also documents an older HTTP/SSE endpoint at /mcp/sse; SSE is deprecated in MCP 2025-03-26. Use Streamable HTTP for a new server unless a client specifically requires the legacy transport.

Transport Endpoint shape When to choose it
Streamable HTTP /mcp New web-accessible MCP servers and clients that support the modern transport.
HTTP/SSE /mcp/sse Legacy-client compatibility when the client requires the older SSE transport.

The MCP protocol version and transport behavior need to agree between client and server. Quarkiverse identifies protocol specification 2026-07-28 and project version 2.0.0. Server 2.0.0 added support for stateless requests in that protocol while preserving the older stateful, session-based path. Do not assume a persistent callback channel for features such as sampling, elicitation, roots, or subscriptions; follow the flow required by the capability and client.

2. Add the HTTP extension

For Maven, add the extension dependency to an existing Quarkus application. The Quarkiverse guide’s generated command uses 2.0.0, while the registry lists 2.0.1. The following uses the registry-listed release; confirm that it matches your Quarkus platform before building.

<dependency>
  <groupId>io.quarkiverse.mcp</groupId>
  <artifactId>quarkus-mcp-server-http</artifactId>
  <version>2.0.1</version>
</dependency>

If the project manages Quarkiverse extension versions through a BOM, follow that project’s version-management pattern rather than adding a conflicting version. For Gradle, add the same artifact and selected version using your existing dependency conventions. Check the extension registry for the current coordinate and compatibility when upgrading.

3. Create an MCP tool

Place a class containing this method under your application’s Java source tree. The @Tool annotation automatically registers the method as an MCP tool, as described in the Quarkiverse getting-started guide.

package org.acme;

import io.quarkiverse.mcp.server.Tool;

public class GreetingTools {
    @Tool(description = "Greet a user by name")
    public String greet(String name) {
        if (name == null || name.isBlank()) {
            return "Hello!";
        }
        return "Hello, " + name + "!";
    }
}

The method’s name becomes the tool name, its description tells clients what it does, and its Java parameters are the inputs. Keep descriptions and parameter names explicit: an MCP client uses that metadata to decide when and how to call the tool. This sample handles an absent or blank name; real tools should also validate domain-specific input and return actionable errors for invalid requests.

4. Run the server locally

  1. Start the Quarkus development server from the project directory:
mvn quarkus:dev
  1. Keep the application running and use the Streamable HTTP endpoint http://localhost:8080/mcp.
  2. Use the Quarkus Dev UI’s MCP Server tools card to invoke greet, or connect MCP Inspector as described below.

The SSE endpoint documented for compatibility is http://localhost:8080/mcp/sse. Select it only when the client expects that legacy transport.

5. Test with MCP Inspector

MCP Inspector is a separate client, useful for checking the server’s advertised tools and making a real tool call. Start the Quarkus app first, configure Inspector for Streamable HTTP, and enter http://localhost:8080/mcp. Connect, select greet, provide a name, and invoke it. The result should contain the greeting.

The Dev UI is convenient for a quick in-app check. Inspector more closely exercises a separately connected MCP client. If a call fails, first verify the selected transport and endpoint path; do not point a Streamable HTTP client at /mcp/sse.

6. Extend the server carefully

Tools are only one MCP capability. Quarkiverse also documents resources and prompts, plus sampling, elicitation, progress, cancellation, and roots. Add these when the client workflow needs them; they are not prerequisites for a basic tool server.

Choose stateful or stateless request handling based on the protocol version, deployment shape, and whether a feature depends on interaction with the client after the initial request. Stateless requests allow any server instance to handle a self-contained call, which can simplify distributed handling. Stateful session behavior remains relevant for flows that rely on session continuity or client interaction. Validate those flows against the protocol version and client you deploy.

7. Security and deployment

The extension can integrate with Quarkus Security for authentication and authorization. The greeting example does not configure an access policy: add and test the policy appropriate for your deployment, including how credentials are supplied by your MCP client. Treat the MCP endpoint like any other exposed application route and verify that unauthenticated and unauthorized requests are handled as intended.

By default, localhost binding protections reject other origins to help prevent DNS rebinding. A request using a hostname or IP instead of localhost can receive 403. Keep initial development testing on localhost. If remote access is required, follow Quarkus’s DNS-rebinding guidance and configure the application for the intended network boundary; do not disable protections without understanding the exposure.

8. Troubleshooting

Symptom Likely cause What to check
Extension cannot be resolved Incorrect coordinates, unavailable version, or mismatch with the Quarkus platform. Verify group and artifact, check the extension registry’s current release, and align with the project’s platform/BOM.
No tool appears in the client The class or method is not being discovered, the annotation import is wrong, or the client has not refreshed its tool list. Confirm the import is io.quarkiverse.mcp.server.Tool, the class is in the application source tree, and reconnect after startup.
404 or connection failure Wrong endpoint or server not running. Use http://localhost:8080/mcp for Streamable HTTP and confirm the Quarkus dev process is listening.
403 when using a hostname or IP Quarkus’s localhost origin protections are rejecting the request. Test with localhost first. For intentional remote access, consult Quarkus DNS-rebinding guidance and configure the deployment deliberately.
Inspector connects but invocation fails Transport mismatch, invalid tool input, or protocol behavior mismatch. Check that Inspector uses Streamable HTTP and the /mcp path; inspect the tool schema and use a non-empty name; confirm client and server protocol support.
Works locally but not in a multi-instance deployment A workflow may rely on stateful session behavior or client callbacks. Determine whether the call is self-contained or uses sampling, elicitation, roots, or subscriptions; configure routing and session behavior to match that flow.

9. Performance, reliability, and cost

The server’s response time depends on the work your tool performs and the resources it uses; the extension information here supplies no benchmark to apply to an application. Keep tool handlers bounded, validate inputs before expensive work, and use the application’s normal timeouts and observability for downstream calls. For long-running operations, use the protocol’s progress and cancellation capabilities where appropriate.

For reliability, verify behavior across client reconnects and server restarts, especially if using stateful sessions or client-interaction features. Stateless requests can make self-contained calls easier to distribute across instances, but they do not remove the need to handle downstream failures or define authentication. The extension itself has no per-call price in the cited material; infrastructure and any services your tools call determine operating cost.

Or skip the browser setup

Quarkus is for building an MCP server. If you also need website screenshots for an MCP workflow, ScreenshotNeo is a website screenshot API and MCP server. It accepts cookie and consent banners before capture and removes 60+ known consent platforms, newsletter popups, and chat widgets. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed; response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.

One request returns an image or PDF. See the ScreenshotNeo API documentation for options and formats.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for the free plan.

FAQ

Does the greeting method need manual MCP registration?

No. The documented @Tool annotation registers the method automatically.

Can I use this server from a browser-based MCP client?

Yes, use an HTTP-capable client with Streamable HTTP support and connect it to the server’s reachable /mcp endpoint. Configure security and network access for the deployment.

Should I start with resources or prompts?

No. A single tool is enough to establish the server and verify the connection. Add resources or prompts when the application needs those capabilities.

Why does the guide show a different extension version?

The registry lists 2.0.1 while the getting-started Maven command uses 2.0.0. Check current registry metadata and platform compatibility when choosing the dependency version.