This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to branch master
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-mcp-server.git
The following commit(s) were added to refs/heads/master by this push:
new 9b9cc46 fix: work around issue in recent Cursor versions that
prevents MCP server registration (#1)
9b9cc46 is described below
commit 9b9cc467ad8ffc9855c079e0c089fd5a6972cae6
Author: Robert Munteanu <[email protected]>
AuthorDate: Fri Feb 6 22:50:27 2026 +0100
fix: work around issue in recent Cursor versions that prevents MCP server
registration (#1)
Cursor tries to register for resource updates even if we don't advertise
that capability. This
causes an internal error to be returned and blocks the MCP server
activation.
We work around it by using reflection to register a no-op handler, which
seems to make
Cursor happy.
---
.../apache/sling/mcp/server/impl/McpServlet.java | 32 ++++++++++++++++++++++
1 file changed, 32 insertions(+)
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 a7ae71b..643265c 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
@@ -28,7 +28,9 @@ import io.modelcontextprotocol.common.McpTransportContext;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.json.schema.jackson.DefaultJsonSchemaValidator;
import io.modelcontextprotocol.server.McpServer;
+import io.modelcontextprotocol.server.McpStatelessRequestHandler;
import
io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncPromptSpecification;
+import io.modelcontextprotocol.server.McpStatelessServerHandler;
import io.modelcontextprotocol.server.McpStatelessSyncServer;
import
io.modelcontextprotocol.server.transport.HttpServletStatelessServerTransport;
import io.modelcontextprotocol.spec.McpSchema;
@@ -52,6 +54,9 @@ import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import reactor.core.publisher.Mono;
import static
org.osgi.service.component.annotations.ReferenceCardinality.MULTIPLE;
import static
org.osgi.service.component.annotations.ReferencePolicyOption.GREEDY;
@@ -80,6 +85,7 @@ public class McpServlet extends SlingJakartaAllMethodsServlet
{
private static final long serialVersionUID = 1L;
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+ private final Logger logger = LoggerFactory.getLogger(getClass());
private McpStatelessSyncServer syncServer;
private HttpServletStatelessServerTransport transportProvider;
private MethodHandle doGetMethod;
@@ -138,6 +144,10 @@ public class McpServlet extends
SlingJakartaAllMethodsServlet {
.build())
.build();
+ // workaround for
https://github.com/modelcontextprotocol/java-sdk/issues/776
+ // cursor tries to register for resource updates even if we don't
advertise that capability
+ tryRegisterNoopResourcesSubscribeHandler();
+
contributions.stream()
.map(McpServerContribution::getSyncToolSpecification)
.flatMap(List::stream)
@@ -159,6 +169,28 @@ public class McpServlet extends
SlingJakartaAllMethodsServlet {
.forEach(syncPrompt -> syncServer.addPrompt(syncPrompt));
}
+ private void tryRegisterNoopResourcesSubscribeHandler() {
+ try {
+ MethodHandles.Lookup transportLookup =
+
MethodHandles.privateLookupIn(HttpServletStatelessServerTransport.class,
LOOKUP);
+ MethodHandle mcpHandlerGetter = transportLookup.findGetter(
+ HttpServletStatelessServerTransport.class, "mcpHandler",
McpStatelessServerHandler.class);
+ Object mcpHandler = mcpHandlerGetter.invoke(transportProvider);
+
+ Class<?> handlerClass = mcpHandler.getClass();
+ MethodHandles.Lookup handlerLookup =
MethodHandles.privateLookupIn(handlerClass, LOOKUP);
+ MethodHandle requestHandlersGetter =
handlerLookup.findGetter(handlerClass, "requestHandlers", Map.class);
+ Map<String, McpStatelessRequestHandler<?>> handlers =
+ (Map<String, McpStatelessRequestHandler<?>>)
requestHandlersGetter.invoke(mcpHandler);
+
+ handlers.put(McpSchema.METHOD_RESOURCES_SUBSCRIBE, (context,
params) -> Mono.just(Map.of()));
+ } catch (Throwable t) {
+ logger.warn(
+ "Failed to register MCP resources subscribe handler,
non-compliant clients requesting resource updates might fail",
+ t);
+ }
+ }
+
@Reference(policy = ReferencePolicy.DYNAMIC, policyOption = GREEDY,
cardinality = MULTIPLE)
protected void bindPrompt(DiscoveredPrompt prompt, Map<String, Object>
properties) {
syncServer.addPrompt(new SyncPromptSpecification(prompt.asPrompt(),
(c, r) -> {