@@ -11,6 +11,17 @@ import io.modelcontextprotocol.kotlin.sdk.types.Resource
1111import io.modelcontextprotocol.kotlin.sdk.types.ResourceTemplate
1212import io.modelcontextprotocol.kotlin.sdk.types.Tool
1313
14+ public interface UriTemplateArgumentExtractor {
15+ /* *
16+ * Extracts the arguments from the given [input] string based on the URI template defined in this extractor.
17+ *
18+ * @param input The input string to extract arguments from.
19+ * @return A map of argument names to their corresponding values extracted from the input string.
20+ * If the input does not match the URI template, an empty map is returned.
21+ */
22+ public fun extractArguments (input : String ): Map <String , String >
23+ }
24+
1425/* *
1526 * Represents a unique key for a feature and allows comparing inputs with the [key].
1627 */
@@ -51,8 +62,11 @@ public class StringFeatureKey(override val key: String) : FeatureKey<String>() {
5162 *
5263 * @property key The URI template string key identifying the feature.
5364 */
54- public class UriTemplateFeatureKey (override val key : String ) : FeatureKey<Regex>() {
65+ public class UriTemplateFeatureKey (override val key : String ) :
66+ FeatureKey <Regex >(),
67+ UriTemplateArgumentExtractor {
5568 override val value: Regex
69+ public val groups: MutableList <String > = mutableListOf<String >()
5670 init {
5771 // Convert URI template to regex as follows:
5872 // - A simple variable `{variable}` is replaced with `(?<variable>[^/]+)`
@@ -62,9 +76,10 @@ public class UriTemplateFeatureKey(override val key: String) : FeatureKey<Regex>
6276
6377 val newRegex = Regex (" \\ {(<groupName>[^}*]*)(<wildcard>[*]?)}" )
6478 .replace(uriWithoutQueryParameters) { matchResult ->
65- val groupName = matchResult.groups[" groupName" ]
79+ val groupName = matchResult.groups[" groupName" ]?.value
6680 checkNotNull(groupName) { " Invalid URI template: $this " }
67- if (matchResult.groups[" wildcard" ] != null ) {
81+ groups.add(groupName)
82+ if (matchResult.groups[" wildcard" ]?.value != null ) {
6883 " (?<$groupName >.+)"
6984 } else {
7085 " (?<$groupName >[^/]*)"
@@ -74,8 +89,25 @@ public class UriTemplateFeatureKey(override val key: String) : FeatureKey<Regex>
7489 }
7590
7691 override fun matches (input : String ): Boolean = value.matches(input)
92+
93+ override fun extractArguments (input : String ): TemplateValues {
94+ val matchGroups = value.matchEntire(input)?.groups
95+ return groups.mapNotNull { groupName ->
96+ val groupValue = matchGroups?.get(groupName)?.value
97+ if (groupValue != null ) {
98+ groupName to groupValue
99+ } else {
100+ null
101+ }
102+ }.toMap()
103+ }
77104}
78105
106+ /* *
107+ * A map of template variable names to their corresponding values extracted from an input string based on a URI template.
108+ */
109+ public typealias TemplateValues = Map <String , String >
110+
79111/* *
80112 * The [FeatureKey] used for [Tool]s.
81113 */
@@ -148,7 +180,7 @@ public data class RegisteredResource(
148180 */
149181public data class RegisteredResourceTemplate (
150182 val resourceTemplate : ResourceTemplate ,
151- val readHandler : suspend (ReadResourceRequest ) -> ReadResourceResult ,
183+ val readHandler : suspend (ReadResourceRequest , TemplateValues ) -> ReadResourceResult ,
152184) : Feature<ResourceTemplateFeatureKey> {
153185 override val key: ResourceTemplateFeatureKey = UriTemplateFeatureKey (resourceTemplate.uriTemplate)
154186}
0 commit comments