@crazyrabbitltc/railway-mcp
Version:
Railway MCP Server - 146+ tools with 100% Railway API coverage, comprehensive MCP testing framework, and real infrastructure management through AI assistants. Enhanced version with enterprise features, based on original work by Jason Tan.
159 lines (158 loc) • 5.47 kB
JavaScript
/**
* Tool filtering utilities for Railway MCP server
* Handles environment variable parsing and tool filtering logic
*/
import { TOOL_DEFINITIONS, CATEGORY_PRESETS, isValidTool, isValidCategory } from '../config/tool-categories.js';
/**
* Parse the RAILWAY_TOOLS_FILTER environment variable
* Supports formats:
* - "simple" (single category)
* - "simple,deployment" (multiple categories)
* - "project_list,service_create" (specific tools)
* - "simple,project_delete" (mixed categories and tools)
*/
export function parseToolFilter(filterString) {
// Default configuration - no filtering
if (!filterString || filterString.trim() === '') {
return {
enabled: false,
categories: [],
specificTools: [],
filteredTools: new Set(Object.keys(TOOL_DEFINITIONS))
};
}
const items = filterString.split(',').map(item => item.trim()).filter(Boolean);
const categories = [];
const specificTools = [];
const warnings = [];
// Classify each item as category or specific tool
for (const item of items) {
if (isValidCategory(item)) {
categories.push(item);
}
else if (isValidTool(item)) {
specificTools.push(item);
}
else {
warnings.push(`Unknown category or tool: "${item}"`);
}
}
// Log warnings for invalid items
if (warnings.length > 0) {
console.error('Tool filter warnings:', warnings.join(', '));
}
// Build the final filtered tool set
const filteredTools = new Set();
// Add tools from categories
for (const category of categories) {
for (const tool of CATEGORY_PRESETS[category].tools) {
filteredTools.add(tool);
}
}
// Add specific tools
for (const tool of specificTools) {
filteredTools.add(tool);
}
// If no valid items found, fall back to all tools
if (filteredTools.size === 0) {
console.error('No valid tools or categories found in filter, enabling all tools');
for (const tool of Object.keys(TOOL_DEFINITIONS)) {
filteredTools.add(tool);
}
}
return {
enabled: true,
categories,
specificTools,
filteredTools
};
}
/**
* Check if a tool should be included based on the current filter configuration
*/
export function shouldIncludeTool(toolName, config) {
if (!config.enabled) {
return true; // No filtering active
}
return config.filteredTools.has(toolName);
}
/**
* Get filtering statistics for logging
*/
export function getFilterStats(config) {
if (!config.enabled) {
return 'No tool filtering active - all tools enabled';
}
const totalTools = Object.keys(TOOL_DEFINITIONS).length;
const enabledTools = config.filteredTools.size;
const percentage = Math.round((enabledTools / totalTools) * 100);
const parts = [];
if (config.categories.length > 0) {
parts.push(`categories: ${config.categories.join(', ')}`);
}
if (config.specificTools.length > 0) {
parts.push(`tools: ${config.specificTools.join(', ')}`);
}
return `Tool filtering active: ${enabledTools}/${totalTools} tools (${percentage}%) - ${parts.join(' + ')}`;
}
/**
* Initialize tool filtering from environment variables
*/
export function initializeToolFilter() {
const filterString = process.env.RAILWAY_TOOLS_FILTER;
const config = parseToolFilter(filterString);
// Log filter status
console.error(getFilterStats(config));
return config;
}
/**
* Get example filter configurations for documentation
*/
export function getFilterExamples() {
return {
'Basic users': 'simple',
'Developers': 'intermediate,deployment',
'DevOps teams': 'pro',
'Monitoring focus': 'monitoring,simple',
'Data management': 'data,core',
'Enterprise setup': 'enterprise,team',
'Custom selection': 'project_list,service_create,deployment_info',
'Mixed approach': 'simple,backup-restore,security-audit-logs'
};
}
/**
* Validate filter configuration and provide helpful error messages
*/
export function validateFilterConfig(filterString) {
const errors = [];
const suggestions = [];
if (!filterString.trim()) {
return { valid: true, errors: [], suggestions: ['Empty filter disables filtering (all tools enabled)'] };
}
const items = filterString.split(',').map(item => item.trim()).filter(Boolean);
let hasValidItems = false;
for (const item of items) {
if (isValidCategory(item) || isValidTool(item)) {
hasValidItems = true;
}
else {
errors.push(`Invalid category or tool: "${item}"`);
// Suggest similar categories
const availableCategories = Object.keys(CATEGORY_PRESETS);
const similarCategory = availableCategories.find(cat => cat.toLowerCase().includes(item.toLowerCase()) ||
item.toLowerCase().includes(cat.toLowerCase()));
if (similarCategory) {
suggestions.push(`Did you mean "${similarCategory}"?`);
}
}
}
if (!hasValidItems) {
errors.push('No valid categories or tools found');
suggestions.push('Available categories: ' + Object.keys(CATEGORY_PRESETS).join(', '));
}
return {
valid: hasValidItems,
errors,
suggestions
};
}