Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 9 additions & 0 deletions api/src/org/labkey/api/mcp/AbstractAgentAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,18 @@ protected String handleEscape(String prompt)
@Override
public void validateForm(F form, Errors errors)
{
if (!McpService.get().isAIFeaturesEnabled())
{
errors.reject(ERROR_GENERIC, "Agent actions are not available.");
return;
}

String prompt = form.getPrompt();
if (prompt != null && prompt.length() > MAX_PROMPT_CHAR_LENGTH)
{
errors.rejectValue("prompt", ERROR_GENERIC, "Prompt cannot exceed " + MAX_PROMPT_CHAR_LENGTH + " characters.");
return;
}

// Only honor a client-supplied conversationId if this agent previously issued this session that
// id. Otherwise, generate a fresh one. This prevents a same-session caller from splicing into
Expand Down
15 changes: 12 additions & 3 deletions api/src/org/labkey/api/mcp/McpService.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ public interface McpService extends ToolCallbackProvider

Logger LOG = LogHelper.getLogger(McpService.class, "MCP registration exceptions");
String ENABLE_MCP_SERVER_FLAG = "enableMcpServer";
String ENABLE_AI_FEATURES = "enableAIFeatures";

// Interface for MCP classes that we will "ingest" using Spring annotations. Provides a few helper methods.
interface McpImpl
Expand All @@ -120,9 +121,6 @@ default User getUser(ToolContext toolContext)
// Every MCP resource should call this on every invocation
default void incrementResourceRequestCount(String resource)
{
if (!get().isEnabled())
throw new RuntimeException("The MCP server is not enabled for external requests. Consider toggling the optional feature flag.");

get().incrementResourceRequestCount(resource);
}
}
Expand All @@ -145,8 +143,19 @@ default boolean isEnabled()
return OptionalFeatureService.get().isFeatureEnabled(ENABLE_MCP_SERVER_FLAG);
}

default boolean isAIFeaturesEnabled()
{
return OptionalFeatureService.get().isFeatureEnabled(ENABLE_AI_FEATURES);
}

boolean isReady();

// Convenience for in-product AI features: the AI feature flag is on AND the service has started.
default boolean isAIFeaturesReady()
{
return isAIFeaturesEnabled() && isReady();
}

// Register MCPs in Module.startup()
default void register(McpImpl mcp)
{
Expand Down
6 changes: 6 additions & 0 deletions api/src/org/labkey/api/mcp/NoopMcpService.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ public boolean isEnabled()
return false;
}

@Override
public boolean isAIFeaturesEnabled()
{
return false;
}

@Override
public boolean isReady()
{
Expand Down
3 changes: 1 addition & 2 deletions api/src/org/labkey/api/util/PageFlowUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -2265,8 +2265,7 @@ public static JSONObject jsInitObject(ContainerUser context, @Nullable PageConfi
if (AppProps.getInstance().isOptionalFeatureEnabled(NotificationMenuView.EXPERIMENTAL_NOTIFICATION_MENU) && user != null)
json.put("notifications", Map.of("unreadCount", NotificationService.get().getUnreadNotificationCountByUser(null, user.getUserId())));

if (McpService.get().isEnabled())
json.put("mcpReady", McpService.get().isReady());
json.put("mcpReady", McpService.get().isAIFeaturesReady());

JSONObject defaultHeaders = new JSONObject();
defaultHeaders.put("X-ONUNAUTHORIZED", "UNAUTHORIZED");
Expand Down
4 changes: 2 additions & 2 deletions core/src/org/labkey/core/admin/sql/SqlScriptController.java
Original file line number Diff line number Diff line change
Expand Up @@ -1122,7 +1122,7 @@ protected void renderScript(SqlScript script, PrintWriter out)
protected void renderButtons(SqlScript script, PrintWriter out)
{
out.println(PageFlowUtil.button("Reorder Script").href(getScriptURL(ReorderScriptAction.class, script)));
if (McpService.get().isReady())
if (McpService.get().isAIFeaturesReady())
{
out.println(
PageFlowUtil.button("Clean Up Script")
Expand Down Expand Up @@ -1259,7 +1259,7 @@ protected abstract class BaseAIScriptAction extends ScriptAction
protected ModelAndView getScriptView(SqlScript script)
{
McpService mcpService = McpService.get();
if (mcpService.isReady())
if (mcpService.isAIFeaturesReady())
{
String prompt = getPrompt(DbScope.getLabKeyScope().getSqlDialect(), script);
HttpSession session = getViewContext().getSession();
Expand Down
2 changes: 1 addition & 1 deletion devtools/src/org/labkey/devtools/TestController.java
Original file line number Diff line number Diff line change
Expand Up @@ -1285,7 +1285,7 @@ public static class ChatAction extends SimpleViewAction<Object>
@Override
public ModelAndView getView(Object o, BindException errors)
{
if (null == McpService.get() || !McpService.get().isReady())
if (null == McpService.get() || !McpService.get().isAIFeaturesReady())
return HtmlView.of("Service is not ready yet.");
getPageConfig().setTemplate(PageConfig.Template.Dialog);
return new JspView<>("/org/labkey/devtools/view/chat.jsp");
Expand Down
6 changes: 1 addition & 5 deletions devtools/src/org/labkey/devtools/view/chat.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@
* limitations under the License.
*/
%>
<%@ page import="org.labkey.api.util.DOM" %>
<%@ page import="java.util.stream.Stream" %>
<%@ page import="static org.labkey.api.util.DOM.*" %>
<%@ page import="static org.labkey.api.util.DOM.Attribute.*" %>
<%@ page extends="org.labkey.api.jsp.JspBase" %>
<%@ taglib prefix="labkey" uri="http://www.labkey.org/taglib" %>
<style type="text/css">
Expand All @@ -30,7 +26,7 @@
border-radius: 15px;
border : solid 1px darkgray;
display: flex;
align-items: center; */
align-items: center;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

Expand Down
2 changes: 1 addition & 1 deletion query/src/org/labkey/query/view/sourceQuery.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
boolean canEdit = queryDef.canEdit(getUser());
boolean canEditMetadata = queryDef.canEditMetadata(getUser());
boolean canDelete = queryDef.canDelete(getUser());
boolean isChatReady = canEdit && McpService.get().isReady();
boolean isChatReady = canEdit && McpService.get().isAIFeaturesReady();
%>
<style type="text/css">

Expand Down