### Example Tool with Structured Content Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-using-structured-content.adoc This example demonstrates a tool that returns structured content. When compatibility mode is enabled, the structured content will also be available as text content for older clients. ```java @Tool(description = "Get user", structuredContent = true) User getUser(String username) { User user = new User(); user.setName("John Doe"); user.setEmail("john@example.com"); return user; } ``` -------------------------------- ### Start MCP Inspector Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-development-tools.adoc Execute this command to start the MCP Inspector tool. A URL with a token will be provided in the console to access the Inspector in your browser. ```bash npx @modelcontextprotocol/inspector ``` -------------------------------- ### McpConnection Usage Examples Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-filters-and-checks.adoc Demonstrates how to access initial request details, client information, and capabilities from an McpConnection object. ```java // Get initial request with client info and capabilities InitialRequest initialRequest = connection.initialRequest(); // Access client information String clientName = initialRequest.clientInfo().name(); String clientVersion = initialRequest.clientInfo().version(); // Check client capabilities boolean supportsSampling = initialRequest.supportsSampling(); boolean supportsElicitation = initialRequest.supportsElicitation(); boolean supportsRoots = initialRequest.supportsRoots(); ``` -------------------------------- ### Define a Prompt in Java Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-custom-encoders.adoc Example of defining a prompt with a description and a method that returns a Template. Requires importing io.quarkiverse.mcp.server.Prompt. ```java import io.quarkiverse.mcp.server.Prompt; public class MyPrompts { @Prompt(description = "Code review template") Template codeReview(String language) { return new Template( "expert code reviewer", "Review this " + language + " code for best practices."); } } ``` -------------------------------- ### Perform Initial Request Check Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-filters-and-checks.adoc Example of performing an initial request check, validating client capabilities like sampling support. ```java @Override public Uni perform(InitialRequest initialRequest) { // Protocol version String version = initialRequest.protocolVersion(); // Client information String clientName = initialRequest.clientInfo().name(); String clientVersion = initialRequest.clientInfo().version(); // Client capabilities boolean hasSampling = initialRequest.supportsSampling(); boolean hasElicitation = initialRequest.supportsElicitation(); boolean hasRoots = initialRequest.supportsRoots(); // Make decision based on this information if (!hasSampling) { return CheckResult.error("Sampling support required"); } return CheckResult.success(); } ``` -------------------------------- ### Batch Operations Test Setup Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-testing.adoc Initializes the McpSseTestClient for performing batch operations. This is the starting point for sending multiple requests and validating them together. ```java @Test public void testBatchOperations() { McpSseTestClient client = McpAssured.newConnectedSseClient(); client.when() ``` -------------------------------- ### Boolean Input Examples Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-client-integration.adoc Demonstrates creating boolean input schemas for checkboxes, with and without metadata, and using the builder pattern. ```java import io.quarkiverse.mcp.server.ElicitationRequest.BooleanSchema; // Simple checkbox new BooleanSchema(true) ``` ```java import io.quarkiverse.mcp.server.ElicitationRequest.BooleanSchema; // Boolean with metadata new BooleanSchema( "Subscribe", // title "Subscribe to newsletter", // description true, // defaultValue false // required ) ``` ```java import io.quarkiverse.mcp.server.ElicitationRequest.BooleanSchema; // Using the builder BooleanSchema.builder() .setTitle("Subscribe") .setDescription("Subscribe to newsletter") .setDefaultValue(true) .setRequired(false) .build() ``` -------------------------------- ### MCP Client Initialization Request Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/concepts-mcp-protocol.adoc Example of an 'initialize' request sent by an MCP client to the server, including protocol version, client info, and supported capabilities. ```json { "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "{spec-version}", "clientInfo": { "name": "my-mcp-client", "version": "1.0.0" }, "capabilities": { "sampling": {}, "elicitation": {}, "roots": { "listChanged": true } } } } ``` -------------------------------- ### Install and Run Application in Prod Mode Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/samples/secure-mcp-sse-server/README.md Package the application for production and run it using jbang. Ensure you have completed the GitHub OAuth2 application registration and configured `application.properties`. ```shell script ./mvnw install ``` ```shell script jbang org.acme:secure-mcp-sse-server:1.0.0-SNAPSHOT:runner ``` -------------------------------- ### Prometheus Scrape Configuration Example Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-observability.adoc An example Prometheus scrape configuration to collect metrics from the Quarkus MCP server endpoint. ```yaml scrape_configs: - job_name: 'quarkus-mcp-server' metrics_path: '/q/metrics' static_configs: - targets: ['localhost:8080'] ``` -------------------------------- ### Run as MCP Server Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-cli-adapter.adoc Start the CLI application as an MCP server by including the `--mcp` flag. This exposes the CLI commands as MCP tools. ```bash # Start as MCP server $ java -jar myapp.jar --mcp ``` -------------------------------- ### Complete Form Mode Example Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-client-integration.adoc Demonstrates a complete form mode elicitation request with various input types including string, email, number, boolean, and multi-select. ```java import io.quarkiverse.mcp.server.Elicitation; import io.quarkiverse.mcp.server.ElicitationRequest.*; import io.quarkiverse.mcp.server.Tool; import java.util.List; public class MyTools { @Tool(description = "User registration form") String registerUser(Elicitation elicitation) { if (!elicitation.isFormModeSupported()) { return "Not supported"; } var response = elicitation.requestBuilder() .setMessage("Please fill out the registration form:") .addSchemaProperty("username", new StringSchema("Username", "Your username", 20, 3, null, true)) .addSchemaProperty("email", new StringSchema("Email", "Your email", null, null, StringSchema.Format.EMAIL, true)) .addSchemaProperty("age", new NumberSchema("Age", "Your age", 120, 13, true)) .addSchemaProperty("newsletter", new BooleanSchema("Newsletter", "Subscribe to updates", false, false)) .addSchemaProperty("interests", new MultiSelectEnumSchema( List.of("coding", "gaming", "music", "sports"))) .build() .sendAndAwait(); if (response.actionAccepted()) { return "Registration successful for " + response.content().getString("username"); } else { return "Registration cancelled"; } } } ``` -------------------------------- ### Implement IconsProvider Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-metadata-and-icons.adoc Create an IconsProvider implementation and reference it using the @Icons annotation. This example shows a basic implementation returning a single icon. ```java import io.quarkiverse.mcp.server.Tool; import io.quarkiverse.mcp.server.Icons; import io.quarkiverse.mcp.server.IconsProvider; import io.quarkiverse.mcp.server.Icon; import io.quarkiverse.mcp.server.FeatureManager.FeatureInfo; import java.util.List; public class MyTools { @Icons(DatabaseIcons.class) // <1> @Tool(description = "Query the database") String queryDatabase(String sql) { return "Query result"; } public static class DatabaseIcons implements IconsProvider { // <2> @Override public List get(FeatureInfo feature) { return List.of( new Icon("file://icons/database.png", "image/png") // <3> ); } } } ``` -------------------------------- ### Start Quarkus Application in Dev Mode Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-development-tools.adoc Run this command to start your Quarkus application in development mode, which enables the Dev UI. ```bash ./mvnw quarkus:dev ``` -------------------------------- ### Multi-turn Conversation Setup in Java Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-client-integration.adoc Initiate a multi-turn conversation with the LLM by constructing a request with multiple messages. This allows for context-aware interactions. ```java import io.quarkiverse.mcp.server.Sampling; import io.quarkiverse.mcp.server.SamplingMessage; import io.quarkiverse.mcp.server.Tool; public class MyTools { @Tool(description = "Multi-turn conversation") String conversation(Sampling sampling) { if (!sampling.isSupported()) { return "Not supported"; } return sampling.requestBuilder() .setMaxTokens(150) // Recreate the conversation history ``` -------------------------------- ### MCP Server Initialization Response Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/concepts-mcp-protocol.adoc Example of an 'initialize' response from an MCP server, detailing the server's information and supported protocol version. ```json { "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "{spec-version}", "serverInfo": { "name": "quarkus-mcp-server", "version": "1.0.0" } } } ``` -------------------------------- ### Registering a Tool Handler Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-annotations.adoc Example of setting a handler for a tool and registering it. This is typically used when implementing custom tool functionalities. ```java .setHandler(args -> ToolResponse.success("Search results")) .register(); ``` -------------------------------- ### Create User Profile with Record Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-parameter-types.adoc Use Java records for concise, immutable data structures. This example defines a UserProfile record. ```java import io.quarkiverse.mcp.server.Tool; import java.util.List; public class MyTools { @Tool(description = "Create a user profile") String createProfile(UserProfile profile) { return "Created profile for " + profile.username() + " with " + profile.tags().size() + " tags"; } } // Concise record definition public record UserProfile( String username, String email, List tags, boolean active) { } ``` -------------------------------- ### Enum/Select Input Examples Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-client-integration.adoc Shows how to create single-select enum (dropdown) inputs, with and without display titles, default values, and using the builder. ```java import io.quarkiverse.mcp.server.ElicitationRequest.SingleSelectEnumSchema; import java.util.List; // Simple dropdown new SingleSelectEnumSchema(List.of("small", "medium", "large")) ``` ```java import io.quarkiverse.mcp.server.ElicitationRequest.SingleSelectEnumSchema; import java.util.List; // Dropdown with titles new SingleSelectEnumSchema( List.of("s", "m", "l"), // values List.of("Small", "Medium", "Large") // display titles ) ``` ```java import io.quarkiverse.mcp.server.ElicitationRequest.SingleSelectEnumSchema; import java.util.List; // With default value new SingleSelectEnumSchema( List.of("red", "green", "blue"), "blue" // default ) ``` ```java import io.quarkiverse.mcp.server.ElicitationRequest.SingleSelectEnumSchema; import java.util.List; // Using the builder SingleSelectEnumSchema.builder(List.of("s", "m", "l")) .setTitle("Size") .setDescription("Choose a size") .setEnumTitles(List.of("Small", "Medium", "Large")) .setRequired(true) .setDefaultValue("m") .build() ``` -------------------------------- ### Client Request for User Profile Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-parameter-types.adoc Example JSON payload for sending record data to a tool. ```json { "name": "createProfile", "arguments": { "profile": { "username": "jdoe", "email": "jdoe@example.com", "tags": ["developer", "admin"], "active": true } } } ``` -------------------------------- ### Resource Template Annotation Example Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-annotations.adoc Applies resource annotations to a resource template. This allows dynamic resources to also carry metadata like audience and priority. ```java import io.quarkiverse.mcp.server.ResourceTemplate; import io.quarkiverse.mcp.server.Resource.Annotations; import io.quarkiverse.mcp.server.Role; import io.quarkiverse.mcp.server.TextResourceContents; import io.quarkiverse.mcp.server.RequestUri; public class MyResourceTemplates { @ResourceTemplate(uriTemplate = "file:///logs/{date}", description = "Daily log files", annotations = @Annotations(audience = Role.ASSISTANT, priority = 0.7)) TextResourceContents dailyLogs(String date, RequestUri uri) { return new TextResourceContents(uri.value(), "Logs for " + date, "text/plain"); } ``` -------------------------------- ### Example Tool with Default Integer Value Converter Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-parameter-types.adoc Demonstrates how a string default value is converted to an integer for a tool argument. The server uses a `DefaultValueConverter` to transform string inputs into the target argument type. ```java @Tool String exampleTool(@ToolArg(defaultValue = "42") int count) { // The string "42" is converted to the integer 42 return "Count: " + count; } ``` -------------------------------- ### Multi-select Input Examples Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-client-integration.adoc Illustrates creating multi-select enum (checkbox group) inputs, including using the builder with options for min/max items and default values. ```java import io.quarkiverse.mcp.server.ElicitationRequest.MultiSelectEnumSchema; import java.util.List; // Multi-select checkbox group new MultiSelectEnumSchema( List.of("java", "python", "javascript", "go") ) ``` ```java import io.quarkiverse.mcp.server.ElicitationRequest.MultiSelectEnumSchema; import java.util.List; // Using the builder MultiSelectEnumSchema.builder(List.of("java", "python", "javascript", "go")) .setTitle("Languages") .setDescription("Select your programming languages") .setEnumTitles(List.of("Java", "Python", "JavaScript", "Go")) .setMinItems(1) .setMaxItems(3) .setRequired(true) .setDefaultValues(List.of("java")) .build() ``` -------------------------------- ### Define a Tool with Annotations Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/index.adoc Use annotations to define tools declaratively. This example shows a simple addition function. JSON schema generation, parameter validation, and error handling are automatic. ```java @Tool(description = "Calculate the sum of two numbers") int add( @ToolArg(description = "First number") int a, @ToolArg(description = "Second number") int b ) { return a + b; } ``` -------------------------------- ### Create Quarkus Project with MCP STDIO Extension Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/getting-started-stdio.adoc Use this Maven command to create a new Quarkus project with the MCP STDIO extension. Ensure you have JDK 17+, Maven 3.9+, and Mandrel/GraalVM installed. ```bash mvn io.quarkus:quarkus-maven-plugin:{quarkus-version}:create \ -DprojectGroupId=org.acme \ -DprojectArtifactId=mcp-stdio-quickstart \ -Dextensions="io.quarkiverse.mcp:quarkus-mcp-server-stdio:{project-version}" cd mcp-stdio-quickstart ``` -------------------------------- ### Resource Method with Logging and Progress Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-implementing-resources.adoc Demonstrates using `McpLog` for logging and `Progress` for sending updates to the client within a resource method. The `RequestUri` parameter can be used to get the current URI. ```java import io.quarkiverse.mcp.server.McpLog; import io.quarkiverse.mcp.server.Progress; import io.quarkiverse.mcp.server.RequestUri; @Resource(uri = "file:///large-file.dat") BlobResourceContents largeFile(McpLog log, Progress progress) throws Exception { // Note this is a very dummy example of the progress API usage, just for demonstration purposes. // In a real implementation, you would typically want to send multiple progress updates during the file reading process. log.info("Reading large file"); progress.send("Reading file", 0.0); byte[] data = Files.readAllBytes(Path.of("large-file.dat")); progress.send("File read complete", 1.0); return BlobResourceContents.create("file:///large-file.dat", data); } ``` -------------------------------- ### MCP JSON-RPC Response Example Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/concepts-mcp-protocol.adoc This is an example of a JSON-RPC response message in MCP, containing a result for a previous request. ```json { "jsonrpc": "2.0", "id": 1, "result": { "tools": [...] } } ``` -------------------------------- ### MCP JSON-RPC Request Example Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/concepts-mcp-protocol.adoc This is an example of a JSON-RPC request message used in MCP, typically for listing available tools. ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {} } ``` -------------------------------- ### Programmatic Registration of Tools, Resources, and Prompts Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/concepts-architecture.adoc Shows how to dynamically register new tools, resources, and prompts at runtime using the respective manager interfaces. ```java @Startup void registerDynamicFeatures() { toolManager.newTool("dynamic").setHandler(...).register(); resourceManager.newResource("uri").setHandler(...).register(); promptManager.newPrompt("template").setHandler(...).register(); } ``` -------------------------------- ### MCP JSON-RPC Notification Example Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/concepts-mcp-protocol.adoc This is an example of a JSON-RPC notification message in MCP, used for one-way communication like progress updates. ```json { "jsonrpc": "2.0", "method": "notifications/progress", "params": { "progressToken": "abc123", "progress": 50, "total": 100 } } ``` -------------------------------- ### Traffic Logging Example - Sent JSON-RPC Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-development-tools.adoc Example of a sent JSON-RPC message when traffic logging is enabled. This shows the structure of outgoing responses. ```text 2024-01-15 10:23:45 INFO [io.qua.mcp.ser.tra.TrafficLogger] Sent: { "jsonrpc": "2.0", "result": { "content": [ { "type": "text", "text": "Hello, Alice!" } ] }, "id": 1 } ``` -------------------------------- ### Traffic Logging Example - Received JSON-RPC Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-development-tools.adoc Example of a received JSON-RPC message when traffic logging is enabled. This shows the structure of incoming requests. ```text 2024-01-15 10:23:45 INFO [io.qua.mcp.ser.tra.TrafficLogger] Received: { "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "greet", "arguments": { "name": "Alice" } }, "id": 1 } ``` -------------------------------- ### Package Application with Maven Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/samples/weather/README.md Use this command to build an uber-jar of the application. The jar can then be run directly. ```shell ./mvnw install ``` -------------------------------- ### Setting Input and Output Guardrails Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-using-guardrails.adoc Demonstrates how to configure input and output guardrails for a tool using `setInputGuardrails()` and `setOutputGuardrails()` methods. This is typically done during tool registration. ```java .setDescription("Process data with validation") .addArgument("data", "Data to process", true, String.class) .setInputGuardrails(List.of(ValidateInput.class)) // <1> .setOutputGuardrails(List.of(FormatOutput.class, AuditLog.class)) // <2> .setHandler(args -> ToolResponse.success("Processed: " + args.args().get("data"))) .register(); ``` -------------------------------- ### Get Prompt Description Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-filters-and-checks.adoc Retrieves the description of a prompt from the PromptInfo object. ```java // Get prompt description String description = prompt.description(); ``` -------------------------------- ### Run Packaged Application Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/devtools/stdio-sse-proxy/README.md Run the packaged Quarkus uber-jar. Use --help to see available options. ```shell java -jar target/quarkus-mcp-stdio-sse-proxy-1.0.0-SNAPSHOT.jar --help ``` -------------------------------- ### Get Prompt Name Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-filters-and-checks.adoc Retrieves the name of a prompt from the PromptInfo object. ```java // Get prompt name String name = prompt.name(); ``` -------------------------------- ### Get Resource Description Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-filters-and-checks.adoc Retrieves the description of a resource from the ResourceInfo object. ```java // Get resource description String description = resource.description(); ``` -------------------------------- ### Get Resource URI Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-filters-and-checks.adoc Retrieves the URI of a resource from the ResourceInfo object. ```java // Get resource URI String uri = resource.uri(); ``` -------------------------------- ### Get Tool Description Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-filters-and-checks.adoc Retrieves the description of a tool from the ToolInfo object. ```java // Get tool description String description = tool.description(); ``` -------------------------------- ### Demonstrate Primitive Parameter Types Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-parameter-types.adoc Illustrates the use of all Java primitive types as parameters for a tool. Each primitive type has a specific range or representation that the server understands. ```java import io.quarkiverse.mcp.server.Tool; public class MyTools { @Tool(description = "Demonstrates primitive types") String primitiveTypes( boolean flag, // true or false byte byteVal, // -128 to 127 short shortVal, // -32768 to 32767 int intVal, // Standard integer long longVal, // Large integer float floatVal, // Floating point double doubleVal, // Double precision char charVal) { // Single character return "Processed primitive values"; } } ``` -------------------------------- ### Get Tool Name Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-filters-and-checks.adoc Retrieves the name of a tool from the ToolInfo object. ```java // Get tool name String name = tool.name(); ``` -------------------------------- ### Get Protocol Version Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-filters-and-checks.adoc Retrieves the protocol version from the initial request. ```java String protocolVersion = initialRequest.protocolVersion(); ``` -------------------------------- ### Basic Prompt Implementation with Annotations Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-implementing-prompts.adoc Demonstrates how to define a prompt using the @Prompt annotation on a CDI bean method. Arguments can be customized with @PromptArg for descriptions and default values. ```java import io.quarkiverse.mcp.server.Prompt; import io.quarkiverse.mcp.server.PromptArg; import io.quarkiverse.mcp.server.PromptMessage; import io.quarkiverse.mcp.server.TextContent; import jakarta.inject.Inject; // @Singleton <1> public class MyPrompts { @Inject <2> FooService fooService; @Prompt(description = "Put your description here.") <3> PromptMessage foo(@PromptArg(description = "The name", defaultValue = "Max") String name) { <4> return PromptMessage.withUserRole(new TextContent(fooService.ping(name))); } } ``` -------------------------------- ### Resource with Text Content Type Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-implementing-resources.adoc Expose a configuration file as a text resource. Use `TextResourceContents.create` to wrap the file content and URI. Ensure the file exists at the specified path. ```java import io.quarkiverse.mcp.server.BlobResourceContents; import io.quarkiverse.mcp.server.Resource; import io.quarkiverse.mcp.server.TextResourceContents; import java.nio.file.Files; import java.nio.file.Path; public class FileResources { @Resource(uri = "file:///config.json") TextResourceContents configFile() throws Exception { String content = Files.readString(Path.of("config.json")); return TextResourceContents.create( "file:///config.json", content); } ``` -------------------------------- ### Get Resource Name Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-filters-and-checks.adoc Retrieves the name of a resource from the ResourceInfo object, if available. ```java // Get resource name (if available) String name = resource.name(); ``` -------------------------------- ### Get Resource Template Description Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-filters-and-checks.adoc Retrieves the description of a resource template from the ResourceTemplateInfo object. ```java // Get template description String description = template.description(); ``` -------------------------------- ### Provide Command Description for AI Discovery (Java) Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-cli-adapter.adoc Annotate your command with a clear, actionable description using `@Command(description = "...")` to help AI choose the right tool. ```java @Command( name = "analyze", description = "Analyze code quality and suggest improvements" // <1> ) ``` -------------------------------- ### Get Resource Template Name Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-filters-and-checks.adoc Retrieves the name of a resource template from the ResourceTemplateInfo object. ```java // Get template name String name = template.name(); ``` -------------------------------- ### Programmatic Prompt Registration in Java Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-implementing-prompts.adoc Demonstrates how to register a prompt programmatically using the `PromptManager` API, typically done at application startup. The `promptManager.newPrompt("prompt_name")` method initiates the creation of a new prompt. ```java import io.quarkiverse.mcp.server.PromptManager; import io.quarkiverse.mcp.server.PromptMessage; import io.quarkiverse.mcp.server.PromptResponse; import io.quarkiverse.mcp.server.TextContent; import io.quarkus.runtime.Startup; import jakarta.inject.Inject; import java.util.List; public class MyPrompts { @Inject PromptManager promptManager; // <1> @Inject CodeService codeService; @Startup // <2> void addPrompt() { promptManager.newPrompt("code_assist") // <3> ``` -------------------------------- ### Test Tool Execution and Response Validation Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-testing.adoc Example of testing tool execution and validating the response. ```java @Test public void testToolCall() { ``` -------------------------------- ### Asynchronous Resource Creation Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-implementing-resources.adoc Demonstrates how to return asynchronous results using Uni for resource content. ```APIDOC ## POST /file:///async-data ### Description Creates a resource asynchronously, returning content wrapped in `Uni`. ### Method GET ### Endpoint /file:///async-data ### Request Body None ### Response #### Success Response (200) - **data** (TextResourceContents) - The asynchronously fetched resource content. ### Response Example ```json { "file": "file:///async-data", "content": "your_data_here" } ``` ``` -------------------------------- ### Per-Server Transport Configuration Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-multiple-servers.adoc Configure transports independently for each server. This snippet shows the start of such configuration. ```properties # Configure transports independently: ``` -------------------------------- ### Prompt with Logging in Java Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-implementing-prompts.adoc Demonstrates how to use McpLog to log information within a prompt method. Ensure McpLog is imported. ```java import io.quarkiverse.mcp.server.McpLog; @Prompt(description = "Prompt with logging") PromptMessage loggedPrompt(String input, McpLog log) { log.info("Processing prompt with input: %s", input); return PromptMessage.withUserRole(new TextContent("Processing: " + input)); } ``` -------------------------------- ### Get Resource Template URI Pattern Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-filters-and-checks.adoc Retrieves the URI template pattern from the ResourceTemplateInfo object. ```java // Get URI template pattern String uriTemplate = template.uriTemplate(); ``` -------------------------------- ### Client Request for Customer Data Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-parameter-types.adoc Example JSON payload for sending custom object data to a tool. ```json { "name": "processCustomer", "arguments": { "customer": { "name": "John Doe", "email": "john@example.com", "age": 30 } } } ``` -------------------------------- ### Tool Metadata Example Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-metadata-and-icons.adoc This JSON shows the structure of metadata added to a tool using the @MetaField annotation. ```json { "_meta": { "category": "data-processing", "version": "2.1" } } ``` -------------------------------- ### Run Proxy Server (Custom Endpoint) Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/devtools/stdio-sse-proxy/README.md Run the proxy server with a custom SSE endpoint URI. ```shell java -jar target/quarkus-mcp-stdio-sse-proxy-1.0.0-SNAPSHOT-runner.jar http://my.app/mcp ``` -------------------------------- ### Test Listing Tools with SSE Client Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-testing.adoc Verify that tools are registered and exposed correctly by listing them using an SSE client and asserting the results. ```java import static org.junit.jupiter.api.Assertions.*; @Test public void testToolsList() { McpSseTestClient client = McpAssured.newConnectedSseClient(); client.when() .toolsList(page -> { assertEquals(3, page.size()); // <1> ToolInfo tool = page.findByName("calculate"); // <2> assertEquals("Perform calculations", tool.description()); assertNotNull(tool.inputSchema()); // <3> }) .thenAssertResults(); // <4> } ``` -------------------------------- ### Applying Multiple Input and Output Guardrails Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-using-guardrails.adoc Shows how to apply both input and output guardrails to a single tool method. ```java @ToolGuardrails( input = { ValidateEmail.class, SanitizeInput.class }, output = { ValidateResponse.class, AuditLog.class } ) @Tool String processEmail(String to, String body) { return "Email processed"; } ``` -------------------------------- ### Configure Client Capabilities for McpSseTestClient Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-testing.adoc Specify which client capabilities to advertise to the server during initialization. The server will see these capabilities when the client connects. ```java import io.quarkiverse.mcp.server.ClientCapability; @Test public void testClientCapabilities() { McpSseTestClient client = McpAssured.newSseClient() .setClientCapabilities( ClientCapability.SAMPLING, // <1> ClientCapability.ROOTS) .build() .connect(); ``` -------------------------------- ### Registering a Dynamic Tool with ToolManager Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/concepts-architecture.adoc Illustrates how to dynamically register a new tool using the ToolManager. This involves defining the tool's name, description, arguments, and a handler function to execute when the tool is called. ```java import io.quarkiverse.mcp.server.ToolManager; import io.quarkiverse.mcp.server.model.ToolResponse; import jakarta.inject.Inject; // Assume ToolManager is injected public class ToolRegistration { @Inject ToolManager toolManager; void addDynamicTool() { toolManager.newTool("greet") .setDescription("Greet someone") .addArgument("name", "Person to greet", true, String.class) .setHandler(args -> ToolResponse.success("Hello, " + args.args().get("name"))) .register(); } } ``` -------------------------------- ### Prompt Returning a Single Message Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-implementing-prompts.adoc Example of a prompt method that returns a single PromptMessage. The TextContent is automatically wrapped in a PromptResponse. ```java @Prompt(description = "Simple prompt") PromptMessage simplePrompt(String input) { return PromptMessage.withUserRole(new TextContent("Process: " + input)); } ``` -------------------------------- ### Prompt with Multiple Arguments and Default Values Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-implementing-prompts.adoc Shows how to define a prompt with multiple arguments, each customizable with descriptions and default values using @PromptArg. Arguments without default values are required. ```java import io.quarkiverse.mcp.server.Prompt; import io.quarkiverse.mcp.server.PromptArg; import io.quarkiverse.mcp.server.PromptMessage; import io.quarkiverse.mcp.server.TextContent; public class CodePrompts { @Prompt(description = "Generate code based on requirements") PromptMessage generateCode( @PromptArg(description = "Programming language", defaultValue = "Java") String language, @PromptArg(description = "Code requirements") String requirements, @PromptArg(description = "Code style", defaultValue = "clean") String style) { String promptText = String.format( "Generate %s code with %s style for: %s", language, style, requirements ); return PromptMessage.withUserRole(new TextContent(promptText)); } } ``` -------------------------------- ### Get Roots Asynchronously Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-client-integration.adoc Retrieve roots asynchronously using Uni for non-blocking operations. Handles cases where roots are not supported or empty. ```java import io.quarkiverse.mcp.server.Root; import io.quarkiverse.mcp.server.Roots; import io.quarkiverse.mcp.server.Tool; import io.smallrye.mutiny.Uni; import java.util.List; public class MyTools { @Tool(description = "Get roots asynchronously") Uni getRootsAsync(Roots roots) { if (!roots.isSupported()) { return Uni.createFrom().item("Not supported"); } return roots.list() // <1> .map(rootList -> { if (rootList.isEmpty()) { return "No roots found"; } return "First root: " + rootList.get(0).name(); }); } } ``` -------------------------------- ### Create SSE Transport Client Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-testing.adoc Instantiate an SSE client for testing. Remember to disconnect after use. ```java import io.quarkiverse.mcp.server.test.McpAssured; import io.quarkiverse.mcp.server.test.McpAssured.McpSseTestClient; @Test public void testSseTransport() { McpSseTestClient client = McpAssured.newConnectedSseClient(); // <1> // Test operations... client.disconnect(); // <2> } ``` -------------------------------- ### List Roots from Client Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-client-integration.adoc Request and await the list of roots from the client. Each root includes a name and URI. ```java import io.quarkiverse.mcp.server.Root; import io.quarkiverse.mcp.server.Roots; import io.quarkiverse.mcp.server.Tool; import java.util.List; public class MyTools { @Tool(description = "Get client roots") String getRoots(Roots roots) { if (!roots.isSupported()) { return "Roots not supported"; } List rootList = roots.listAndAwait(); // <1> StringBuilder result = new StringBuilder("Client roots:\n"); for (Root root : rootList) { result.append("- ").append(root.name()) .append(": ").append(root.uri()) .append("\n"); // <2> } return result.toString(); } } ``` -------------------------------- ### Create ResourceLink Response Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/reference-content-types.adoc Use ResourceLink to provide a reference to a resource without embedding its content. This example creates a link to a file resource. ```java import io.quarkiverse.mcp.server.Tool; import io.quarkiverse.mcp.server.ResourceLink; import io.quarkiverse.mcp.server.ToolResponse; public class MyTools { @Tool(description = "Returns a link to a resource") ToolResponse getResourceLink(String resourceName) { String uri = "file:///resources/" + resourceName; return ToolResponse.success(new ResourceLink(uri, "Link to " + resourceName)); } } ``` -------------------------------- ### Customize STDIO Client Configuration Source: https://github.com/quarkiverse/quarkus-mcp-server/blob/main/docs/modules/ROOT/pages/guides-testing.adoc Configure the STDIO client by setting the command, working directory, environment variables, and stderr handler before building and connecting. ```java McpStdioTestClient client = McpAssured.newStdioClient() .setCommand("java", "-jar", "/path/to/app.jar") // <1> .setWorkingDirectory(Path.of("/path/to/workdir")) // <2> .setEnvironment(Map.of("MY_VAR", "value")) // <3> .setStderrHandler(line -> LOG.info(line)) // <4> .build() .connect(); ```