@bschauer/webtools-mcp-server
Version:
MCP server providing web analysis tools including screenshot, debug, performance, security, accessibility, SEO, and asset optimization capabilities
373 lines (330 loc) • 11.5 kB
JavaScript
/**
* 📋 Resource Configuration for All WebTools MCP Server Tools
*
* This file defines how each tool should handle resource creation.
* The configuration is used by the ResourceManager to automatically
* convert tool outputs to stored resources.
*
* 🎯 Zero Code Duplication Strategy:
* Instead of modifying each tool individually, we configure resource
* behavior declaratively here, then apply it via middleware.
*/
import { ResourceConfigBuilder } from '../utils/resource-manager.js';
/**
* 🌐 Web Content Tools
* Tools that fetch and process web content
*/
export const WEB_TOOLS_CONFIG = {
// HTML content extraction
webtool_gethtml: ResourceConfigBuilder
.for('webtool_gethtml')
.addOutput('content[0].text', 'html', {
uriType: 'web',
nameTemplate: '{urlForDisplay} - HTML Content ({timestamp})',
descriptionTemplate: 'HTML content from {fullUrl}{urlPath} loaded at {timestamp}'
})
.replaceWithSummary(true)
.build(),
// Page content in markdown format
webtool_readpage: ResourceConfigBuilder
.for('webtool_readpage')
.addOutput('content[0].text', 'markdown', {
uriType: 'web',
nameTemplate: '{urlForDisplay} - Page Content ({timestamp})',
descriptionTemplate: 'Markdown content from {fullUrl}{urlPath} processed at {timestamp}'
})
.replaceWithSummary(true)
.build()
};
/**
* 📸 Visual Tools
* Tools that capture visual content
*/
export const VISUAL_TOOLS_CONFIG = {
// Screenshot capture
webtool_screenshot: ResourceConfigBuilder
.for('webtool_screenshot')
.addOutput('content[0]', 'image', {
uriType: 'image',
nameTemplate: '{urlForDisplay} - Screenshot ({timestamp})',
descriptionTemplate: 'Screenshot of {fullUrl}{urlPath} captured at {timestamp}'
})
.build()
};
/**
* 🐞 Debug and Analysis Tools
* Tools that provide debugging and analysis information
*/
export const DEBUG_TOOLS_CONFIG = {
// Debug information with console, network, errors
webtool_debug: ResourceConfigBuilder
.for('webtool_debug')
.addOutput('content[0].text', 'markdown', {
uriType: 'debug',
nameTemplate: '{urlForDisplay} - Debug Report ({timestamp})',
descriptionTemplate: 'Debug analysis of {fullUrl}{urlPath} generated at {timestamp}'
})
.build()
};
/**
* ⚡ Performance Analysis Tools
* Tools that analyze website performance and optimization
*/
export const PERFORMANCE_TOOLS_CONFIG = {
// Lighthouse audit results
webtool_lighthouse: ResourceConfigBuilder
.for('webtool_lighthouse')
.addOutput('content[0].text', 'markdown', {
uriType: 'performance',
nameTemplate: '{urlForDisplay} - Lighthouse Report ({timestamp})',
descriptionTemplate: 'Lighthouse audit of {fullUrl}{urlPath} conducted at {timestamp}'
})
.build(),
// Performance trace analysis
webtool_performance_trace: ResourceConfigBuilder
.for('webtool_performance_trace')
.addOutput('content[0].text', 'json', {
uriType: 'performance',
nameTemplate: '{urlForDisplay} - Performance Trace ({timestamp})',
descriptionTemplate: 'Performance trace of {fullUrl}{urlPath} captured at {timestamp}'
})
.build(),
// Code coverage analysis
webtool_coverage_analysis: ResourceConfigBuilder
.for('webtool_coverage_analysis')
.addOutput('content[0].text', 'json', {
uriType: 'performance',
nameTemplate: '{urlForDisplay} - Coverage Analysis ({timestamp})',
descriptionTemplate: 'Coverage analysis of {fullUrl}{urlPath} analyzed at {timestamp}'
})
.build(),
// Core Web Vitals analysis
webtool_web_vitals: ResourceConfigBuilder
.for('webtool_web_vitals')
.addOutput('content[0].text', 'json', {
uriType: 'performance',
nameTemplate: '{urlForDisplay} - Web Vitals ({timestamp})',
descriptionTemplate: 'Web Vitals of {fullUrl}{urlPath} measured at {timestamp}'
})
.build(),
// Network activity monitoring
webtool_network_monitor: ResourceConfigBuilder
.for('webtool_network_monitor')
.addOutput('content[0].text', 'json', {
uriType: 'performance',
nameTemplate: '{urlForDisplay} - Network Monitor ({timestamp})',
descriptionTemplate: 'Network analysis of {fullUrl}{urlPath} monitored at {timestamp}'
})
.build(),
// Performance testing across conditions
webtool_performance_test: ResourceConfigBuilder
.for('webtool_performance_test')
.addOutput('content[0].text', 'json', {
uriType: 'performance',
nameTemplate: '{urlForDisplay} - Performance Test ({timestamp})',
descriptionTemplate: 'Performance test of {fullUrl}{urlPath} executed at {timestamp}'
})
.build()
};
/**
* 📊 Consolidated Configuration
* All tool configurations combined for easy import
*/
export const ALL_TOOLS_CONFIG = {
...WEB_TOOLS_CONFIG,
...VISUAL_TOOLS_CONFIG,
...DEBUG_TOOLS_CONFIG,
...PERFORMANCE_TOOLS_CONFIG
};
/**
* 🎯 Quick Configuration Presets
* Pre-defined configuration sets for common scenarios
*/
export const CONFIG_PRESETS = {
// Enable resources for all tools
ALL_ENABLED: Object.fromEntries(
Object.entries(ALL_TOOLS_CONFIG).map(([toolName, config]) => [
toolName, { ...config, enabled: true }
])
),
// Enable only web content tools
WEB_ONLY: Object.fromEntries(
Object.entries(WEB_TOOLS_CONFIG).map(([toolName, config]) => [
toolName, { ...config, enabled: true }
])
),
// Enable only performance tools
PERFORMANCE_ONLY: Object.fromEntries(
Object.entries(PERFORMANCE_TOOLS_CONFIG).map(([toolName, config]) => [
toolName, { ...config, enabled: true }
])
),
// Enable only visual tools
VISUAL_ONLY: Object.fromEntries(
Object.entries(VISUAL_TOOLS_CONFIG).map(([toolName, config]) => [
toolName, { ...config, enabled: true }
])
),
// Minimal set - just HTML and screenshots
MINIMAL: {
webtool_gethtml: { ...WEB_TOOLS_CONFIG.webtool_gethtml, enabled: true },
webtool_screenshot: { ...VISUAL_TOOLS_CONFIG.webtool_screenshot, enabled: true }
}
};
/**
* 🔧 Configuration Utilities
*/
export class ResourceConfigManager {
constructor() {
this.activeConfig = {};
}
/**
* Load a preset configuration
*/
loadPreset(presetName) {
if (!CONFIG_PRESETS[presetName]) {
throw new Error(`Unknown preset: ${presetName}`);
}
this.activeConfig = { ...CONFIG_PRESETS[presetName] };
return this;
}
/**
* Enable resource storage for specific tools
*/
enableTools(...toolNames) {
for (const toolName of toolNames) {
if (ALL_TOOLS_CONFIG[toolName]) {
this.activeConfig[toolName] = {
...ALL_TOOLS_CONFIG[toolName],
enabled: true
};
}
}
return this;
}
/**
* Disable resource storage for specific tools
*/
disableTools(...toolNames) {
for (const toolName of toolNames) {
if (this.activeConfig[toolName]) {
this.activeConfig[toolName].enabled = false;
}
}
return this;
}
/**
* Override configuration for specific tools
*/
overrideConfig(toolName, configOverrides) {
if (this.activeConfig[toolName]) {
this.activeConfig[toolName] = {
...this.activeConfig[toolName],
...configOverrides
};
}
return this;
}
/**
* Get the active configuration
*/
getConfig() {
return this.activeConfig;
}
/**
* Get configuration for a specific tool
*/
getToolConfig(toolName) {
return this.activeConfig[toolName];
}
/**
* Check if a tool has resource storage enabled
*/
isToolEnabled(toolName) {
return this.activeConfig[toolName]?.enabled === true;
}
/**
* Get list of enabled tools
*/
getEnabledTools() {
return Object.entries(this.activeConfig)
.filter(([, config]) => config.enabled)
.map(([toolName]) => toolName);
}
/**
* Get summary of configuration
*/
getConfigSummary() {
const enabled = this.getEnabledTools();
const disabled = Object.keys(ALL_TOOLS_CONFIG).filter(
toolName => !enabled.includes(toolName)
);
return {
totalTools: Object.keys(ALL_TOOLS_CONFIG).length,
enabledCount: enabled.length,
disabledCount: disabled.length,
enabledTools: enabled,
disabledTools: disabled
};
}
}
/**
* 🎛️ Environment-based Configuration
* Different configurations for different environments
*/
export function getConfigForEnvironment(env = process.env.NODE_ENV) {
switch (env) {
case 'development':
// In development, enable all tools for testing
return CONFIG_PRESETS.ALL_ENABLED;
case 'production':
// In production, be more conservative
return CONFIG_PRESETS.WEB_ONLY;
case 'testing':
// In testing, minimal set
return CONFIG_PRESETS.MINIMAL;
default:
// Default to all enabled
return CONFIG_PRESETS.ALL_ENABLED;
}
}
/**
* 📄 Export default configuration based on environment
*/
export const DEFAULT_CONFIG = getConfigForEnvironment();
/**
* 🔍 Configuration Validation
*/
export function validateConfig(config) {
const errors = [];
for (const [toolName, toolConfig] of Object.entries(config)) {
// Check if tool exists in our definitions
if (!ALL_TOOLS_CONFIG[toolName]) {
errors.push(`Unknown tool: ${toolName}`);
continue;
}
// Check required fields
if (typeof toolConfig.enabled !== 'boolean') {
errors.push(`Tool ${toolName}: 'enabled' must be a boolean`);
}
if (toolConfig.enabled && (!toolConfig.outputs || !Array.isArray(toolConfig.outputs))) {
errors.push(`Tool ${toolName}: 'outputs' must be an array when enabled`);
}
// Validate outputs
if (toolConfig.outputs) {
for (let i = 0; i < toolConfig.outputs.length; i++) {
const output = toolConfig.outputs[i];
if (!output.contentPath) {
errors.push(`Tool ${toolName}, output ${i}: 'contentPath' is required`);
}
if (!output.contentType) {
errors.push(`Tool ${toolName}, output ${i}: 'contentType' is required`);
}
}
}
}
if (errors.length > 0) {
throw new Error(`Configuration validation failed:\n${errors.join('\n')}`);
}
return true;
}