diff --git a/README.md b/README.md
index 9ebb37c..aa6519c 100644
--- a/README.md
+++ b/README.md
@@ -895,6 +895,63 @@ public List smartComplete(
This feature enables context-aware MCP operations where the behavior can be customized based on client-provided metadata such as user identity, preferences, session information, or any other contextual data.
+#### metaProvider (_meta) Support
+
+The `@McpTool`, `@McpPrompt`, and `@McpResource` annotations support a `metaProvider` attribute that allows attaching arbitrary `_meta` data to MCP tool, prompt, and resource declarations. This metadata is propagated to both the declarations and to resource content in `ReadResourceResult`.
+
+To use this feature, implement the `MetaProvider` interface and reference the class in the annotation:
+
+```java
+class MyMetaProvider implements MetaProvider {
+ @Override
+ public Map getMeta() {
+ return Map.of(
+ "openai/widgetPrefersBorder", true,
+ "openai/widgetDomain", "https://chatgpt.com"
+ );
+ }
+}
+```
+
+**Tool with _meta:**
+```java
+@McpTool(name = "my-tool",
+ description = "A tool with metadata",
+ metaProvider = MyMetaProvider.class)
+public String myTool(@McpToolParam(description = "Input", required = true) String input) {
+ return "Processed: " + input;
+}
+```
+
+**Prompt with _meta:**
+```java
+@McpPrompt(name = "my-prompt",
+ description = "A prompt with metadata",
+ metaProvider = MyMetaProvider.class)
+public GetPromptResult myPrompt(
+ @McpArg(name = "topic", required = true) String topic) {
+ return new GetPromptResult("My Prompt",
+ List.of(new PromptMessage(Role.ASSISTANT, new TextContent("About: " + topic))));
+}
+```
+
+**Resource with _meta:**
+```java
+@McpResource(uri = "data://{id}",
+ name = "My Resource",
+ description = "A resource with metadata",
+ metaProvider = MyMetaProvider.class)
+public String getData(String id) {
+ return "Data for: " + id;
+}
+```
+
+**MetaProvider behavior:**
+- **Default**: `DefaultMetaProvider.class` — returns `null`, meaning no `_meta` is appended to declarations
+- **Custom**: Implement `MetaProvider` and return a `Map` with the desired key-value pairs
+- The provider must have a public no-arg constructor (it is instantiated via reflection)
+- Metadata is propagated to both the MCP declaration and to resource content in `ReadResourceResult`
+
#### McpRequestContext Support
The library provides unified request context interfaces (`McpSyncRequestContext` and `McpAsyncRequestContext`) that offer a higher-level abstraction over the underlying MCP infrastructure. These context objects provide convenient access to:
@@ -2275,6 +2332,7 @@ Override `AbstractMcpToolProvider#doGetToolCallException()` to customize the exc
- **Sampling support** - Handle sampling requests from MCP servers
- **Progress notification support** - Handle progress notifications for long-running operations
- **Tool list changed support** - Handle tool list change notifications from MCP servers when tools are dynamically added, removed, or modified
+- **_meta support via metaProvider** - Attach arbitrary `_meta` data to tool, prompt, and resource declarations using a pluggable `MetaProvider` interface on `@McpTool`, `@McpPrompt`, and `@McpResource`
## Requirements
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/MetaUtils.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/MetaUtils.java
index 93f6640..1fa86e9 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/MetaUtils.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/MetaUtils.java
@@ -21,6 +21,9 @@
* {@link IllegalArgumentException IllegalArgumentExceptions}. This class is stateless and
* not intended to be instantiated.
*
+ *
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public final class MetaUtils {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/adapter/PromptAdapter.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/adapter/PromptAdapter.java
index 8c870d8..8aaa641 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/adapter/PromptAdapter.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/adapter/PromptAdapter.java
@@ -19,6 +19,8 @@
* Utility class for adapting between McpPrompt annotations and McpSchema.Prompt objects.
*
* @author Christian Tzolov
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public class PromptAdapter {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/adapter/ResourceAdapter.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/adapter/ResourceAdapter.java
index 6de5cc3..b228f3e 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/adapter/ResourceAdapter.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/adapter/ResourceAdapter.java
@@ -4,17 +4,21 @@
package org.springaicommunity.mcp.adapter;
import java.util.List;
-import java.util.Map;
import io.modelcontextprotocol.spec.McpSchema;
-import io.modelcontextprotocol.util.Utils;
import org.springaicommunity.mcp.MetaUtils;
import org.springaicommunity.mcp.annotation.McpResource;
-import org.springaicommunity.mcp.method.tool.utils.JsonParser;
/**
+ * Utility class that converts {@link McpResource} annotations into MCP schema objects.
+ * Provides factory methods to build {@link McpSchema.Resource} and
+ * {@link McpSchema.ResourceTemplate} instances from annotation metadata, including URI,
+ * name, description, MIME type, annotations, and optional {@code _meta} fields.
+ *
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public class ResourceAdapter {
@@ -66,12 +70,4 @@ public static McpSchema.ResourceTemplate asResourceTemplate(McpResource mcpResou
.build();
}
- @SuppressWarnings("unchecked")
- private static Map parseMeta(String metaJson) {
- if (!Utils.hasText(metaJson)) {
- return null;
- }
- return JsonParser.fromJson(metaJson, Map.class);
- }
-
}
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/annotation/McpPrompt.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/annotation/McpPrompt.java
index 65531c5..7a5c04e 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/annotation/McpPrompt.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/annotation/McpPrompt.java
@@ -17,6 +17,8 @@
* Marks a method as a MCP Prompt.
*
* @author Christian Tzolov
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/annotation/McpResource.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/annotation/McpResource.java
index 6770418..0ca56e2 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/annotation/McpResource.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/annotation/McpResource.java
@@ -19,6 +19,8 @@
*
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/annotation/McpTool.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/annotation/McpTool.java
index 3b89b3e..7d1bdde 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/annotation/McpTool.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/annotation/McpTool.java
@@ -3,19 +3,20 @@
*/
package org.springaicommunity.mcp.annotation;
-import org.springaicommunity.mcp.context.DefaultMetaProvider;
-import org.springaicommunity.mcp.context.MetaProvider;
-
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import java.util.Map;
+
+import org.springaicommunity.mcp.context.DefaultMetaProvider;
+import org.springaicommunity.mcp.context.MetaProvider;
/**
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/context/DefaultMetaProvider.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/context/DefaultMetaProvider.java
index 766a059..3876f97 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/context/DefaultMetaProvider.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/context/DefaultMetaProvider.java
@@ -15,6 +15,9 @@
* Use this when your tool, prompt, or resource does not need to expose any meta
* information or you want to keep responses minimal by default.
*
+ *
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public class DefaultMetaProvider implements MetaProvider {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/context/MetaProvider.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/context/MetaProvider.java
index 0d37863..4802ecd 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/context/MetaProvider.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/context/MetaProvider.java
@@ -5,6 +5,9 @@
/**
* Common interface for classes that provide metadata for the "_meta" field. This metadata
* is used in tool, prompt, and resource declarations.
+ *
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public interface MetaProvider {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/AbstractMcpResourceMethodCallback.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/AbstractMcpResourceMethodCallback.java
index 9d58c92..8855fcc 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/AbstractMcpResourceMethodCallback.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/AbstractMcpResourceMethodCallback.java
@@ -36,6 +36,8 @@
*
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public abstract class AbstractMcpResourceMethodCallback {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/AsyncMcpResourceMethodCallback.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/AsyncMcpResourceMethodCallback.java
index 8741f4e..75a613b 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/AsyncMcpResourceMethodCallback.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/AsyncMcpResourceMethodCallback.java
@@ -31,6 +31,8 @@
*
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public final class AsyncMcpResourceMethodCallback extends AbstractMcpResourceMethodCallback
implements BiFunction> {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/AsyncStatelessMcpResourceMethodCallback.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/AsyncStatelessMcpResourceMethodCallback.java
index 9bc8984..223a93c 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/AsyncStatelessMcpResourceMethodCallback.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/AsyncStatelessMcpResourceMethodCallback.java
@@ -31,6 +31,8 @@
*
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public final class AsyncStatelessMcpResourceMethodCallback extends AbstractMcpResourceMethodCallback
implements BiFunction> {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/DefaultMcpReadResourceResultConverter.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/DefaultMcpReadResourceResultConverter.java
index 301b278..539c01b 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/DefaultMcpReadResourceResultConverter.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/DefaultMcpReadResourceResultConverter.java
@@ -23,6 +23,8 @@
*
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public class DefaultMcpReadResourceResultConverter implements McpReadResourceResultConverter {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/McpReadResourceResultConverter.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/McpReadResourceResultConverter.java
index 4439737..689802e 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/McpReadResourceResultConverter.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/McpReadResourceResultConverter.java
@@ -18,6 +18,8 @@
*
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public interface McpReadResourceResultConverter {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/SyncMcpResourceMethodCallback.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/SyncMcpResourceMethodCallback.java
index 98bfb30..c91d1fe 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/SyncMcpResourceMethodCallback.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/SyncMcpResourceMethodCallback.java
@@ -29,6 +29,8 @@
*
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public final class SyncMcpResourceMethodCallback extends AbstractMcpResourceMethodCallback
implements BiFunction {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/SyncStatelessMcpResourceMethodCallback.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/SyncStatelessMcpResourceMethodCallback.java
index 551dd38..2e7eb30 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/SyncStatelessMcpResourceMethodCallback.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/method/resource/SyncStatelessMcpResourceMethodCallback.java
@@ -30,6 +30,8 @@
*
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public final class SyncStatelessMcpResourceMethodCallback extends AbstractMcpResourceMethodCallback
implements BiFunction {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/resource/AsyncMcpResourceProvider.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/resource/AsyncMcpResourceProvider.java
index a687d71..79e527d 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/resource/AsyncMcpResourceProvider.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/resource/AsyncMcpResourceProvider.java
@@ -49,6 +49,8 @@
*
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public class AsyncMcpResourceProvider {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/resource/AsyncStatelessMcpResourceProvider.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/resource/AsyncStatelessMcpResourceProvider.java
index 8af5f93..c4f1a11 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/resource/AsyncStatelessMcpResourceProvider.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/resource/AsyncStatelessMcpResourceProvider.java
@@ -49,6 +49,8 @@
*
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public class AsyncStatelessMcpResourceProvider {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/resource/SyncMcpResourceProvider.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/resource/SyncMcpResourceProvider.java
index f31388b..8fae24f 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/resource/SyncMcpResourceProvider.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/resource/SyncMcpResourceProvider.java
@@ -36,6 +36,8 @@
/**
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public class SyncMcpResourceProvider {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/resource/SyncStatelessMcpResourceProvider.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/resource/SyncStatelessMcpResourceProvider.java
index dcbfea4..713d855 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/resource/SyncStatelessMcpResourceProvider.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/resource/SyncStatelessMcpResourceProvider.java
@@ -48,6 +48,8 @@
*
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public class SyncStatelessMcpResourceProvider {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/AbstractMcpToolProvider.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/AbstractMcpToolProvider.java
index 966b97d..a997c5f 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/AbstractMcpToolProvider.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/AbstractMcpToolProvider.java
@@ -14,6 +14,8 @@
/**
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public abstract class AbstractMcpToolProvider {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/AsyncMcpToolProvider.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/AsyncMcpToolProvider.java
index 0029dab..aed93e5 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/AsyncMcpToolProvider.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/AsyncMcpToolProvider.java
@@ -43,6 +43,8 @@
/**
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public class AsyncMcpToolProvider extends AbstractMcpToolProvider {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/AsyncStatelessMcpToolProvider.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/AsyncStatelessMcpToolProvider.java
index 676e1c9..96413dc 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/AsyncStatelessMcpToolProvider.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/AsyncStatelessMcpToolProvider.java
@@ -49,6 +49,8 @@
*
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public class AsyncStatelessMcpToolProvider extends AbstractMcpToolProvider {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/SyncMcpToolProvider.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/SyncMcpToolProvider.java
index c9d49db..bb5688f 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/SyncMcpToolProvider.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/SyncMcpToolProvider.java
@@ -41,6 +41,8 @@
/**
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public class SyncMcpToolProvider extends AbstractMcpToolProvider {
diff --git a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/SyncStatelessMcpToolProvider.java b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/SyncStatelessMcpToolProvider.java
index a130d1a..016804e 100644
--- a/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/SyncStatelessMcpToolProvider.java
+++ b/mcp-annotations/src/main/java/org/springaicommunity/mcp/provider/tool/SyncStatelessMcpToolProvider.java
@@ -46,6 +46,8 @@
*
* @author Christian Tzolov
* @author Alexandros Pappas
+ * @author Vadzim Shurmialiou
+ * @author Craig Walls
*/
public class SyncStatelessMcpToolProvider extends AbstractMcpToolProvider {