Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -802,9 +802,13 @@ public CompletableFuture<List<List<Object>>> getInputOutputMappings(MappingsGenR
@Override
public CompletableFuture<MCPToolResponse> getMCPTools(MCPToolRequest param) {

log.log(Level.INFO, "Fetching MCP tools for connection: {}", param.connectionName);
Connections connections = ConnectionFinder.findConnections(projectUri, Constant.LOWERCASE_AI, connectorHolder, isLegacyProject).getLeft();
AIConnectorHandler aiConnectorHandler = new AIConnectorHandler(mediatorHandler, projectUri);
return CompletableFuture.supplyAsync(() -> aiConnectorHandler.fetchMcpTools(connections.getConnections(), param.connectionName));
log.log(Level.INFO, "Initialized AI connector handler for MCP tools fetch");
return CompletableFuture.supplyAsync(
() -> aiConnectorHandler.fetchMcpTools(param.documentUri, param.range, connections.getConnections(),
param.connectionName));
}

public String getProjectUri() {
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@

package org.eclipse.lemminx.customservice.synapse.mediatorService.pojo;

import java.util.Map;
import org.eclipse.lsp4j.Range;

public class MCPToolRequest {

public String documentUri;
public Range range;
public String connectionName;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@

package org.eclipse.lemminx.customservice.synapse.mediatorService.pojo;

import org.eclipse.lsp4j.Range;

import java.util.Map;
import java.util.List;

public class MCPToolResponse {

public Map<String, String> tools;
public String error;
// Names of tools already present in the document for the requested connection
public List<String> selectedTools;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.eclipse.lemminx.customservice.synapse.syntaxTree.pojo.connector.ai.AIConnector;
import org.eclipse.lemminx.customservice.synapse.syntaxTree.pojo.connector.ai.AgentTool;
import org.eclipse.lemminx.customservice.synapse.syntaxTree.pojo.connector.ai.AgentTools;
import org.eclipse.lemminx.customservice.synapse.syntaxTree.pojo.connector.ai.MCPConnections;
import org.eclipse.lemminx.customservice.synapse.syntaxTree.pojo.mediator.Mediator;
import org.eclipse.lemminx.customservice.synapse.syntaxTree.pojo.template.Template;
import org.eclipse.lemminx.customservice.synapse.utils.ConfigFinder;
Expand Down Expand Up @@ -52,10 +53,49 @@ protected Mediator createSpecificMediator(DOMElement element) {
((AIAgent) aiAgent).setAgentID(Utils.getInlineString(agentIDNode.getFirstChild()));
}

populateMCPConnections((AIAgent) aiAgent, element);
populateTools((AIAgent) aiAgent, element);
return aiAgent;
}

/**
* Extracts MCP connection configuration details from the given DOM element
* and populates the provided {@link AIAgent} instance.
*
* <p>This method searches for a child element named {@code <mcpConnections>}
* inside the provided element. If found, it iterates through its
* child nodes and collects the values of all {@code <mcpConfigKey>} elements.
* Non-null and non-blank values are added to a list of MCP connection keys.</p>
*
* <p>The collected connection keys are then set into a {@link MCPConnections}
* object, which is attached to the given {@link AIAgent}.</p>
*
* @param aiAgent the {@link AIAgent} instance to populate with MCP connection data
* @param element the DOM element that potentially contains the
* {@code <mcpConnections>} configuration
*/
private void populateMCPConnections(AIAgent aiAgent, DOMElement element) {

DOMNode mcpConnectionsElement = Utils.getChildNodeByName(element, Constant.MCP_CONNECTIONS);
if (mcpConnectionsElement != null) {
LOGGER.log(Level.INFO, "Processing MCP connections for AI agent");
MCPConnections mcpConnectionsObj = new MCPConnections();
List<DOMNode> mcpChildren = mcpConnectionsElement.getChildren();
List<String> mcpConnectionList = new java.util.ArrayList<>();
for (DOMNode child : mcpChildren) {
if (child instanceof DOMElement && Constant.MCP_CONFIG_KEY.equals(child.getNodeName())) {
String value = Utils.getInlineString(child.getFirstChild());
if (value != null && !value.isBlank()) {
mcpConnectionList.add(value);
}
}
}
mcpConnectionsObj.setMcpConnections(mcpConnectionList);
aiAgent.setMcpConnections(mcpConnectionsObj);
LOGGER.log(Level.INFO, "MCP connections configured for AI agent with {} connections", mcpConnectionList.size());
}
}

private void populateTools(AIAgent aiAgent, DOMElement element) {

DOMNode toolsElement = Utils.getChildNodeByName(element, Constant.TOOLS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
public class AIAgent extends AIConnector {

private String agentID;
private MCPConnections mcpConnections;
private AgentTools tools;

public String getAgentID() {
Expand All @@ -38,4 +39,14 @@ public void setTools(AgentTools tools) {

this.tools = tools;
}

public MCPConnections getMcpConnections() {

return mcpConnections;
}

public void setMcpConnections(MCPConnections mcpConnections) {

this.mcpConnections = mcpConnections;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com).
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* WSO2 LLC - support for WSO2 Micro Integrator Configuration
*/

package org.eclipse.lemminx.customservice.synapse.syntaxTree.pojo.connector.ai;

import org.eclipse.lemminx.customservice.synapse.syntaxTree.pojo.STNode;

import java.util.ArrayList;
import java.util.List;

public class MCPConnections extends STNode {

private List<String> mcpConnections;

public MCPConnections() {

this.mcpConnections = new ArrayList<>();
}

public List<String> getMcpConnections() {

return mcpConnections;
}

public void setMcpConnections(List<String> mcpConnections) {

this.mcpConnections = mcpConnections;
}

public void addMcpConnection(String mcpConnection) {

this.mcpConnections.add(mcpConnection);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,8 @@ public class Constant {
public static final String TOOLS = "tools";
public static final String TOOL = "tool";
public static final String MCP_TOOLS = "mcpTools";
public static final String MCP_CONFIG_KEY = "mcpConfigKey";
public static final String MCP_CONNECTIONS = "mcpConnections";
public static final String AI_AGENT_TAG = "ai.agent";
public static final String ATTRIBUTE_GROUP = "attributeGroup";
public static final String CURRENT_VALUE = "currentValue";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.apache.maven.shared.invoker.Invoker;
import org.apache.maven.shared.invoker.InvocationResult;
import org.apache.maven.shared.invoker.InvocationRequest;
import org.eclipse.lemminx.commons.BadLocationException;
import org.eclipse.lemminx.commons.TextDocument;
import org.eclipse.lemminx.customservice.synapse.connectors.ConnectorHolder;
import org.eclipse.lemminx.customservice.synapse.connectors.entity.Connector;
Expand All @@ -47,6 +48,7 @@
import org.eclipse.lemminx.dom.DOMParser;
import org.eclipse.lemminx.uriresolver.URIResolverExtensionManager;
import org.eclipse.lsp4j.InitializeParams;
import org.eclipse.lsp4j.Position;
import org.w3c.dom.Node;

import java.io.BufferedInputStream;
Expand Down Expand Up @@ -221,6 +223,33 @@ public static DOMDocument getDOMDocument(File file) throws IOException {
return domDocument;
}

/**
* Returns the {@link DOMNode} located at the given LSP {@link Position} in the document identified
* by {@code documentUri}.
*
* @param documentUri the document URI as a string
* @param position the position inside the document
* @return the {@link DOMNode} at the given position, or {@code null} if not found
* @throws IOException if an I/O error occurs while reading or parsing the document
* @throws BadLocationException if the provided {@code position} is invalid for the document
*/
public static DOMNode getDOMNode(String documentUri, Position position)
throws IOException, BadLocationException {

if (StringUtils.isEmpty(documentUri) || position == null) {
logger.log(Level.INFO, "Invalid input: documentUri is empty or position is null");
return null;
}
logger.log(Level.INFO,
String.format("Retrieving DOM node at position [%d:%d] in document: %s", position.getLine(),
position.getCharacter(), documentUri));
DOMDocument document = Utils.getDOMDocumentFromPath(getAbsolutePath(documentUri));
int offset = document.offsetAt(position);
DOMNode node = document.findNodeAt(offset);
logger.log(Level.INFO, "Found DOM node of type '%s'", node != null ? node.getNodeName() : "null");
return node;
}

/**
* Get the DOM document from the given xml content
*
Expand Down Expand Up @@ -778,6 +807,8 @@ public static String getAbsolutePath(String path) {
try {
return Paths.get(new URI(path)).toAbsolutePath().toString();
} catch (URISyntaxException e) {
logger.log(Level.SEVERE,
String.format("Failed to convert URI to absolute path: %s", path), e);
}
}
return path;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
{{/connections}}
</connections>
{{#supportTools}}<mcpConnections>
{{#mcpConnections}}
<mcpConfigKey>{{.}}</mcpConfigKey>
{{/mcpConnections}}
</mcpConnections>{{/supportTools}}
{{#parameters}}
<{{{name}}} {{#value}}{{#namespaces}} xmlns:{{{prefix}}}="{{{uri}}}"{{/namespaces}}>{{#isCDATA}}<![CDATA[{{{value}}}]]>{{/isCDATA}}{{^isCDATA}}{{value}}{{/isCDATA}}{{/value}}</{{{name}}}>
{{/parameters}}
{{#supportTools}}<tools>
{{#tools}}
<tool name="{{name}}" template="{{template}}" resultExpression="{{resultExpression}}" description="{{description}}"/>
<tool name="{{name}}" {{#isMCP}}type="mcp" mcpConnection="{{mcpConnection}}"{{/isMCP}}{{^isMCP}}template="{{template}}" resultExpression="{{resultExpression}}"{{/isMCP}} description="{{description}}"/>
{{/tools}}
</tools>{{/supportTools}}
</{{tag}}>
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
<xs:element name="mcpConnections">
<xs:complexType>
<xs:sequence>
<xs:element name="mcpConfigKey" type="xs:string" maxOccurs="unbounded"/>
<xs:element name="mcpConfigKey" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
Expand Down
Loading