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 128443db4e1fcd2f6203e28180b13a9512c9a79a
Author: Robert Munteanu <[email protected]>
AuthorDate: Fri Dec 12 17:03:33 2025 +0100

    feat(mcp): repository prompts support parameters defined in the front matter
---
 pom.xml                                            |  19 +++
 .../sling/mcp/server/impl/DiscoveredPrompt.java    |  10 +-
 .../apache/sling/mcp/server/impl/McpServlet.java   |  15 +-
 .../impl/contribs/DiscoveredPromptBuilder.java     | 160 +++++++++++++++++++++
 .../impl/contribs/RepositoryPromptsRegistrar.java  |  81 ++---------
 .../libs/sling/mcp/prompts/new-sling-servlet.md    |  17 +++
 .../impl/contribs/DiscoveredPromptBuilderTest.java | 129 +++++++++++++++++
 7 files changed, 346 insertions(+), 85 deletions(-)

diff --git a/pom.xml b/pom.xml
index d90ecce..919caad 100644
--- a/pom.xml
+++ b/pom.xml
@@ -123,6 +123,25 @@
             <version>0.27.0</version>
             <scope>provided</scope>
         </dependency>
+
+        <!-- test dependencies -->
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>5.20.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <version>3.27.6</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
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 ad64197..4e6e54f 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
@@ -20,14 +20,16 @@ package org.apache.sling.mcp.server.impl;
 
 import java.util.List;
 
+import io.modelcontextprotocol.common.McpTransportContext;
+import io.modelcontextprotocol.spec.McpSchema.GetPromptRequest;
+import io.modelcontextprotocol.spec.McpSchema.Prompt;
 import io.modelcontextprotocol.spec.McpSchema.PromptMessage;
-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);
+    List<PromptMessage> getPromptMessages(McpTransportContext c, 
GetPromptRequest r);
+
+    Prompt asPrompt();
 }
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 8deb6dc..06bb9c4 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
@@ -33,7 +33,6 @@ import 
io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncPromptSpeci
 import io.modelcontextprotocol.server.McpStatelessSyncServer;
 import 
io.modelcontextprotocol.server.transport.HttpServletStatelessServerTransport;
 import io.modelcontextprotocol.spec.McpSchema;
-import io.modelcontextprotocol.spec.McpSchema.Prompt;
 import io.modelcontextprotocol.spec.McpSchema.ServerCapabilities;
 import jakarta.servlet.Servlet;
 import jakarta.servlet.ServletException;
@@ -41,7 +40,6 @@ import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import org.apache.sling.api.SlingJakartaHttpServletRequest;
 import org.apache.sling.api.SlingJakartaHttpServletResponse;
-import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.servlets.SlingJakartaAllMethodsServlet;
 import org.apache.sling.servlets.annotations.SlingServletPaths;
 import org.jetbrains.annotations.NotNull;
@@ -163,15 +161,10 @@ 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);
-        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);
-                }));
+        syncServer.addPrompt(new SyncPromptSpecification(prompt.asPrompt(), 
(c, r) -> {
+            var messages = prompt.getPromptMessages(c, r);
+            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/DiscoveredPromptBuilder.java
 
b/src/main/java/org/apache/sling/mcp/server/impl/contribs/DiscoveredPromptBuilder.java
new file mode 100644
index 0000000..ca2f9a7
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/mcp/server/impl/contribs/DiscoveredPromptBuilder.java
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+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.ArrayList;
+import java.util.List;
+
+import io.modelcontextprotocol.common.McpTransportContext;
+import io.modelcontextprotocol.spec.McpSchema.GetPromptRequest;
+import io.modelcontextprotocol.spec.McpSchema.Prompt;
+import io.modelcontextprotocol.spec.McpSchema.PromptArgument;
+import io.modelcontextprotocol.spec.McpSchema.PromptMessage;
+import io.modelcontextprotocol.spec.McpSchema.Role;
+import io.modelcontextprotocol.spec.McpSchema.TextContent;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class DiscoveredPromptBuilder {
+
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    public DiscoveredPrompt buildPrompt(Resource prompt, String promptName) 
throws IOException {
+
+        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);
+
+            String title = visitor.getData().getOrDefault("title", 
List.of()).stream()
+                    .findFirst()
+                    .orElse(null);
+            String description = visitor.getData().getOrDefault("description", 
List.of()).stream()
+                    .findFirst()
+                    .orElse(null);
+
+            List<PromptArgument> arguments = new ArrayList<>();
+
+            visitor.getData().entrySet().stream()
+                    .filter(e -> e.getKey().startsWith("argument."))
+                    .forEach(e -> {
+                        String argName = 
e.getKey().substring("argument.".length());
+                        List<String> values = e.getValue();
+                        String argTitle = null;
+                        String argDesc = null;
+                        boolean argRequired = false;
+                        for (String value : values) {
+
+                            if (value.startsWith("title:")) {
+                                argTitle = 
value.substring("title:".length()).trim();
+                            } else if (value.startsWith("description:")) {
+                                argDesc =
+                                        
value.substring("description:".length()).trim();
+                            } else if (value.startsWith("required:")) {
+                                String argRequiredRaw =
+                                        
value.substring("required:".length()).trim();
+                                argRequired = Boolean.valueOf(argRequiredRaw);
+                            } else {
+                                logger.warn("Unknown argument property in 
prompt {}: {}", promptName, value);
+                            }
+                        }
+
+                        arguments.add(new PromptArgument(argName, argTitle, 
argDesc, argRequired));
+                    });
+
+            return new RepositoryPrompt(prompt.getPath(), promptName, title, 
description, arguments);
+        }
+    }
+
+    static class RepositoryPrompt implements DiscoveredPrompt {
+
+        private final String promptPath;
+        private final String promptName;
+        private final String promptTitle;
+        private final String promptDescription;
+        private final List<PromptArgument> arguments;
+
+        RepositoryPrompt(
+                String promptPath,
+                String promptName,
+                String promptTitle,
+                String promptDescription,
+                List<PromptArgument> arguments) {
+            this.promptPath = promptPath;
+            this.promptName = promptName;
+            this.promptTitle = promptTitle;
+            this.promptDescription = promptDescription;
+            this.arguments = arguments;
+        }
+
+        @Override
+        public List<PromptMessage> getPromptMessages(McpTransportContext c, 
GetPromptRequest req) {
+
+            ResourceResolver rr = (ResourceResolver) c.get("resourceResolver");
+
+            try {
+                Resource promptResource = rr.getResource(promptPath);
+                String encoding = 
promptResource.getResourceMetadata().getCharacterEncoding();
+                if (encoding == null) {
+                    encoding = StandardCharsets.UTF_8.name();
+                }
+                try (InputStream stream = 
promptResource.adaptTo(InputStream.class)) {
+                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                    stream.transferTo(baos);
+                    String contents = baos.toString(encoding);
+
+                    for (PromptArgument arg : arguments) {
+                        String placeholder = "{" + arg.name() + "}";
+                        Object requestedArg = req.arguments().get(arg.name());
+                        String value = requestedArg != null ? 
requestedArg.toString() : "";
+                        contents = contents.replace(placeholder, value);
+                    }
+
+                    return List.of(new PromptMessage(Role.ASSISTANT, new 
TextContent(contents)));
+                }
+            } catch (IOException e) {
+                return List.of();
+            }
+        }
+
+        @Override
+        public Prompt asPrompt() {
+            return new Prompt(promptName, promptTitle, promptDescription, 
arguments);
+        }
+    }
+}
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 fe0e97e..81b07a4 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
@@ -18,12 +18,7 @@
  */
 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;
@@ -31,9 +26,6 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
-import io.modelcontextprotocol.spec.McpSchema.PromptMessage;
-import io.modelcontextprotocol.spec.McpSchema.Role;
-import io.modelcontextprotocol.spec.McpSchema.TextContent;
 import org.apache.sling.api.resource.LoginException;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
@@ -42,10 +34,6 @@ 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;
@@ -61,6 +49,7 @@ public class RepositoryPromptsRegistrar {
     private static final String PROMPT_LIBS_DIR = "/libs/sling/mcp/prompts";
     private final Logger logger = LoggerFactory.getLogger(getClass());
     private ConcurrentMap<String, ServiceRegistration<DiscoveredPrompt>> 
registrations = new ConcurrentHashMap<>();
+    private final DiscoveredPromptBuilder promptBuilder = new 
DiscoveredPromptBuilder();
 
     @Activate
     public RepositoryPromptsRegistrar(@Reference ResourceResolverFactory rrf, 
BundleContext ctx) throws LoginException {
@@ -128,40 +117,20 @@ public class RepositoryPromptsRegistrar {
         }
     }
 
-    private void registerPrompt(BundleContext ctx, String promptName, Resource 
prompt) {
+    private void registerPrompt(BundleContext ctx, String promptName, Resource 
promptResource) {
 
-        Map<String, String> serviceProps = new 
HashMap<>(Map.of(DiscoveredPrompt.SERVICE_PROP_NAME, promptName));
+        try {
+            DiscoveredPrompt prompt = 
promptBuilder.buildPrompt(promptResource, 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));
+            var sr = ctx.registerService(
+                    DiscoveredPrompt.class,
+                    prompt,
+                    new Hashtable<>(Map.of(DiscoveredPrompt.SERVICE_PROP_NAME, 
promptName)));
+
+            registrations.put(promptName, sr);
         } catch (IOException e) {
-            logger.error("Error reading prompt markdown file at {}", 
prompt.getPath(), e);
+            logger.warn("Error registering prompt {} at path {}", promptName, 
promptResource.getPath(), e);
         }
-
-        // TODO - discover additional properties from the markdown file (front 
matter)
-
-        var sr = ctx.registerService(
-                DiscoveredPrompt.class,
-                new RepositoryPrompt(prompt.getPath()),
-                new Hashtable<String, String>(serviceProps));
-
-        registrations.put(promptName, sr);
     }
 
     private String getPromptName(String path) {
@@ -177,32 +146,4 @@ public class RepositoryPromptsRegistrar {
         // remove .md extension
         return promptName.substring(0, promptName.length() - ".md".length());
     }
-
-    class RepositoryPrompt implements DiscoveredPrompt {
-        private final String promptPath;
-
-        RepositoryPrompt(String promptPath) {
-            this.promptPath = promptPath;
-        }
-
-        @Override
-        public List<PromptMessage> getPromptMessages(ResourceResolver 
resolver) {
-
-            try {
-                Resource promptResource = resolver.getResource(promptPath);
-                String encoding = 
promptResource.getResourceMetadata().getCharacterEncoding();
-                if (encoding == null) {
-                    encoding = StandardCharsets.UTF_8.name();
-                }
-                try (InputStream stream = 
promptResource.adaptTo(InputStream.class)) {
-                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                    stream.transferTo(baos);
-                    String contents = baos.toString(encoding);
-                    return List.of(new PromptMessage(Role.ASSISTANT, new 
TextContent(contents)));
-                }
-            } catch (IOException e) {
-                return List.of();
-            }
-        }
-    }
 }
diff --git 
a/src/main/resources/SLING-INF/libs/sling/mcp/prompts/new-sling-servlet.md 
b/src/main/resources/SLING-INF/libs/sling/mcp/prompts/new-sling-servlet.md
new file mode 100644
index 0000000..c92cb83
--- /dev/null
+++ b/src/main/resources/SLING-INF/libs/sling/mcp/prompts/new-sling-servlet.md
@@ -0,0 +1,17 @@
+---
+title: "Create new Sling Servlet"
+description: "Creates a new Sling Servlet in the current project using 
annotations"
+argument.resource-type:
+  - title: Resource Type
+  - required: true
+  - description: The Sling resource type to bind this servlet to
+---
+
+# Create a new Sling Servlet
+
+ Create a new Sling Servlet for resource type: `{resource-type}`
+ 
+ Use the Sling-specific OSGi declarative services annotations - 
`@SlingServletResourceTypes` and `@Component` . 
+ Configure by default with the GET method and the json extension.
+ Provide a basic implementation of the doGet method that returns a JSON 
response with a message 'Hello from Sling Servlet at resource type 
{resource-type}'.
+ 
\ No newline at end of file
diff --git 
a/src/test/java/org/apache/sling/mcp/server/impl/contribs/DiscoveredPromptBuilderTest.java
 
b/src/test/java/org/apache/sling/mcp/server/impl/contribs/DiscoveredPromptBuilderTest.java
new file mode 100644
index 0000000..cd8d58e
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/mcp/server/impl/contribs/DiscoveredPromptBuilderTest.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.mcp.server.impl.contribs;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+import io.modelcontextprotocol.spec.McpSchema.Prompt;
+import io.modelcontextprotocol.spec.McpSchema.PromptArgument;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceMetadata;
+import org.apache.sling.mcp.server.impl.DiscoveredPrompt;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class DiscoveredPromptBuilderTest {
+
+    @Test
+    void basicMarkdownFile() throws IOException {
+
+        String markdownFile = """
+                # Basic Prompt
+                """;
+
+        Resource promptResource = mock(Resource.class);
+        when(promptResource.getResourceMetadata()).thenReturn(new 
ResourceMetadata());
+        when(promptResource.adaptTo(InputStream.class))
+                .thenReturn(new 
ByteArrayInputStream(markdownFile.getBytes(StandardCharsets.UTF_8)));
+
+        DiscoveredPromptBuilder builder = new DiscoveredPromptBuilder();
+        DiscoveredPrompt prompt = builder.buildPrompt(promptResource, 
"basic-prompt");
+
+        assertThat(prompt)
+                .as("prompt")
+                .extracting(DiscoveredPrompt::asPrompt)
+                .extracting(Prompt::name, Prompt::title, Prompt::description, 
Prompt::arguments)
+                .containsExactly("basic-prompt", null, null, List.of());
+    }
+
+    @Test
+    void basicFrontMatter() throws IOException {
+
+        String markdownFile = """
+                ---
+                title: Basic Prompt
+                description: |
+                    A basic prompt for testing.
+                    Spans multiple lines.
+                ---
+                # Basic Prompt
+                """;
+
+        Resource promptResource = mock(Resource.class);
+        when(promptResource.getResourceMetadata()).thenReturn(new 
ResourceMetadata());
+        when(promptResource.adaptTo(InputStream.class))
+                .thenReturn(new 
ByteArrayInputStream(markdownFile.getBytes(StandardCharsets.UTF_8)));
+
+        DiscoveredPromptBuilder builder = new DiscoveredPromptBuilder();
+        DiscoveredPrompt prompt = builder.buildPrompt(promptResource, 
"prompt-with-front-matter");
+
+        assertThat(prompt)
+                .as("prompt")
+                .extracting(DiscoveredPrompt::asPrompt)
+                .extracting(Prompt::name, Prompt::title, Prompt::description, 
Prompt::arguments)
+                .containsExactly(
+                        "prompt-with-front-matter",
+                        "Basic Prompt",
+                        "A basic prompt for testing.\nSpans multiple lines.",
+                        List.of());
+    }
+
+    @Test
+    void arguments() throws IOException {
+
+        String markdownFile = """
+                ---
+                title: Basic Prompt
+                argument.first:
+                    - title: First Argument
+                    - description: This is the first argument
+                    - required: true
+                argument.second:
+                    - title: Second Argument
+                ---
+                # Basic Prompt
+                """;
+
+        Resource promptResource = mock(Resource.class);
+        when(promptResource.getResourceMetadata()).thenReturn(new 
ResourceMetadata());
+        when(promptResource.adaptTo(InputStream.class))
+                .thenReturn(new 
ByteArrayInputStream(markdownFile.getBytes(StandardCharsets.UTF_8)));
+
+        DiscoveredPromptBuilder builder = new DiscoveredPromptBuilder();
+        DiscoveredPrompt prompt = builder.buildPrompt(promptResource, 
"prompt-with-arguments");
+        assertThat(prompt)
+                .as("prompt")
+                .extracting(DiscoveredPrompt::asPrompt)
+                .extracting(Prompt::name, Prompt::title, Prompt::description, 
Prompt::arguments)
+                .containsExactly(
+                        "prompt-with-arguments",
+                        "Basic Prompt",
+                        null,
+                        List.of(
+                                new PromptArgument("first", "First Argument", 
"This is the first argument", true),
+                                new PromptArgument("second", "Second 
Argument", null, false)));
+    }
+}

Reply via email to