From 1e3d5c81f17ace75fdb334868a71d5e1f37d6b69 Mon Sep 17 00:00:00 2001 From: Ahmed Muhsin Date: Tue, 21 Apr 2026 12:34:38 -0500 Subject: [PATCH 1/4] Add McpPromptTrigger and McpPromptArgument annotations Implements annotation definitions for MCP prompt support (issue #861). - McpPromptTrigger: trigger annotation for prompt functions with name, description, title, promptArguments, metadata, and icons properties - McpPromptArgument: input binding annotation for individual prompt arguments with argumentName, description, and isRequired properties The name() property serves as both the binding parameter name and the unique prompt identifier (same convention as McpToolTrigger). --- .../annotation/McpPromptArgument.java | 77 ++++++++++ .../annotation/McpPromptTrigger.java | 132 ++++++++++++++++++ 2 files changed, 209 insertions(+) create mode 100644 src/main/java/com/microsoft/azure/functions/annotation/McpPromptArgument.java create mode 100644 src/main/java/com/microsoft/azure/functions/annotation/McpPromptTrigger.java diff --git a/src/main/java/com/microsoft/azure/functions/annotation/McpPromptArgument.java b/src/main/java/com/microsoft/azure/functions/annotation/McpPromptArgument.java new file mode 100644 index 0000000..2063d35 --- /dev/null +++ b/src/main/java/com/microsoft/azure/functions/annotation/McpPromptArgument.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.azure.functions.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Defines a strongly-typed input argument for an MCP prompt function parameter. + *

+ * Alternative to using JSON format in {@link McpPromptTrigger#promptArguments()}. + * Each annotated parameter receives a specific argument value from the prompt invocation. + * Unlike tool properties, prompt arguments are always strings — no type schema is needed. + *

+ * + *

Example:

+ *
+ * {@literal @}FunctionName("codeReview")
+ * public String codeReview(
+ *     {@literal @}McpPromptTrigger(name = "context", description = "Code review prompt") String context,
+ *     {@literal @}McpPromptArgument(
+ *         name = "code",
+ *         argumentName = "code",
+ *         description = "The code to review",
+ *         isRequired = true
+ *     ) String code,
+ *     {@literal @}McpPromptArgument(
+ *         name = "language",
+ *         argumentName = "language",
+ *         description = "The programming language"
+ *     ) String language
+ * ) {
+ *     return "Please review the following " + language + " code:\n\n" + code;
+ * }
+ * 
+ * + * @see McpPromptTrigger + * @since 3.3.0 + */ +@Target({ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface McpPromptArgument { + + /** + * The parameter binding name for the Azure Functions runtime. + * + * @return The parameter binding name + */ + String name(); + + /** + * The name of the prompt argument as exposed in the MCP protocol. + * + * @return The argument name + */ + String argumentName() default ""; + + /** + * Description of the argument's purpose and usage. + * + * @return Description of the argument + */ + String description() default ""; + + /** + * Whether this argument is required for prompt invocation. + * + * @return true if required, false if optional + */ + boolean isRequired() default false; +} diff --git a/src/main/java/com/microsoft/azure/functions/annotation/McpPromptTrigger.java b/src/main/java/com/microsoft/azure/functions/annotation/McpPromptTrigger.java new file mode 100644 index 0000000..b3aa32b --- /dev/null +++ b/src/main/java/com/microsoft/azure/functions/annotation/McpPromptTrigger.java @@ -0,0 +1,132 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.azure.functions.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Triggers an Azure Function when invoked by the Model Context Protocol (MCP) prompt system. + *

+ * This annotation enables Azure Functions to expose prompt templates that MCP-compatible clients + * can discover via {@code prompts/list} and invoke via {@code prompts/get} with arguments. + * The function returns a plain string (auto-wrapped into a single user message) or a + * JSON-serialized {@code GetPromptResult} for multi-message or rich content responses. + *

+ * + *

Example with inline arguments:

+ *
+ * {@literal @}FunctionName("codeReview")
+ * public String codeReview(
+ *     {@literal @}McpPromptTrigger(
+ *         name = "code_review",
+ *         description = "Generates a code review prompt",
+ *         promptArguments = "[{\"name\":\"code\",\"description\":\"The code to review\",\"required\":true}," +
+ *                           "{\"name\":\"language\",\"description\":\"Programming language\",\"required\":false}]"
+ *     ) String context
+ * ) {
+ *     return "Please review the following code...";
+ * }
+ * 
+ * + *

Example with {@link McpPromptArgument} annotations:

+ *
+ * {@literal @}FunctionName("summarize")
+ * public String summarize(
+ *     {@literal @}McpPromptTrigger(
+ *         name = "summarize",
+ *         description = "Summarizes the provided text"
+ *     ) String context,
+ *     {@literal @}McpPromptArgument(
+ *         name = "text",
+ *         argumentName = "text",
+ *         description = "The text to summarize",
+ *         isRequired = true
+ *     ) String text
+ * ) {
+ *     return "Please provide a concise summary of: " + text;
+ * }
+ * 
+ * + * @see McpPromptArgument + * @see McpMetadata + * @since 3.3.0 + */ +@Target({ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface McpPromptTrigger { + + /** + * The variable name used in function.json and also the unique prompt name + * that MCP clients use to identify and invoke this prompt. + *

+ * This serves as both the binding parameter name and the prompt identifier. + * It must be unique across all prompts in the function app. + *

+ * + * @return The prompt name / parameter binding name + */ + String name(); + + /** + * Defines how Functions runtime should treat the parameter value. Possible values are: + * + * + * @return The dataType which will be used by the Functions runtime. + */ + String dataType() default ""; + + /** + * Human-readable description of what this prompt does. + * + * @return Description of the prompt's purpose + */ + String description() default ""; + + /** + * Optional human-readable title for display purposes. + * + * @return The display title, or empty string if not specified + */ + String title() default ""; + + /** + * JSON array defining expected prompt arguments. + *

+ * Each argument should be a JSON object with: name, description, required. + * Alternative: use {@link McpPromptArgument} annotations on parameters. + *

+ * + *

Example:

+ *
+     * [{"name":"code","description":"The code to review","required":true}]
+     * 
+ * + * @return JSON array of argument definitions, or empty string + */ + String promptArguments() default ""; + + /** + * JSON-serialized metadata for the MCP prompt. + * + * @return JSON metadata string, or empty string if not specified + */ + String metadata() default ""; + + /** + * JSON array of icons for the MCP prompt. + * + * @return JSON array of icon definitions, or empty string if not specified + */ + String icons() default ""; +} From b861a1ea61e1d4135ac6693a4497731456938f52 Mon Sep 17 00:00:00 2001 From: Ahmed Muhsin Date: Tue, 21 Apr 2026 16:57:08 -0500 Subject: [PATCH 2/4] Address review feedback: remove argumentName, fix Javadoc - Remove argumentName() from McpPromptArgument: name() serves as both the binding parameter name and the MCP argument identifier, matching the McpToolProperty pattern where name() maps to propertyName - Fix Javadoc example in McpPromptArgument: use code_review as prompt name instead of context - Remove argumentName from McpPromptTrigger Javadoc example - Add Javadoc notes explaining the name/argumentName patching convention --- .../annotation/McpPromptArgument.java | 23 +++++++++---------- .../annotation/McpPromptTrigger.java | 1 - 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/microsoft/azure/functions/annotation/McpPromptArgument.java b/src/main/java/com/microsoft/azure/functions/annotation/McpPromptArgument.java index 2063d35..8582ec4 100644 --- a/src/main/java/com/microsoft/azure/functions/annotation/McpPromptArgument.java +++ b/src/main/java/com/microsoft/azure/functions/annotation/McpPromptArgument.java @@ -18,21 +18,25 @@ * Each annotated parameter receives a specific argument value from the prompt invocation. * Unlike tool properties, prompt arguments are always strings — no type schema is needed. *

+ *

+ * The {@code name()} value serves as both the binding parameter name and the argument name + * exposed in the MCP protocol (the Maven plugin patches it into {@code argumentName} in + * function.json). This follows the same convention as {@link McpToolProperty} where + * {@code name()} is patched into {@code propertyName}. + *

* *

Example:

*
  * {@literal @}FunctionName("codeReview")
  * public String codeReview(
- *     {@literal @}McpPromptTrigger(name = "context", description = "Code review prompt") String context,
+ *     {@literal @}McpPromptTrigger(name = "code_review", description = "Code review prompt") String context,
  *     {@literal @}McpPromptArgument(
  *         name = "code",
- *         argumentName = "code",
  *         description = "The code to review",
  *         isRequired = true
  *     ) String code,
  *     {@literal @}McpPromptArgument(
  *         name = "language",
- *         argumentName = "language",
  *         description = "The programming language"
  *     ) String language
  * ) {
@@ -48,18 +52,13 @@
 public @interface McpPromptArgument {
 
     /**
-     * The parameter binding name for the Azure Functions runtime.
-     *
-     * @return The parameter binding name
-     */
-    String name();
-
-    /**
-     * The name of the prompt argument as exposed in the MCP protocol.
+     * The argument name used as both the binding parameter name and the MCP protocol
+     * argument identifier. The Maven plugin patches this into {@code argumentName}
+     * in function.json.
      *
      * @return The argument name
      */
-    String argumentName() default "";
+    String name();
 
     /**
      * Description of the argument's purpose and usage.
diff --git a/src/main/java/com/microsoft/azure/functions/annotation/McpPromptTrigger.java b/src/main/java/com/microsoft/azure/functions/annotation/McpPromptTrigger.java
index b3aa32b..2ee4138 100644
--- a/src/main/java/com/microsoft/azure/functions/annotation/McpPromptTrigger.java
+++ b/src/main/java/com/microsoft/azure/functions/annotation/McpPromptTrigger.java
@@ -45,7 +45,6 @@
  *     ) String context,
  *     {@literal @}McpPromptArgument(
  *         name = "text",
- *         argumentName = "text",
  *         description = "The text to summarize",
  *         isRequired = true
  *     ) String text

From faec766c46ebc2ad73f67a4a28ee8129afdaf3ae Mon Sep 17 00:00:00 2001
From: Ahmed Muhsin 
Date: Tue, 28 Apr 2026 12:20:17 -0500
Subject: [PATCH 3/4] Bump version to 3.3.0 for new MCP prompt annotations

---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 515289f..8a0e26c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
 	4.0.0
 	com.microsoft.azure.functions
 	azure-functions-java-library
-	3.2.4
+	3.3.0
 	jar
 	
 		com.microsoft.maven

From ae0dde560eb4137bd59950a2a2c597034e41e497 Mon Sep 17 00:00:00 2001
From: Ahmed Muhsin 
Date: Tue, 28 Apr 2026 14:49:09 -0500
Subject: [PATCH 4/4] Remove inline JSON example from McpPromptTrigger Javadoc

Steer users toward @McpPromptArgument annotations as the recommended
approach. The promptArguments() JSON string property is kept for
consistency with McpToolTrigger.toolProperties() but is no longer
showcased in the examples.
---
 .../annotation/McpPromptTrigger.java          | 31 ++++++-------------
 1 file changed, 10 insertions(+), 21 deletions(-)

diff --git a/src/main/java/com/microsoft/azure/functions/annotation/McpPromptTrigger.java b/src/main/java/com/microsoft/azure/functions/annotation/McpPromptTrigger.java
index 2ee4138..311f216 100644
--- a/src/main/java/com/microsoft/azure/functions/annotation/McpPromptTrigger.java
+++ b/src/main/java/com/microsoft/azure/functions/annotation/McpPromptTrigger.java
@@ -20,36 +20,25 @@
  * JSON-serialized {@code GetPromptResult} for multi-message or rich content responses.
  * 

* - *

Example with inline arguments:

+ *

Example:

*
  * {@literal @}FunctionName("codeReview")
  * public String codeReview(
  *     {@literal @}McpPromptTrigger(
  *         name = "code_review",
- *         description = "Generates a code review prompt",
- *         promptArguments = "[{\"name\":\"code\",\"description\":\"The code to review\",\"required\":true}," +
- *                           "{\"name\":\"language\",\"description\":\"Programming language\",\"required\":false}]"
- *     ) String context
- * ) {
- *     return "Please review the following code...";
- * }
- * 
- * - *

Example with {@link McpPromptArgument} annotations:

- *
- * {@literal @}FunctionName("summarize")
- * public String summarize(
- *     {@literal @}McpPromptTrigger(
- *         name = "summarize",
- *         description = "Summarizes the provided text"
+ *         description = "Generates a code review prompt"
  *     ) String context,
  *     {@literal @}McpPromptArgument(
- *         name = "text",
- *         description = "The text to summarize",
+ *         name = "code",
+ *         description = "The code to review",
  *         isRequired = true
- *     ) String text
+ *     ) String code,
+ *     {@literal @}McpPromptArgument(
+ *         name = "language",
+ *         description = "The programming language"
+ *     ) String language
  * ) {
- *     return "Please provide a concise summary of: " + text;
+ *     return "Please review the following " + language + " code:\n\n" + code;
  * }
  * 
*