pub static MCP_ALIASES: &[(&str, &str)] = &[
("filesystem", "@modelcontextprotocol/server-filesystem"),
("memory", "@modelcontextprotocol/server-memory"),
("puppeteer", "@modelcontextprotocol/server-puppeteer"),
("brave-search", "@modelcontextprotocol/server-brave-search"),
("google-maps", "@modelcontextprotocol/server-google-maps"),
("fetch", "@modelcontextprotocol/server-fetch"),
("github", "@modelcontextprotocol/server-github"),
("gitlab", "@modelcontextprotocol/server-gitlab"),
("neo4j", "@neo4j/mcp-neo4j"),
("postgres", "@modelcontextprotocol/server-postgres"),
("mysql", "mcp-server-mysql"),
("sqlite", "@anthropic/mcp-server-sqlite"),
("mongodb", "mcp-mongodb"),
("redis", "mcp-redis"),
("supabase", "mcp-supabase"),
("neon", "@neondatabase/mcp-server-neon"),
("perplexity", "perplexity-mcp"),
("firecrawl", "firecrawl-mcp"),
("brave", "@anthropic/mcp-server-brave-search"),
("exa", "exa-mcp-server"),
("tavily", "tavily-mcp"),
("serper", "serper-mcp"),
("searchapi", "searchapi-mcp"),
("bing", "bing-mcp"),
("linear", "mcp-linear"),
("sentry", "@modelcontextprotocol/server-sentry"),
("raygun", "raygun-mcp"),
("buildkite", "buildkite-mcp"),
("circleci", "circleci-mcp"),
("vercel", "vercel-mcp"),
("cloudflare", "cloudflare-mcp"),
("aws", "aws-mcp"),
("slack", "@anthropic/mcp-server-slack"),
("google-drive", "@anthropic/mcp-server-google-drive"),
("notion", "notion-mcp"),
("airtable", "airtable-mcp"),
("todoist", "todoist-mcp"),
("asana", "asana-mcp"),
("trello", "trello-mcp"),
("monday", "monday-mcp"),
("langchain", "langchain-mcp"),
("e2b", "@e2b/mcp-server"),
(
"sequential-thinking",
"@modelcontextprotocol/server-sequential-thinking",
),
("context7", "context7-mcp"),
("21st", "21st-mcp"),
("supadata", "supadata-mcp"),
("dataforseo", "dataforseo-mcp"),
("ahrefs", "ahrefs-mcp"),
];
pub fn resolve_alias(alias: &str) -> Option<&'static str> {
MCP_ALIASES
.iter()
.find(|(a, _)| *a == alias)
.map(|(_, pkg)| *pkg)
}
pub fn is_alias(name: &str) -> bool {
MCP_ALIASES.iter().any(|(a, _)| *a == name)
}
pub fn list_aliases() -> Vec<&'static str> {
MCP_ALIASES.iter().map(|(a, _)| *a).collect()
}
pub fn aliases_by_category(category: &str) -> Vec<(&'static str, &'static str)> {
let (start, end) = match category {
"anthropic" => (0, 8),
"databases" => (8, 16),
"search" => (16, 24),
"developer" => (24, 32),
"productivity" => (32, 40),
"ai" => (40, 48),
_ => return vec![],
};
MCP_ALIASES[start..end.min(MCP_ALIASES.len())].to_vec()
}
pub fn resolve_name(name: &str) -> Option<String> {
if name.starts_with('@') || name.contains('/') {
return Some(name.to_string());
}
resolve_alias(name).map(|s| s.to_string())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mcp_aliases_count() {
assert_eq!(MCP_ALIASES.len(), 48);
}
#[test]
fn test_resolve_alias() {
assert_eq!(resolve_alias("neo4j"), Some("@neo4j/mcp-neo4j"));
assert_eq!(
resolve_alias("github"),
Some("@modelcontextprotocol/server-github")
);
assert_eq!(resolve_alias("perplexity"), Some("perplexity-mcp"));
assert_eq!(resolve_alias("slack"), Some("@anthropic/mcp-server-slack"));
assert_eq!(resolve_alias("nonexistent"), None);
}
#[test]
fn test_is_alias() {
assert!(is_alias("neo4j"));
assert!(is_alias("github"));
assert!(is_alias("perplexity"));
assert!(!is_alias("@neo4j/mcp-neo4j"));
assert!(!is_alias("unknown"));
}
#[test]
fn test_list_aliases() {
let aliases = list_aliases();
assert_eq!(aliases.len(), 48);
assert!(aliases.contains(&"neo4j"));
assert!(aliases.contains(&"github"));
assert!(aliases.contains(&"perplexity"));
}
#[test]
fn test_aliases_by_category() {
let anthropic = aliases_by_category("anthropic");
assert_eq!(anthropic.len(), 8);
assert!(anthropic.iter().any(|(a, _)| *a == "filesystem"));
assert!(anthropic.iter().any(|(a, _)| *a == "github"));
let databases = aliases_by_category("databases");
assert_eq!(databases.len(), 8);
assert!(databases.iter().any(|(a, _)| *a == "neo4j"));
assert!(databases.iter().any(|(a, _)| *a == "postgres"));
let unknown = aliases_by_category("unknown");
assert!(unknown.is_empty());
}
#[test]
fn test_resolve_name() {
assert_eq!(resolve_name("neo4j"), Some("@neo4j/mcp-neo4j".to_string()));
assert_eq!(
resolve_name("@custom/server"),
Some("@custom/server".to_string())
);
assert_eq!(
resolve_name("some-org/server"),
Some("some-org/server".to_string())
);
assert_eq!(resolve_name("unknown-thing"), None);
}
#[test]
fn test_all_aliases_have_valid_packages() {
for (alias, package) in MCP_ALIASES {
assert!(!alias.is_empty(), "Alias should not be empty");
assert!(!package.is_empty(), "Package should not be empty");
assert!(
!alias.contains('/'),
"Alias '{}' should not contain '/'",
alias
);
assert!(
!alias.starts_with('@'),
"Alias '{}' should not start with '@'",
alias
);
}
}
#[test]
fn test_no_duplicate_aliases() {
let aliases: Vec<_> = MCP_ALIASES.iter().map(|(a, _)| *a).collect();
let unique: std::collections::HashSet<_> = aliases.iter().collect();
assert_eq!(
aliases.len(),
unique.len(),
"Duplicate aliases found in MCP_ALIASES"
);
}
}