From da69bbaecae3f3e9fde441011e13384a2463b459 Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Wed, 11 Feb 2026 08:16:22 -0800 Subject: [PATCH 1/3] Upgrade Spring AI to 2.0.0-M2 and add Jackson 3 --- api/build.gradle | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/api/build.gradle b/api/build.gradle index ed797da8c47..f46b8548a98 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -466,6 +466,7 @@ dependencies { ) ) + // Jackson 2 BuildUtils.addExternalDependency( project, new ExternalDependency( @@ -522,6 +523,33 @@ dependencies { } ) + // Jackson 3 + BuildUtils.addExternalDependency( + project, + new ExternalDependency( + "tools.jackson.core:jackson-core:${jacksonVersion3}", + "Jackson Core Library", + "Jackson", + "https://github.com/FasterXML/jackson", + ExternalDependency.APACHE_2_LICENSE_NAME, + ExternalDependency.APACHE_2_LICENSE_URL, + "JSON de/serialization, reporting API dependency", + ) + ) + + BuildUtils.addExternalDependency( + project, + new ExternalDependency( + "tools.jackson.core:jackson-databind:${jacksonDatabindVersion3}", + "Jackson Databind Library", + "Jackson", + "https://github.com/FasterXML/jackson", + ExternalDependency.APACHE_2_LICENSE_NAME, + ExternalDependency.APACHE_2_LICENSE_URL, + "JSON de/serialization, reporting API dependency", + ) + ) + // added because otherwise we get this error: Java 8 date/time type `java.time.LocalDate` not supported by default BuildUtils.addExternalDependency( project, From c803b14eade93af8b6b1001604bbdb532b455553 Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Wed, 11 Feb 2026 16:53:37 -0800 Subject: [PATCH 2/3] Logging for MCP tool and vector store usage --- .../org/labkey/core/mpc/McpServiceImpl.java | 109 +++++++++++++++++- 1 file changed, 105 insertions(+), 4 deletions(-) diff --git a/core/src/org/labkey/core/mpc/McpServiceImpl.java b/core/src/org/labkey/core/mpc/McpServiceImpl.java index 422d0140223..a6d840aa9b2 100644 --- a/core/src/org/labkey/core/mpc/McpServiceImpl.java +++ b/core/src/org/labkey/core/mpc/McpServiceImpl.java @@ -53,9 +53,15 @@ import org.springframework.ai.google.genai.text.GoogleGenAiTextEmbeddingModel; import org.springframework.ai.google.genai.text.GoogleGenAiTextEmbeddingOptions; import org.springframework.ai.mcp.McpToolUtils; +import org.springframework.ai.chat.model.ToolContext; import org.springframework.ai.tool.ToolCallback; +import org.springframework.ai.tool.definition.ToolDefinition; +import org.springframework.ai.tool.metadata.ToolMetadata; +import org.springframework.ai.document.Document; +import org.springframework.ai.vectorstore.SearchRequest; import org.springframework.ai.vectorstore.SimpleVectorStore; import org.springframework.ai.vectorstore.VectorStore; +import org.springframework.ai.vectorstore.filter.Filter; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import reactor.core.publisher.Mono; @@ -154,7 +160,7 @@ public boolean isReady() @Override public void registerTools(@NotNull List tools) { - tools.forEach(tool -> toolMap.put(tool.getToolDefinition().name(), tool)); + tools.forEach(tool -> toolMap.put(tool.getToolDefinition().name(), new _LoggingToolCallback(tool))); } @Override @@ -300,6 +306,64 @@ public void shutdownStarted() } + /** Delegating wrapper that logs vector store similarity searches */ + private static class _LoggingVectorStore implements VectorStore + { + private final VectorStore delegate; + + _LoggingVectorStore(VectorStore delegate) + { + this.delegate = delegate; + } + + @Override + public void add(List documents) + { + delegate.add(documents); + } + + @Override + public void delete(Filter.Expression filterExpression) + { + delegate.delete(filterExpression); + } + + @Override + public void delete(List idList) + { + delegate.delete(idList); + } + + @Override + public List similaritySearch(SearchRequest request) + { + LOG.info("Vector store search: query=\"{}\"", request.getQuery()); + List results = delegate.similaritySearch(request); + if (results.isEmpty()) + { + LOG.info("Vector store search returned no results"); + } + else + { + LOG.info("Vector store search returned {} result(s):", results.size()); + for (Document doc : results) + { + String content = doc.getText(); + String snippet = content.length() > 200 ? content.substring(0, 200) + "..." : content; + LOG.info(" - [{}] {}", doc.getMetadata(), snippet); + } + } + return results; + } + + @Override + public String getName() + { + return delegate.getName(); + } + } + + @Override public ChatClient getChat(HttpSession session, String agentName, Supplier systemPromptSupplier) { @@ -324,7 +388,7 @@ public ChatClient getChat(HttpSession session, String agentName, Supplier Date: Wed, 11 Feb 2026 23:02:55 -0800 Subject: [PATCH 3/3] No need for Jackson 3 direct dependency --- api/build.gradle | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/api/build.gradle b/api/build.gradle index f46b8548a98..17623571fa9 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -523,33 +523,6 @@ dependencies { } ) - // Jackson 3 - BuildUtils.addExternalDependency( - project, - new ExternalDependency( - "tools.jackson.core:jackson-core:${jacksonVersion3}", - "Jackson Core Library", - "Jackson", - "https://github.com/FasterXML/jackson", - ExternalDependency.APACHE_2_LICENSE_NAME, - ExternalDependency.APACHE_2_LICENSE_URL, - "JSON de/serialization, reporting API dependency", - ) - ) - - BuildUtils.addExternalDependency( - project, - new ExternalDependency( - "tools.jackson.core:jackson-databind:${jacksonDatabindVersion3}", - "Jackson Databind Library", - "Jackson", - "https://github.com/FasterXML/jackson", - ExternalDependency.APACHE_2_LICENSE_NAME, - ExternalDependency.APACHE_2_LICENSE_URL, - "JSON de/serialization, reporting API dependency", - ) - ) - // added because otherwise we get this error: Java 8 date/time type `java.time.LocalDate` not supported by default BuildUtils.addExternalDependency( project,