Skip to content

Commit 37d79e6

Browse files
Add Feature Flag for MCP connectors Feature (#3738)
* Add Feature Flag for MCP connectors Feature Signed-off-by: rithin-pullela-aws <rithinp@amazon.com> * Address failing tests Signed-off-by: rithin-pullela-aws <rithinp@amazon.com> * Add UT to verify MCP feature is disabled by default Signed-off-by: rithin-pullela-aws <rithinp@amazon.com> --------- Signed-off-by: rithin-pullela-aws <rithinp@amazon.com>
1 parent 2da7d7a commit 37d79e6

File tree

10 files changed

+119
-4
lines changed

10 files changed

+119
-4
lines changed

common/src/main/java/org/opensearch/ml/common/CommonValue.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.util.Set;
99

1010
import org.opensearch.Version;
11+
import org.opensearch.common.settings.Setting;
1112

1213
import com.google.common.collect.ImmutableSet;
1314

@@ -94,6 +95,13 @@ public class CommonValue {
9495
public static final String MCP_SYNC_CLIENT = "mcp_sync_client";
9596
public static final String MCP_EXECUTOR_SERVICE = "mcp_executor_service";
9697
public static final String MCP_TOOLS_FIELD = "tools";
98+
public static final String MCP_CONNECTORS_FIELD = "mcp_connectors";
99+
public static final String MCP_CONNECTOR_ID_FIELD = "mcp_connector_id";
100+
101+
public static final Setting<Boolean> ML_COMMONS_MCP_FEATURE_ENABLED = Setting
102+
.boolSetting("plugins.ml_commons.mcp_feature_enabled", false, Setting.Property.NodeScope, Setting.Property.Dynamic);
103+
public static final String ML_COMMONS_MCP_FEATURE_DISABLED_MESSAGE =
104+
"The MCP feature is not enabled. To enable, please update the setting " + ML_COMMONS_MCP_FEATURE_ENABLED.getKey();
97105

98106
// TOOL Constants
99107
public static final String TOOL_INPUT_SCHEMA_FIELD = "input_schema";

ml-algorithms/src/main/java/org/opensearch/ml/engine/algorithms/agent/AgentUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
package org.opensearch.ml.engine.algorithms.agent;
77

88
import static org.opensearch.core.xcontent.XContentParserUtils.ensureExpectedToken;
9+
import static org.opensearch.ml.common.CommonValue.MCP_CONNECTORS_FIELD;
10+
import static org.opensearch.ml.common.CommonValue.MCP_CONNECTOR_ID_FIELD;
911
import static org.opensearch.ml.common.CommonValue.ML_CONNECTOR_INDEX;
1012
import static org.opensearch.ml.common.CommonValue.TENANT_ID_FIELD;
1113
import static org.opensearch.ml.common.utils.StringUtils.getParameterMap;
@@ -125,8 +127,6 @@ public class AgentUtils {
125127
public static final String LLM_FINAL_RESPONSE_POST_FILTER = "llm_final_response_post_filter";
126128
public static final String LLM_FINISH_REASON_PATH = "llm_finish_reason_path";
127129
public static final String LLM_FINISH_REASON_TOOL_USE = "llm_finish_reason_tool_use";
128-
public static final String MCP_CONNECTORS_FIELD = "mcp_connectors";
129-
public static final String MCP_CONNECTOR_ID_FIELD = "mcp_connector_id";
130130
public static final String TOOL_FILTERS_FIELD = "tool_filters";
131131

132132
public static String addExamplesToPrompt(Map<String, String> parameters, String prompt) {

ml-algorithms/src/main/java/org/opensearch/ml/engine/algorithms/agent/MLAgentExecutor.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77

88
import static org.opensearch.common.xcontent.json.JsonXContent.jsonXContent;
99
import static org.opensearch.core.xcontent.XContentParserUtils.ensureExpectedToken;
10+
import static org.opensearch.ml.common.CommonValue.MCP_CONNECTORS_FIELD;
1011
import static org.opensearch.ml.common.CommonValue.ML_AGENT_INDEX;
12+
import static org.opensearch.ml.common.CommonValue.ML_COMMONS_MCP_FEATURE_DISABLED_MESSAGE;
1113
import static org.opensearch.ml.common.CommonValue.ML_TASK_INDEX;
1214
import static org.opensearch.ml.common.MLTask.LAST_UPDATE_TIME_FIELD;
1315
import static org.opensearch.ml.common.MLTask.RESPONSE_FIELD;
@@ -26,6 +28,7 @@
2628
import java.util.Objects;
2729

2830
import org.opensearch.ExceptionsHelper;
31+
import org.opensearch.OpenSearchException;
2932
import org.opensearch.OpenSearchStatusException;
3033
import org.opensearch.ResourceNotFoundException;
3134
import org.opensearch.action.get.GetResponse;
@@ -43,6 +46,7 @@
4346
import org.opensearch.core.xcontent.NamedXContentRegistry;
4447
import org.opensearch.core.xcontent.XContentParser;
4548
import org.opensearch.index.IndexNotFoundException;
49+
import org.opensearch.ml.common.CommonValue;
4650
import org.opensearch.ml.common.FunctionName;
4751
import org.opensearch.ml.common.MLAgentType;
4852
import org.opensearch.ml.common.MLTask;
@@ -109,6 +113,7 @@ public class MLAgentExecutor implements Executable, SettingsChangeListener {
109113
private Map<String, Memory.Factory> memoryFactoryMap;
110114
private volatile Boolean isMultiTenancyEnabled;
111115
private Encryptor encryptor;
116+
private static volatile boolean mcpFeatureIsEnabled;
112117

113118
public MLAgentExecutor(
114119
Client client,
@@ -130,6 +135,10 @@ public MLAgentExecutor(
130135
this.memoryFactoryMap = memoryFactoryMap;
131136
this.isMultiTenancyEnabled = isMultiTenancyEnabled;
132137
this.encryptor = encryptor;
138+
this.mcpFeatureIsEnabled = CommonValue.ML_COMMONS_MCP_FEATURE_ENABLED.get(clusterService.getSettings());
139+
clusterService
140+
.getClusterSettings()
141+
.addSettingsUpdateConsumer(CommonValue.ML_COMMONS_MCP_FEATURE_ENABLED, it -> mcpFeatureIsEnabled = it);
133142
}
134143

135144
@Override
@@ -386,6 +395,12 @@ private void executeAgent(
386395
List<ModelTensor> modelTensors,
387396
ActionListener<Output> listener
388397
) {
398+
String mcpConnectorConfigJSON = (mlAgent.getParameters() != null) ? mlAgent.getParameters().get(MCP_CONNECTORS_FIELD) : null;
399+
if (mcpConnectorConfigJSON != null && !mcpFeatureIsEnabled) {
400+
// MCP connector provided as tools but MCP feature is disabled, so abort.
401+
listener.onFailure(new OpenSearchException(ML_COMMONS_MCP_FEATURE_DISABLED_MESSAGE));
402+
return;
403+
}
389404
MLAgentRunner mlAgentRunner = getAgentRunner(mlAgent);
390405
// If async is true, index ML task and return the taskID. Also add memoryID to the task if it exists
391406
if (isAsync) {

ml-algorithms/src/test/java/org/opensearch/ml/engine/algorithms/agent/MLAgentExecutorTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.HashMap;
2424
import java.util.List;
2525
import java.util.Map;
26+
import java.util.Set;
2627

2728
import javax.naming.Context;
2829

@@ -43,6 +44,7 @@
4344
import org.opensearch.cluster.metadata.Metadata;
4445
import org.opensearch.cluster.node.DiscoveryNode;
4546
import org.opensearch.cluster.service.ClusterService;
47+
import org.opensearch.common.settings.ClusterSettings;
4648
import org.opensearch.common.settings.Settings;
4749
import org.opensearch.common.util.concurrent.ThreadContext;
4850
import org.opensearch.common.xcontent.XContentFactory;
@@ -55,6 +57,7 @@
5557
import org.opensearch.core.xcontent.ToXContent;
5658
import org.opensearch.core.xcontent.XContentBuilder;
5759
import org.opensearch.index.get.GetResult;
60+
import org.opensearch.ml.common.CommonValue;
5861
import org.opensearch.ml.common.FunctionName;
5962
import org.opensearch.ml.common.MLAgentType;
6063
import org.opensearch.ml.common.agent.LLMSpec;
@@ -167,6 +170,9 @@ public void setup() {
167170
Mockito.when(memory.getMemoryManager()).thenReturn(memoryManager);
168171
when(client.threadPool()).thenReturn(threadPool);
169172
when(threadPool.getThreadContext()).thenReturn(threadContext);
173+
when(this.clusterService.getSettings()).thenReturn(settings);
174+
when(this.clusterService.getClusterSettings())
175+
.thenReturn(new ClusterSettings(settings, Set.of(CommonValue.ML_COMMONS_MCP_FEATURE_ENABLED)));
170176

171177
settings = Settings.builder().build();
172178
mlAgentExecutor = Mockito

plugin/src/main/java/org/opensearch/ml/action/agents/TransportRegisterAgentAction.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55

66
package org.opensearch.ml.action.agents;
77

8+
import static org.opensearch.ml.common.CommonValue.MCP_CONNECTORS_FIELD;
89
import static org.opensearch.ml.common.CommonValue.ML_AGENT_INDEX;
10+
import static org.opensearch.ml.common.CommonValue.ML_COMMONS_MCP_FEATURE_DISABLED_MESSAGE;
911

1012
import java.time.Instant;
1113
import java.util.HashMap;
@@ -21,6 +23,7 @@
2123
import org.opensearch.common.util.concurrent.ThreadContext;
2224
import org.opensearch.commons.authuser.User;
2325
import org.opensearch.core.action.ActionListener;
26+
import org.opensearch.ml.common.CommonValue;
2427
import org.opensearch.ml.common.MLAgentType;
2528
import org.opensearch.ml.common.agent.MLAgent;
2629
import org.opensearch.ml.common.transport.agent.MLRegisterAgentAction;
@@ -48,6 +51,7 @@ public class TransportRegisterAgentAction extends HandledTransportAction<ActionR
4851
ClusterService clusterService;
4952

5053
private final MLFeatureEnabledSetting mlFeatureEnabledSetting;
54+
private volatile boolean mcpFeatureIsEnabled;
5155

5256
@Inject
5357
public TransportRegisterAgentAction(
@@ -65,6 +69,10 @@ public TransportRegisterAgentAction(
6569
this.mlIndicesHandler = mlIndicesHandler;
6670
this.clusterService = clusterService;
6771
this.mlFeatureEnabledSetting = mlFeatureEnabledSetting;
72+
this.mcpFeatureIsEnabled = CommonValue.ML_COMMONS_MCP_FEATURE_ENABLED.get(clusterService.getSettings());
73+
clusterService
74+
.getClusterSettings()
75+
.addSettingsUpdateConsumer(CommonValue.ML_COMMONS_MCP_FEATURE_ENABLED, it -> mcpFeatureIsEnabled = it);
6876
}
6977

7078
@Override
@@ -76,6 +84,12 @@ protected void doExecute(Task task, ActionRequest request, ActionListener<MLRegi
7684
}
7785

7886
private void registerAgent(MLAgent agent, ActionListener<MLRegisterAgentResponse> listener) {
87+
String mcpConnectorConfigJSON = (agent.getParameters() != null) ? agent.getParameters().get(MCP_CONNECTORS_FIELD) : null;
88+
if (mcpConnectorConfigJSON != null && !mcpFeatureIsEnabled) {
89+
// MCP connector provided as tools but MCP feature is disabled, so abort.
90+
listener.onFailure(new OpenSearchException(ML_COMMONS_MCP_FEATURE_DISABLED_MESSAGE));
91+
return;
92+
}
7993
Instant now = Instant.now();
8094
boolean isHiddenAgent = RestActionUtils.isSuperAdminUser(clusterService, client);
8195
MLAgent mlAgent = agent.toBuilder().createdTime(now).lastUpdateTime(now).isHidden(isHiddenAgent).build();

plugin/src/main/java/org/opensearch/ml/action/connector/TransportCreateConnectorAction.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package org.opensearch.ml.action.connector;
77

8+
import static org.opensearch.ml.common.CommonValue.ML_COMMONS_MCP_FEATURE_DISABLED_MESSAGE;
89
import static org.opensearch.ml.common.CommonValue.ML_CONNECTOR_INDEX;
910
import static org.opensearch.ml.settings.MLCommonsSettings.ML_COMMONS_TRUSTED_CONNECTOR_ENDPOINTS_REGEX;
1011

@@ -13,6 +14,7 @@
1314
import java.util.HashSet;
1415
import java.util.List;
1516

17+
import org.opensearch.OpenSearchException;
1618
import org.opensearch.action.ActionRequest;
1719
import org.opensearch.action.index.IndexResponse;
1820
import org.opensearch.action.support.ActionFilters;
@@ -28,7 +30,9 @@
2830
import org.opensearch.core.xcontent.ToXContent;
2931
import org.opensearch.core.xcontent.XContentBuilder;
3032
import org.opensearch.ml.common.AccessMode;
33+
import org.opensearch.ml.common.CommonValue;
3134
import org.opensearch.ml.common.connector.Connector;
35+
import org.opensearch.ml.common.connector.ConnectorProtocols;
3236
import org.opensearch.ml.common.transport.connector.MLCreateConnectorAction;
3337
import org.opensearch.ml.common.transport.connector.MLCreateConnectorInput;
3438
import org.opensearch.ml.common.transport.connector.MLCreateConnectorRequest;
@@ -63,6 +67,8 @@ public class TransportCreateConnectorAction extends HandledTransportAction<Actio
6367

6468
private volatile List<String> trustedConnectorEndpointsRegex;
6569

70+
private volatile boolean mcpFeatureIsEnabled;
71+
6672
@Inject
6773
public TransportCreateConnectorAction(
6874
TransportService transportService,
@@ -89,12 +95,23 @@ public TransportCreateConnectorAction(
8995
clusterService
9096
.getClusterSettings()
9197
.addSettingsUpdateConsumer(ML_COMMONS_TRUSTED_CONNECTOR_ENDPOINTS_REGEX, it -> trustedConnectorEndpointsRegex = it);
98+
this.mcpFeatureIsEnabled = CommonValue.ML_COMMONS_MCP_FEATURE_ENABLED.get(clusterService.getSettings());
99+
clusterService
100+
.getClusterSettings()
101+
.addSettingsUpdateConsumer(CommonValue.ML_COMMONS_MCP_FEATURE_ENABLED, it -> mcpFeatureIsEnabled = it);
92102
}
93103

94104
@Override
95105
protected void doExecute(Task task, ActionRequest request, ActionListener<MLCreateConnectorResponse> listener) {
96106
MLCreateConnectorRequest mlCreateConnectorRequest = MLCreateConnectorRequest.fromActionRequest(request);
97107
MLCreateConnectorInput mlCreateConnectorInput = mlCreateConnectorRequest.getMlCreateConnectorInput();
108+
if (mlCreateConnectorInput.getProtocol() != null
109+
&& mlCreateConnectorInput.getProtocol().equals(ConnectorProtocols.MCP_SSE)
110+
&& !this.mcpFeatureIsEnabled) {
111+
// MCP connector provided but MCP feature is disabled, so abort.
112+
listener.onFailure(new OpenSearchException(ML_COMMONS_MCP_FEATURE_DISABLED_MESSAGE));
113+
return;
114+
}
98115
if (!TenantAwareHelper.validateTenantId(mlFeatureEnabledSetting, mlCreateConnectorInput.getTenantId(), listener)) {
99116
return;
100117
}

plugin/src/main/java/org/opensearch/ml/plugin/MachineLearningPlugin.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1054,7 +1054,8 @@ public List<Setting<?>> getSettings() {
10541054
MLCommonsSettings.REMOTE_METADATA_TYPE,
10551055
MLCommonsSettings.REMOTE_METADATA_ENDPOINT,
10561056
MLCommonsSettings.REMOTE_METADATA_REGION,
1057-
MLCommonsSettings.REMOTE_METADATA_SERVICE_NAME
1057+
MLCommonsSettings.REMOTE_METADATA_SERVICE_NAME,
1058+
MLCommonsSettings.ML_COMMONS_MCP_FEATURE_ENABLED
10581059
);
10591060
return settings;
10601061
}

plugin/src/main/java/org/opensearch/ml/settings/MLCommonsSettings.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.opensearch.common.settings.Setting;
1717
import org.opensearch.core.common.unit.ByteSizeUnit;
1818
import org.opensearch.core.common.unit.ByteSizeValue;
19+
import org.opensearch.ml.common.CommonValue;
1920
import org.opensearch.ml.common.conversation.ConversationalIndexConstants;
2021
import org.opensearch.searchpipelines.questionanswering.generative.GenerativeQAProcessorConstants;
2122

@@ -216,6 +217,8 @@ private MLCommonsSettings() {}
216217

217218
public static final Setting<Boolean> ML_COMMONS_MEMORY_FEATURE_ENABLED = ConversationalIndexConstants.ML_COMMONS_MEMORY_FEATURE_ENABLED;
218219

220+
public static final Setting<Boolean> ML_COMMONS_MCP_FEATURE_ENABLED = CommonValue.ML_COMMONS_MCP_FEATURE_ENABLED;
221+
219222
// Feature flag for enabling search processors for Retrieval Augmented Generation using OpenSearch and Remote Inference.
220223
public static final Setting<Boolean> ML_COMMONS_RAG_PIPELINE_FEATURE_ENABLED =
221224
GenerativeQAProcessorConstants.RAG_PIPELINE_FEATURE_ENABLED;

plugin/src/test/java/org/opensearch/ml/action/agents/RegisterAgentTransportActionTests.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.io.IOException;
1616
import java.util.Collections;
1717
import java.util.HashMap;
18+
import java.util.Set;
1819

1920
import org.junit.Before;
2021
import org.junit.Test;
@@ -25,12 +26,14 @@
2526
import org.opensearch.action.index.IndexResponse;
2627
import org.opensearch.action.support.ActionFilters;
2728
import org.opensearch.cluster.service.ClusterService;
29+
import org.opensearch.common.settings.ClusterSettings;
2830
import org.opensearch.common.settings.Settings;
2931
import org.opensearch.common.util.concurrent.ThreadContext;
3032
import org.opensearch.commons.ConfigConstants;
3133
import org.opensearch.core.action.ActionListener;
3234
import org.opensearch.core.index.shard.ShardId;
3335
import org.opensearch.core.xcontent.NamedXContentRegistry;
36+
import org.opensearch.ml.common.CommonValue;
3437
import org.opensearch.ml.common.MLAgentType;
3538
import org.opensearch.ml.common.agent.LLMSpec;
3639
import org.opensearch.ml.common.agent.MLAgent;
@@ -95,6 +98,8 @@ public void setup() throws IOException {
9598
when(client.threadPool()).thenReturn(threadPool);
9699
when(threadPool.getThreadContext()).thenReturn(threadContext);
97100
when(clusterService.getSettings()).thenReturn(settings);
101+
when(this.clusterService.getClusterSettings())
102+
.thenReturn(new ClusterSettings(settings, Set.of(CommonValue.ML_COMMONS_MCP_FEATURE_ENABLED)));
98103
transportRegisterAgentAction = new TransportRegisterAgentAction(
99104
transportService,
100105
actionFilters,

plugin/src/test/java/org/opensearch/ml/action/connector/TransportCreateConnectorActionTests.java

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import static org.mockito.Mockito.mock;
1111
import static org.mockito.Mockito.verify;
1212
import static org.mockito.Mockito.when;
13+
import static org.opensearch.ml.common.CommonValue.ML_COMMONS_MCP_FEATURE_DISABLED_MESSAGE;
1314
import static org.opensearch.ml.common.CommonValue.ML_CONNECTOR_INDEX;
1415
import static org.opensearch.ml.settings.MLCommonsSettings.ML_COMMONS_CONNECTOR_ACCESS_CONTROL_ENABLED;
1516
import static org.opensearch.ml.settings.MLCommonsSettings.ML_COMMONS_TRUSTED_CONNECTOR_ENDPOINTS_REGEX;
@@ -27,6 +28,7 @@
2728
import org.mockito.Captor;
2829
import org.mockito.Mock;
2930
import org.mockito.MockitoAnnotations;
31+
import org.opensearch.OpenSearchException;
3032
import org.opensearch.OpenSearchStatusException;
3133
import org.opensearch.action.index.IndexRequest;
3234
import org.opensearch.action.index.IndexResponse;
@@ -41,6 +43,7 @@
4143
import org.opensearch.core.index.shard.ShardId;
4244
import org.opensearch.core.xcontent.NamedXContentRegistry;
4345
import org.opensearch.ml.common.AccessMode;
46+
import org.opensearch.ml.common.CommonValue;
4447
import org.opensearch.ml.common.connector.ConnectorAction;
4548
import org.opensearch.ml.common.connector.ConnectorProtocols;
4649
import org.opensearch.ml.common.transport.connector.MLCreateConnectorInput;
@@ -141,11 +144,13 @@ public void setup() {
141144
ClusterSettings clusterSettings = clusterSetting(
142145
settings,
143146
ML_COMMONS_TRUSTED_CONNECTOR_ENDPOINTS_REGEX,
144-
ML_COMMONS_CONNECTOR_ACCESS_CONTROL_ENABLED
147+
ML_COMMONS_CONNECTOR_ACCESS_CONTROL_ENABLED,
148+
CommonValue.ML_COMMONS_MCP_FEATURE_ENABLED
145149
);
146150
when(clusterService.getClusterSettings()).thenReturn(clusterSettings);
147151

148152
when(mlFeatureEnabledSetting.isMultiTenancyEnabled()).thenReturn(false);
153+
when(this.clusterService.getSettings()).thenReturn(settings);
149154

150155
action = new TransportCreateConnectorAction(
151156
transportService,
@@ -596,6 +601,47 @@ public void test_connector_creation_success_deepseek() {
596601
verify(actionListener).onResponse(any(MLCreateConnectorResponse.class));
597602
}
598603

604+
public void test_mcp_connector_creation_fail_default() {
605+
TransportCreateConnectorAction action = new TransportCreateConnectorAction(
606+
transportService,
607+
actionFilters,
608+
mlIndicesHandler,
609+
client,
610+
sdkClient,
611+
mlEngine,
612+
connectorAccessControlHelper,
613+
settings,
614+
clusterService,
615+
mlModelManager,
616+
mlFeatureEnabledSetting
617+
);
618+
doAnswer(invocation -> {
619+
ActionListener<Boolean> listener = invocation.getArgument(0);
620+
listener.onResponse(true);
621+
return null;
622+
}).when(mlIndicesHandler).initMLConnectorIndex(isA(ActionListener.class));
623+
doAnswer(invocation -> {
624+
ActionListener<IndexResponse> listener = invocation.getArgument(1);
625+
listener.onResponse(indexResponse);
626+
return null;
627+
}).when(client).index(any(IndexRequest.class), isA(ActionListener.class));
628+
629+
Map<String, String> credential = ImmutableMap.of("access_key", "mockKey", "secret_key", "mockSecret");
630+
MLCreateConnectorInput mlCreateConnectorInput = MLCreateConnectorInput
631+
.builder()
632+
.name(randomAlphaOfLength(5))
633+
.description(randomAlphaOfLength(10))
634+
.version("1")
635+
.protocol(ConnectorProtocols.MCP_SSE)
636+
.credential(credential)
637+
.build();
638+
MLCreateConnectorRequest request = new MLCreateConnectorRequest(mlCreateConnectorInput);
639+
action.doExecute(task, request, actionListener);
640+
ArgumentCaptor<OpenSearchException> argCaptor = ArgumentCaptor.forClass(OpenSearchException.class);
641+
verify(actionListener).onFailure(argCaptor.capture());
642+
assertEquals(argCaptor.getValue().getMessage(), ML_COMMONS_MCP_FEATURE_DISABLED_MESSAGE);
643+
}
644+
599645
public void test_connector_creation_success_rekognition() {
600646
TransportCreateConnectorAction action = new TransportCreateConnectorAction(
601647
transportService,

0 commit comments

Comments
 (0)