This repository was archived by the owner on Apr 11, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 34
Combine PRs #102 and #83 #104
Closed
Closed
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
87 changes: 87 additions & 0 deletions
87
mcp-annotations/src/main/java/org/springaicommunity/mcp/MetaUtils.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| package org.springaicommunity.mcp; | ||
|
|
||
| import java.lang.reflect.Constructor; | ||
| import java.lang.reflect.InvocationTargetException; | ||
| import java.util.Collections; | ||
| import java.util.Map; | ||
|
|
||
| import org.springaicommunity.mcp.context.MetaProvider; | ||
|
|
||
| /** | ||
| * Utility methods for working with {@link MetaProvider} metadata. | ||
| * | ||
| * <p> | ||
| * This class provides a single entry point {@link #getMeta(Class)} that instantiates the | ||
| * given provider type via a no-argument constructor and returns its metadata as an | ||
| * unmodifiable {@link Map}. | ||
| * </p> | ||
| * | ||
| * <p> | ||
| * Instantiation failures and missing no-arg constructors are reported as | ||
| * {@link IllegalArgumentException IllegalArgumentExceptions}. This class is stateless and | ||
| * not intended to be instantiated. | ||
| * </p> | ||
| */ | ||
| public final class MetaUtils { | ||
|
|
||
| /** Not intended to be instantiated. */ | ||
| private MetaUtils() { | ||
| } | ||
|
|
||
| /** | ||
| * Instantiate the supplied {@link MetaProvider} type using a no-argument constructor | ||
| * and return the metadata it supplies. | ||
| * <p> | ||
| * The returned map is wrapped in {@link Collections#unmodifiableMap(Map)} to prevent | ||
| * external modification. If the provider returns {@code null}, this method also | ||
| * returns {@code null}. | ||
| * @param metaProviderClass the {@code MetaProvider} implementation class to | ||
| * instantiate; must provide a no-arg constructor | ||
| * @return an unmodifiable metadata map, or {@code null} if the provider returns | ||
| * {@code null} | ||
| * @throws IllegalArgumentException if a no-arg constructor is missing or the instance | ||
| * cannot be created | ||
| */ | ||
| public static Map<String, Object> getMeta(Class<? extends MetaProvider> metaProviderClass) { | ||
|
|
||
| if (metaProviderClass == null) { | ||
| return null; | ||
| } | ||
|
|
||
| String className = metaProviderClass.getName(); | ||
| MetaProvider metaProvider; | ||
| try { | ||
| // Prefer a public no-arg constructor; fall back to a declared no-arg if | ||
| // accessible | ||
| Constructor<? extends MetaProvider> constructor = getConstructor(metaProviderClass); | ||
| metaProvider = constructor.newInstance(); | ||
| } | ||
| catch (NoSuchMethodException e) { | ||
| throw new IllegalArgumentException("Required no-arg constructor not found in " + className, e); | ||
| } | ||
| catch (InvocationTargetException | InstantiationException | IllegalAccessException e) { | ||
| throw new IllegalArgumentException(className + " instantiation failed", e); | ||
| } | ||
|
|
||
| Map<String, Object> meta = metaProvider.getMeta(); | ||
| return meta == null ? null : Collections.unmodifiableMap(meta); | ||
| } | ||
|
|
||
| /** | ||
| * Locate a no-argument constructor on the given class: prefer public, otherwise fall | ||
| * back to a declared no-arg constructor. | ||
| * @param metaProviderClass the class to inspect | ||
| * @return the resolved no-arg constructor | ||
| * @throws NoSuchMethodException if the class does not declare any no-arg constructor | ||
| */ | ||
| private static Constructor<? extends MetaProvider> getConstructor(Class<? extends MetaProvider> metaProviderClass) | ||
| throws NoSuchMethodException { | ||
| try { | ||
| return metaProviderClass.getDeclaredConstructor(); | ||
| } | ||
| catch (NoSuchMethodException ex) { | ||
| return metaProviderClass.getConstructor(); | ||
| } | ||
| } | ||
|
|
||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,12 +4,17 @@ | |
| 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; | ||
|
|
||
| /** | ||
| * @author Christian Tzolov | ||
| * @author Alexandros Pappas | ||
| */ | ||
| public class ResourceAdapter { | ||
|
|
||
|
|
@@ -21,13 +26,15 @@ public static McpSchema.Resource asResource(McpResource mcpResourceAnnotation) { | |
| if (name == null || name.isEmpty()) { | ||
| name = "resource"; // Default name when not specified | ||
| } | ||
| var meta = MetaUtils.getMeta(mcpResourceAnnotation.metaProvider()); | ||
|
|
||
| var resourceBuilder = McpSchema.Resource.builder() | ||
| .uri(mcpResourceAnnotation.uri()) | ||
| .name(name) | ||
| .title(mcpResourceAnnotation.title()) | ||
| .description(mcpResourceAnnotation.description()) | ||
| .mimeType(mcpResourceAnnotation.mimeType()); | ||
| .mimeType(mcpResourceAnnotation.mimeType()) | ||
| .meta(meta); | ||
|
|
||
| // Only set annotations if not default value is provided | ||
| // This is a workaround since Java annotations do not support null default values | ||
|
|
@@ -48,8 +55,23 @@ public static McpSchema.ResourceTemplate asResourceTemplate(McpResource mcpResou | |
| if (name == null || name.isEmpty()) { | ||
| name = "resource"; // Default name when not specified | ||
| } | ||
| return new McpSchema.ResourceTemplate(mcpResource.uri(), name, mcpResource.description(), | ||
| mcpResource.mimeType(), null); | ||
| var meta = MetaUtils.getMeta(mcpResource.metaProvider()); | ||
|
|
||
| return McpSchema.ResourceTemplate.builder() | ||
| .uriTemplate(mcpResource.uri()) | ||
| .name(name) | ||
| .description(mcpResource.description()) | ||
| .mimeType(mcpResource.mimeType()) | ||
| .meta(meta) | ||
| .build(); | ||
| } | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| private static Map<String, Object> parseMeta(String metaJson) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this method in use? Also in AsyncStatelessMcpResourceProvider, SyncMcpResourceProvider, SyncStatelessMcpResourceProvider, AbstractMcpToolProvider.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it doesn't and was removed in #105 |
||
| if (!Utils.hasText(metaJson)) { | ||
| return null; | ||
| } | ||
| return JsonParser.fromJson(metaJson, Map.class); | ||
| } | ||
|
|
||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
mcp-annotations/src/main/java/org/springaicommunity/mcp/context/DefaultMetaProvider.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package org.springaicommunity.mcp.context; | ||
|
|
||
| import java.util.Map; | ||
|
|
||
| /** | ||
| * Default {@link MetaProvider} implementation that disables the "_meta" field in tool, | ||
| * prompt, resource declarations. | ||
| * | ||
| * <p> | ||
| * This provider deliberately returns {@code null} from {@link #getMeta()} to signal that | ||
| * no "_meta" information is included. | ||
| * </p> | ||
| * | ||
| * <p> | ||
| * 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. | ||
| * </p> | ||
| */ | ||
| public class DefaultMetaProvider implements MetaProvider { | ||
|
|
||
| /** | ||
| * Returns {@code null} to indicate that no "_meta" field should be included in. | ||
| */ | ||
| @Override | ||
| public Map<String, Object> getMeta() { | ||
| return null; | ||
| } | ||
|
|
||
| } |
20 changes: 20 additions & 0 deletions
20
mcp-annotations/src/main/java/org/springaicommunity/mcp/context/MetaProvider.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package org.springaicommunity.mcp.context; | ||
|
|
||
| import java.util.Map; | ||
|
|
||
| /** | ||
| * Common interface for classes that provide metadata for the "_meta" field. This metadata | ||
| * is used in tool, prompt, and resource declarations. | ||
| */ | ||
| public interface MetaProvider { | ||
|
|
||
| /** | ||
| * Returns metadata key-value pairs that will be included in the "_meta" field. These | ||
| * metadata values provide additional context and information for tools, prompts, and | ||
| * resource declarations. | ||
| * @return A Map containing metadata key-value pairs, where keys are strings and | ||
| * values can be any object type. | ||
| */ | ||
| Map<String, Object> getMeta(); | ||
|
|
||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since here are multiple authors I would suggest to remove them from JavaDoc and keep them in the git log. Here and in 26 other changed files.
Also, it would be nice to write a couple words explaining the class purpose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the javadocs to add the missing hames: #105