Skip to content

Commit

Permalink
Make the server info included in the "initialize" response configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
mkouba committed Dec 16, 2024
1 parent 6d383cc commit 0ad5aec
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.quarkiverse.mcp.server.test.serverinfo;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.net.URISyntaxException;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkiverse.mcp.server.test.McpClient;
import io.quarkiverse.mcp.server.test.McpServerTest;
import io.quarkus.test.QuarkusUnitTest;
import io.vertx.core.json.JsonObject;

public class CustomServerInfoTest extends McpServerTest {

private static final String NAME = "Foo";
private static final String VERSION = "1.0";

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot(root -> root.addClasses(McpClient.class))
.overrideConfigKey("quarkus.mcp-server.server-info.name", NAME)
.overrideConfigKey("quarkus.mcp-server.server-info.version", VERSION);

@Test
public void testServerInfo() throws URISyntaxException {
initClient(result -> {
JsonObject serverInfo = result.getJsonObject("serverInfo");
assertNotNull(serverInfo);
assertEquals(NAME, serverInfo.getString("name"));
assertEquals(VERSION, serverInfo.getString("version"));
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.quarkiverse.mcp.server.test.serverinfo;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.net.URISyntaxException;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkiverse.mcp.server.test.McpClient;
import io.quarkiverse.mcp.server.test.McpServerTest;
import io.quarkus.test.QuarkusUnitTest;
import io.vertx.core.json.JsonObject;

public class DefaultServerInfoTest extends McpServerTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot(root -> root.addClasses(McpClient.class));

@Test
public void testServerInfo() throws URISyntaxException {
initClient(result -> {
JsonObject serverInfo = result.getJsonObject("serverInfo");
assertNotNull(serverInfo);
assertEquals("quarkus-mcp-server-deployment", serverInfo.getString("name"));
assertEquals("999-SNAPSHOT", serverInfo.getString("version"));
});
}
}
38 changes: 38 additions & 0 deletions docs/modules/ROOT/pages/includes/quarkus-mcp-server.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,43 @@ endif::add-copy-button-to-env-var[]
|string
|`/mcp`

a|icon:lock[title=Fixed at build time] [[quarkus-mcp-server_quarkus-mcp-server-server-info-name]] [.property-path]##link:#quarkus-mcp-server_quarkus-mcp-server-server-info-name[`quarkus.mcp-server.server-info.name`]##

[.description]
--
The name of the server is included in the response to an `initialize` request as defined by the
https://spec.modelcontextprotocol.io/specification/basic/lifecycle/#initialization[spec].
By default, the value of the `quarkus.application.name` config property is used.


ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_MCP_SERVER_SERVER_INFO_NAME+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_MCP_SERVER_SERVER_INFO_NAME+++`
endif::add-copy-button-to-env-var[]
--
|string
|

a|icon:lock[title=Fixed at build time] [[quarkus-mcp-server_quarkus-mcp-server-server-info-version]] [.property-path]##link:#quarkus-mcp-server_quarkus-mcp-server-server-info-version[`quarkus.mcp-server.server-info.version`]##

[.description]
--
The version of the server is included in the response to an `initialize` request as defined by the
https://spec.modelcontextprotocol.io/specification/basic/lifecycle/#initialization[spec].
By default, the value of the `quarkus.application.version` config property is used.


ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_MCP_SERVER_SERVER_INFO_VERSION+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_MCP_SERVER_SERVER_INFO_VERSION+++`
endif::add-copy-button-to-env-var[]
--
|string
|

|===

Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,43 @@ endif::add-copy-button-to-env-var[]
|string
|`/mcp`

a|icon:lock[title=Fixed at build time] [[quarkus-mcp-server_quarkus-mcp-server-server-info-name]] [.property-path]##link:#quarkus-mcp-server_quarkus-mcp-server-server-info-name[`quarkus.mcp-server.server-info.name`]##

[.description]
--
The name of the server is included in the response to an `initialize` request as defined by the
https://spec.modelcontextprotocol.io/specification/basic/lifecycle/#initialization[spec].
By default, the value of the `quarkus.application.name` config property is used.


ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_MCP_SERVER_SERVER_INFO_NAME+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_MCP_SERVER_SERVER_INFO_NAME+++`
endif::add-copy-button-to-env-var[]
--
|string
|

a|icon:lock[title=Fixed at build time] [[quarkus-mcp-server_quarkus-mcp-server-server-info-version]] [.property-path]##link:#quarkus-mcp-server_quarkus-mcp-server-server-info-version[`quarkus.mcp-server.server-info.version`]##

[.description]
--
The version of the server is included in the response to an `initialize` request as defined by the
https://spec.modelcontextprotocol.io/specification/basic/lifecycle/#initialization[spec].
By default, the value of the `quarkus.application.version` config property is used.


ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_MCP_SERVER_SERVER_INFO_VERSION+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_MCP_SERVER_SERVER_INFO_VERSION+++`
endif::add-copy-button-to-env-var[]
--
|string
|

|===

Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.quarkiverse.mcp.server.runtime;

import java.util.Optional;

import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;
import io.smallrye.config.ConfigMapping;
Expand All @@ -17,4 +19,34 @@ public interface McpBuildTimeConfig {
@WithDefault("/mcp")
String rootPath();

/**
* The server info is included in the response to an `initialize` request as defined by the
* https://spec.modelcontextprotocol.io/specification/basic/lifecycle/#initialization[spec].
*
* @asciidoclet
*/
ServerInfo serverInfo();

public interface ServerInfo {

/**
* The name of the server is included in the response to an `initialize` request as defined by the
* https://spec.modelcontextprotocol.io/specification/basic/lifecycle/#initialization[spec].
* By default, the value of the `quarkus.application.name` config property is used.
*
* @asciidoclet
*/
Optional<String> name();

/**
* The version of the server is included in the response to an `initialize` request as defined by the
* https://spec.modelcontextprotocol.io/specification/basic/lifecycle/#initialization[spec].
* By default, the value of the `quarkus.application.version` config property is used.
*
* @asciidoclet
*/
Optional<String> version();

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.List;
import java.util.Map;

import org.eclipse.microprofile.config.ConfigProvider;
import org.jboss.logging.Logger;

import io.quarkiverse.mcp.server.ClientCapability;
Expand All @@ -27,10 +28,13 @@ class McpMessagesHandler implements Handler<RoutingContext> {

private final PromptMessageHandler promptHandler;

McpMessagesHandler(ConnectionManager connectionManager) {
private final McpBuildTimeConfig config;

McpMessagesHandler(ConnectionManager connectionManager, McpBuildTimeConfig config) {
this.connectionManager = connectionManager;
this.toolHandler = new ToolMessageHandler();
this.promptHandler = new PromptMessageHandler();
this.config = config;
}

@Override
Expand Down Expand Up @@ -165,8 +169,14 @@ static JsonObject newResult(Object id, Object result) {
private Map<String, Object> serverInfo() {
Map<String, Object> info = new HashMap<>();
info.put("protocolVersion", "2024-11-05");
info.put("serverInfo", Map.of("name", "Foo", "version", "999-SNAPSHOT"));
info.put("capabilities", Map.of("prompts", Map.of()));

String serverName = config.serverInfo().name()
.orElse(ConfigProvider.getConfig().getOptionalValue("quarkus.application.name", String.class).orElse("N/A"));
String serverVersion = config.serverInfo().version()
.orElse(ConfigProvider.getConfig().getOptionalValue("quarkus.application.version", String.class).orElse("N/A"));
info.put("serverInfo", Map.of("name", serverName, "version", serverVersion));

info.put("capabilities", Map.of("prompts", Map.of(), "tools", Map.of()));
return info;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ public class McpServerRecorder {

private static final Logger LOG = Logger.getLogger(McpServerRecorder.class);

private final McpBuildTimeConfig config;

public McpServerRecorder(McpBuildTimeConfig config) {
this.config = config;
}

public Handler<RoutingContext> createSseEndpointHandler(String mcpPath) {

ArcContainer container = Arc.container();
Expand Down Expand Up @@ -68,7 +74,7 @@ public void accept(Route route) {
}

public Handler<RoutingContext> createMessagesEndpointHandler() {
return new McpMessagesHandler(Arc.container().instance(ConnectionManager.class).get());
return new McpMessagesHandler(Arc.container().instance(ConnectionManager.class).get(), config);
}

}

0 comments on commit 0ad5aec

Please sign in to comment.