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
commit 234099621ea2124b9f435196c71f053915c0b29c Author: Robert Munteanu <[email protected]> AuthorDate: Fri Dec 12 14:51:36 2025 +0100 feat(mcp): register templates from the repository Still need to add support for parameters --- pom.xml | 12 +++++++++ src/main/features/main.json | 10 ++++++- .../sling/mcp/server/impl/DiscoveredPrompt.java | 2 ++ .../apache/sling/mcp/server/impl/McpServlet.java | 13 +++++---- .../impl/contribs/RepositoryPromptsRegistrar.java | 31 ++++++++++++++++++++-- .../libs/sling/mcp/prompts/troubleshoot.md | 4 +++ 6 files changed, 64 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index edca093..d90ecce 100644 --- a/pom.xml +++ b/pom.xml @@ -111,6 +111,18 @@ <version>1.3.0</version> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.commonmark</groupId> + <artifactId>commonmark</artifactId> + <version>0.27.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.commonmark</groupId> + <artifactId>commonmark-ext-yaml-front-matter</artifactId> + <version>0.27.0</version> + <scope>provided</scope> + </dependency> </dependencies> <build> diff --git a/src/main/features/main.json b/src/main/features/main.json index 656a96b..ffae06a 100644 --- a/src/main/features/main.json +++ b/src/main/features/main.json @@ -31,7 +31,15 @@ { "id": "org.yaml:snakeyaml:2.3", "start-order": 25 - } + }, + { + "id": "org.commonmark:commonmark:0.27.0", + "start-order": 25 + }, + { + "id": "org.commonmark:commonmark-ext-yaml-front-matter:0.27.0", + "start-order": 25 + } ], "configurations": { "org.apache.sling.jcr.base.internal.LoginAdminWhitelist.fragment~mcp-server":{ diff --git a/src/main/java/org/apache/sling/mcp/server/impl/DiscoveredPrompt.java b/src/main/java/org/apache/sling/mcp/server/impl/DiscoveredPrompt.java index 6a52ce5..ad64197 100644 --- a/src/main/java/org/apache/sling/mcp/server/impl/DiscoveredPrompt.java +++ b/src/main/java/org/apache/sling/mcp/server/impl/DiscoveredPrompt.java @@ -26,6 +26,8 @@ import org.apache.sling.api.resource.ResourceResolver; public interface DiscoveredPrompt { public static final String SERVICE_PROP_NAME = "mcp.prompt.name"; + public static final String SERVICE_PROP_TITLE = "mcp.prompt.title"; + public static final String SERVICE_PROP_DESCRIPTION = "mcp.prompt.description"; List<PromptMessage> getPromptMessages(ResourceResolver resolver); } 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 ac708c6..8deb6dc 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 @@ -164,11 +164,14 @@ public class McpServlet extends SlingJakartaAllMethodsServlet { @Reference(policy = ReferencePolicy.DYNAMIC, policyOption = GREEDY, cardinality = MULTIPLE) protected void bindPrompt(DiscoveredPrompt prompt, Map<String, Object> properties) { String promptName = (String) properties.get(DiscoveredPrompt.SERVICE_PROP_NAME); - syncServer.addPrompt(new SyncPromptSpecification(new Prompt(promptName, null, List.of()), (c, r) -> { - ResourceResolver resourceResolver = (ResourceResolver) c.get("resourceResolver"); - var messages = prompt.getPromptMessages(resourceResolver); - return new McpSchema.GetPromptResult(null, messages); - })); + String promptTitle = (String) properties.get(DiscoveredPrompt.SERVICE_PROP_TITLE); + String promptDescription = (String) properties.get(DiscoveredPrompt.SERVICE_PROP_DESCRIPTION); + syncServer.addPrompt(new SyncPromptSpecification( + new Prompt(promptName, promptTitle, promptDescription, List.of()), (c, r) -> { + ResourceResolver resourceResolver = (ResourceResolver) c.get("resourceResolver"); + var messages = prompt.getPromptMessages(resourceResolver); + return new McpSchema.GetPromptResult(null, messages); + })); } protected void unbindPrompt(Map<String, Object> properties) { diff --git a/src/main/java/org/apache/sling/mcp/server/impl/contribs/RepositoryPromptsRegistrar.java b/src/main/java/org/apache/sling/mcp/server/impl/contribs/RepositoryPromptsRegistrar.java index 990de0d..fe0e97e 100644 --- a/src/main/java/org/apache/sling/mcp/server/impl/contribs/RepositoryPromptsRegistrar.java +++ b/src/main/java/org/apache/sling/mcp/server/impl/contribs/RepositoryPromptsRegistrar.java @@ -21,7 +21,9 @@ package org.apache.sling.mcp.server.impl.contribs; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.List; @@ -40,6 +42,10 @@ import org.apache.sling.api.resource.observation.ResourceChange; import org.apache.sling.api.resource.observation.ResourceChange.ChangeType; import org.apache.sling.api.resource.observation.ResourceChangeListener; import org.apache.sling.mcp.server.impl.DiscoveredPrompt; +import org.commonmark.ext.front.matter.YamlFrontMatterExtension; +import org.commonmark.ext.front.matter.YamlFrontMatterVisitor; +import org.commonmark.node.Node; +import org.commonmark.parser.Parser; import org.jetbrains.annotations.NotNull; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; @@ -65,7 +71,6 @@ public class RepositoryPromptsRegistrar { @Override public void onChange(@NotNull List<ResourceChange> changes) { - changes.forEach(a -> logger.info("Received change {} at {}", a.getType(), a.getPath())); try (ResourceResolver resolver = rrf.getAdministrativeResourceResolver(null)) { for (ResourceChange change : changes) { @@ -125,7 +130,29 @@ public class RepositoryPromptsRegistrar { private void registerPrompt(BundleContext ctx, String promptName, Resource prompt) { - Map<String, String> serviceProps = Map.of(DiscoveredPrompt.SERVICE_PROP_NAME, promptName); + Map<String, String> serviceProps = new HashMap<>(Map.of(DiscoveredPrompt.SERVICE_PROP_NAME, promptName)); + + Parser parser = Parser.builder() + .extensions(List.of(YamlFrontMatterExtension.create())) + .build(); + String charset = prompt.getResourceMetadata().getCharacterEncoding(); + if (charset == null) { + charset = StandardCharsets.UTF_8.name(); + } + try (InputStream is = prompt.adaptTo(InputStream.class)) { + Node node = parser.parseReader(new InputStreamReader(is, charset)); + YamlFrontMatterVisitor visitor = new YamlFrontMatterVisitor(); + node.accept(visitor); + + visitor.getData().getOrDefault("title", List.of()).stream() + .findFirst() + .ifPresent(title -> serviceProps.put(DiscoveredPrompt.SERVICE_PROP_TITLE, title)); + visitor.getData().getOrDefault("description", List.of()).stream() + .findFirst() + .ifPresent(title -> serviceProps.put(DiscoveredPrompt.SERVICE_PROP_DESCRIPTION, title)); + } catch (IOException e) { + logger.error("Error reading prompt markdown file at {}", prompt.getPath(), e); + } // TODO - discover additional properties from the markdown file (front matter) diff --git a/src/main/resources/SLING-INF/libs/sling/mcp/prompts/troubleshoot.md b/src/main/resources/SLING-INF/libs/sling/mcp/prompts/troubleshoot.md index e60aed8..d5e9587 100644 --- a/src/main/resources/SLING-INF/libs/sling/mcp/prompts/troubleshoot.md +++ b/src/main/resources/SLING-INF/libs/sling/mcp/prompts/troubleshoot.md @@ -1,3 +1,7 @@ +--- +title: "Troubleshooting guide" +description: "Guide to troubleshoot common issues with Apache Sling applications" +--- # Troubleshooting Guide ## Overview
