From e286a0fca8a537f7a1cc75db8c8d16ed617f9270 Mon Sep 17 00:00:00 2001 From: Avichay Marciano Date: Sat, 14 Feb 2026 12:45:26 +0200 Subject: [PATCH] [FLINK-AGENTS] Skip listPrompts for Java MCP servers without prompt support PR #447 fixed the Python MCP path but not the Java path. AgentPlan.extractJavaMCPServer calls listPrompts() unconditionally, which fails with 'Method not found' for MCP servers that only support tools (e.g. AgentCore Gateway). - Add MCPServer.supportsPrompts() checking ServerCapabilities.prompts() - Guard listPrompts call in extractJavaMCPServer with supportsPrompts check --- .../agents/integrations/mcp/MCPServer.java | 11 ++++++++ .../integrations/mcp/MCPServerTest.java | 12 ++++++++ .../apache/flink/agents/plan/AgentPlan.java | 28 +++++++++++-------- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/integrations/mcp/src/main/java/org/apache/flink/agents/integrations/mcp/MCPServer.java b/integrations/mcp/src/main/java/org/apache/flink/agents/integrations/mcp/MCPServer.java index 64e71a321..882553f01 100644 --- a/integrations/mcp/src/main/java/org/apache/flink/agents/integrations/mcp/MCPServer.java +++ b/integrations/mcp/src/main/java/org/apache/flink/agents/integrations/mcp/MCPServer.java @@ -257,6 +257,17 @@ private void validateHttpUrl() { } } + /** + * Check if the MCP server supports prompts based on its declared capabilities. + * + * @return true if the server declared prompt capabilities during initialization + */ + public boolean supportsPrompts() { + McpSyncClient mcpClient = getClient(); + McpSchema.ServerCapabilities caps = mcpClient.getServerCapabilities(); + return caps != null && caps.prompts() != null; + } + /** * List available tools from the MCP server. * diff --git a/integrations/mcp/src/test/java/org/apache/flink/agents/integrations/mcp/MCPServerTest.java b/integrations/mcp/src/test/java/org/apache/flink/agents/integrations/mcp/MCPServerTest.java index 5fe52bccb..3d9d58512 100644 --- a/integrations/mcp/src/test/java/org/apache/flink/agents/integrations/mcp/MCPServerTest.java +++ b/integrations/mcp/src/test/java/org/apache/flink/agents/integrations/mcp/MCPServerTest.java @@ -243,4 +243,16 @@ void testClose() { server.close(); server.close(); // Calling twice should be safe } + + @Test + @DisabledOnJre(JRE.JAVA_11) + @DisplayName("supportsPrompts method exists and is callable via reflection") + void testSupportsPromptsMethodExists() throws Exception { + MCPServer server = new MCPServer(DEFAULT_ENDPOINT); + + // Verify the method exists (AgentPlan calls it via reflection) + java.lang.reflect.Method method = server.getClass().getMethod("supportsPrompts"); + assertThat(method).isNotNull(); + assertThat(method.getReturnType()).isEqualTo(boolean.class); + } } diff --git a/plan/src/main/java/org/apache/flink/agents/plan/AgentPlan.java b/plan/src/main/java/org/apache/flink/agents/plan/AgentPlan.java index 0641e8193..879553fef 100644 --- a/plan/src/main/java/org/apache/flink/agents/plan/AgentPlan.java +++ b/plan/src/main/java/org/apache/flink/agents/plan/AgentPlan.java @@ -432,18 +432,22 @@ private void extractJavaMCPServer(Method method) throws Exception { JavaSerializableResourceProvider.createResourceProvider(toolName, TOOL, tool)); } - // Call listPrompts() via reflection - Method listPromptsMethod = mcpServer.getClass().getMethod("listPrompts"); - @SuppressWarnings("unchecked") - Iterable prompts = - (Iterable) listPromptsMethod.invoke(mcpServer); - - for (SerializableResource prompt : prompts) { - Method getNameMethod = prompt.getClass().getMethod("getName"); - String promptName = (String) getNameMethod.invoke(prompt); - addResourceProvider( - JavaSerializableResourceProvider.createResourceProvider( - promptName, PROMPT, prompt)); + // Call listPrompts() only if the server supports prompts (optional per MCP spec). + // MCP servers like AgentCore Gateway only support tools, not prompts. + Method supportsPromptsMethod = mcpServer.getClass().getMethod("supportsPrompts"); + if ((boolean) supportsPromptsMethod.invoke(mcpServer)) { + Method listPromptsMethod = mcpServer.getClass().getMethod("listPrompts"); + @SuppressWarnings("unchecked") + Iterable prompts = + (Iterable) listPromptsMethod.invoke(mcpServer); + + for (SerializableResource prompt : prompts) { + Method getNameMethod = prompt.getClass().getMethod("getName"); + String promptName = (String) getNameMethod.invoke(prompt); + addResourceProvider( + JavaSerializableResourceProvider.createResourceProvider( + promptName, PROMPT, prompt)); + } } // Call close() via reflection