Fix full-string MCP regex matching

This commit is contained in:
Felix Xia
2026-06-23 17:22:35 +01:00
parent 251056df68
commit d26a5d52fb
2 changed files with 17 additions and 6 deletions

View File

@@ -13,23 +13,25 @@ pub enum McpServerValueMatcher {
}
impl McpServerValueMatcher {
fn compile_full_regex(expression: &str) -> Result<Regex, String> {
Regex::new(&format!(r"\A(?:{expression})\z"))
.map_err(|err| format!("invalid regex `{expression}`: {err}"))
}
fn validate(&self) -> Result<(), String> {
let Self::Regex { expression } = self else {
return Ok(());
};
Regex::new(expression)
.map(|_| ())
.map_err(|err| format!("invalid regex `{expression}`: {err}"))
Self::compile_full_regex(expression).map(|_| ())
}
fn matches(&self, candidate: &str) -> bool {
match self {
Self::Exact { value } => candidate == value,
Self::Prefix { value } => candidate.starts_with(value),
Self::Regex { expression } => Regex::new(expression)
Self::Regex { expression } => Self::compile_full_regex(expression)
.ok()
.and_then(|regex| regex.find(candidate))
.is_some_and(|matched| matched.start() == 0 && matched.end() == candidate.len()),
.is_some_and(|regex| regex.is_match(candidate)),
}
}
}

View File

@@ -72,6 +72,15 @@ fn regex_matcher_requires_a_full_value_match() {
assert!(!matcher.matches("prefix-mcp"));
}
#[test]
fn regex_matcher_allows_a_later_alternative_to_match_the_full_value() {
let matcher = McpServerValueMatcher::Regex {
expression: r"https://api\.example\.com|https://api\.example\.com/mcp".to_string(),
};
assert!(matcher.matches("https://api.example.com/mcp"));
}
#[test]
fn matcher_deserializes_command_and_url_shapes() {
let command: McpServerMatcher = toml::from_str(