This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch issue/admin-access in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-mcp-server.git
commit 52677036c67787afae17474fbfc16ba153f1fb2e Author: Robert Munteanu <[email protected]> AuthorDate: Fri Mar 13 14:09:36 2026 +0100 fix: require admin access for McpServlet --- README.md | 16 ++++++++++- pom.xml | 5 ++++ .../apache/sling/mcp/server/impl/McpServlet.java | 33 ++++++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b189d5d..ed82a21 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,21 @@ Then build and deploy the [MCP server contributions bundle from the Sling Whiteb $ mvn -f whiteboard/mcp-server-contributions/ install sling:install ``` -Then open up your coding assistant tool and add an remote MCP server with location http://localhost:8080/mcp . +Then open up your coding assistant tool and add an remote MCP server with location http://localhost:8080/mcp . Access is only +permitted for the `admin` user therefore basic authentication headers need to be specified. In case of the default credentials +the configuration can look as follows + +```json +"aem-cs-sdk": { + "type": "streamable-http", + "url": "http://localhost:4502/bin/mcp", + "headers": { + "Authorization": "Basic YWRtaW46YWRtaW4=" + } +} +``` + +Please refer to the documentation of your coding assistant tool for details on how to add a remote MCP server and specify authentication headers. ## Legacy artifact diff --git a/pom.xml b/pom.xml index be655a9..c76aa7b 100644 --- a/pom.xml +++ b/pom.xml @@ -121,6 +121,11 @@ <artifactId>jakarta.servlet-api</artifactId> <scope>compile</scope> </dependency> + <dependency> + <groupId>org.apache.jackrabbit</groupId> + <artifactId>oak-jackrabbit-api</artifactId> + <scope>provided</scope> + </dependency> <dependency> <groupId>org.apache.felix</groupId> <artifactId>org.apache.felix.http.wrappers</artifactId> diff --git a/src/main/java/org/apache/sling/mcp/server/impl/McpServlet.java b/src/main/java/org/apache/sling/mcp/server/impl/McpServlet.java index d3a68d0..2cdfc72 100644 --- a/src/main/java/org/apache/sling/mcp/server/impl/McpServlet.java +++ b/src/main/java/org/apache/sling/mcp/server/impl/McpServlet.java @@ -18,8 +18,11 @@ */ package org.apache.sling.mcp.server.impl; +import javax.jcr.RepositoryException; +import javax.jcr.Session; import javax.servlet.Servlet; import javax.servlet.ServletException; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.invoke.MethodHandle; @@ -40,6 +43,8 @@ import io.modelcontextprotocol.spec.McpSchema; import io.modelcontextprotocol.spec.McpSchema.ServerCapabilities; import org.apache.felix.http.jakartawrappers.HttpServletRequestWrapper; import org.apache.felix.http.jakartawrappers.HttpServletResponseWrapper; +import org.apache.jackrabbit.api.JackrabbitSession; +import org.apache.jackrabbit.api.security.user.User; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.SlingHttpServletResponse; import org.apache.sling.api.servlets.SlingAllMethodsServlet; @@ -218,6 +223,13 @@ public class McpServlet extends SlingAllMethodsServlet { @Override protected void doGet(@NotNull SlingHttpServletRequest request, @NotNull SlingHttpServletResponse response) throws ServletException, IOException { + + User user = getCurrentUser(request); + if (user == null || !user.isAdmin()) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied"); + return; + } + try { doGetMethod.invoke( transportProvider, @@ -230,9 +242,30 @@ public class McpServlet extends SlingAllMethodsServlet { } } + protected User getCurrentUser(SlingHttpServletRequest request) { + if (request.getResourceResolver().adaptTo(Session.class) instanceof JackrabbitSession jcrSession) { + + String userId = jcrSession.getUserID(); + + try { + return jcrSession.getUserManager().getAuthorizable(userId, User.class); + } catch (RepositoryException e) { + logger.warn("Failed to retrieve user for ID {}, access will be denied", userId, e); + } + } + return null; + } + @Override protected void doPost(@NotNull SlingHttpServletRequest request, @NotNull SlingHttpServletResponse response) throws ServletException, IOException { + + User user = getCurrentUser(request); + if (user == null || !user.isAdmin()) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied"); + return; + } + try { doPostMethod.invoke( transportProvider,
