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-whiteboard.git
The following commit(s) were added to refs/heads/master by this push:
new 62743eb2 feat(mcp-server): various improvements
62743eb2 is described below
commit 62743eb2b440f081442dfca06bc00db9de2b6875
Author: Robert Munteanu <[email protected]>
AuthorDate: Tue Dec 9 11:43:36 2025 +0100
feat(mcp-server): various improvements
- add empty completions for the new-sling-servlet prompt to remove errors
in the MCP inspector
about missing completions
- make the name/version/instructions for the MCP configurable and provide
sensible defaults
---
.../apache/sling/mcp/server/impl/McpServlet.java | 44 +++++++++++++++++++---
1 file changed, 38 insertions(+), 6 deletions(-)
diff --git
a/mcp-server/src/main/java/org/apache/sling/mcp/server/impl/McpServlet.java
b/mcp-server/src/main/java/org/apache/sling/mcp/server/impl/McpServlet.java
index 3f62a10a..b12faa6b 100644
--- a/mcp-server/src/main/java/org/apache/sling/mcp/server/impl/McpServlet.java
+++ b/mcp-server/src/main/java/org/apache/sling/mcp/server/impl/McpServlet.java
@@ -33,18 +33,19 @@ import
io.modelcontextprotocol.json.jackson.JacksonMcpJsonMapper;
import io.modelcontextprotocol.json.schema.jackson.DefaultJsonSchemaValidator;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.McpStatelessServerFeatures;
+import
io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncCompletionSpecification;
import
io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncPromptSpecification;
import
io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncToolSpecification;
import io.modelcontextprotocol.server.McpStatelessSyncServer;
import
io.modelcontextprotocol.server.transport.HttpServletStatelessServerTransport;
import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpSchema.CallToolResult;
+import
io.modelcontextprotocol.spec.McpSchema.CompleteResult.CompleteCompletion;
import io.modelcontextprotocol.spec.McpSchema.Prompt;
import io.modelcontextprotocol.spec.McpSchema.PromptArgument;
import io.modelcontextprotocol.spec.McpSchema.PromptMessage;
import io.modelcontextprotocol.spec.McpSchema.ReadResourceResult;
import io.modelcontextprotocol.spec.McpSchema.Resource;
-import io.modelcontextprotocol.spec.McpSchema.ResourceContents;
import io.modelcontextprotocol.spec.McpSchema.ResourceTemplate;
import io.modelcontextprotocol.spec.McpSchema.Role;
import io.modelcontextprotocol.spec.McpSchema.ServerCapabilities;
@@ -65,11 +66,30 @@ import org.osgi.framework.wiring.FrameworkWiring;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
@Component(service = Servlet.class)
@SlingServletPaths(value = {McpServlet.ENDPOINT})
+@Designate(ocd = McpServlet.Config.class)
public class McpServlet extends SlingJakartaAllMethodsServlet {
+ @ObjectClassDefinition(name = "Apache Sling MCP Server Configuration")
+ public @interface Config {
+ @AttributeDefinition(name = "Server Title", description = "The title
of the MCP server")
+ String serverTitle() default "Apache Sling";
+
+ @AttributeDefinition(
+ name = "Server Version",
+ description = "The version of the MCP server. Defaults to the
bundle version if not set")
+ String serverVersion();
+
+ @AttributeDefinition(name = "Instructions", description = "Initial
instructions for the MCP server")
+ String instructions() default
+ "This MCP server provides access to an Apache Sling
development instance. Exposed tools and information always reference the Sling
deployment and not local projects or files";
+ }
+
static final String ENDPOINT = "/bin/mcp";
private static final long serialVersionUID = 1L;
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
@@ -92,7 +112,7 @@ public class McpServlet extends
SlingJakartaAllMethodsServlet {
}
@Activate
- public McpServlet(BundleContext ctx) throws IllegalAccessException,
NoSuchMethodException {
+ public McpServlet(BundleContext ctx, Config config) throws
IllegalAccessException, NoSuchMethodException {
McpJsonMapper jsonMapper = new JacksonMcpJsonMapper(new
ObjectMapper());
@@ -115,14 +135,26 @@ public class McpServlet extends
SlingJakartaAllMethodsServlet {
java.lang.invoke.MethodType.methodType(
void.class, HttpServletRequest.class,
HttpServletResponse.class));
+ SyncCompletionSpecification servletCompletionSpec = new
McpStatelessServerFeatures.SyncCompletionSpecification(
+ new McpSchema.PromptReference("ref/prompt",
"new-sling-servlet"), (context, request) -> {
+ return new McpSchema.CompleteResult(new
CompleteCompletion(List.of(), 0, false));
+ });
+
+ String serverVersion = config.serverVersion();
+ if (serverVersion == null || serverVersion.isEmpty()) {
+ serverVersion = ctx.getBundle().getVersion().toString();
+ }
syncServer = McpServer.sync(transportProvider)
- .serverInfo("apache-sling", "0.1.0")
+ .serverInfo(config.serverTitle(), serverVersion)
.jsonMapper(jsonMapper)
.jsonSchemaValidator(new DefaultJsonSchemaValidator())
+ .instructions(config.instructions())
+ .completions(List.of(servletCompletionSpec))
.capabilities(ServerCapabilities.builder()
- .tools(true)
- .prompts(true)
- .resources(true, true)
+ .tools(false)
+ .prompts(false)
+ .resources(false, false)
+ .completions()
.build())
.build();