""" Web Tools for MCP """ import urllib.parse from typing import Dict, Any, List, Optional from ..core.types import MCPTool class WebTools: """Collection of web-related tools""" @staticmethod def get_tools() -> List[MCPTool]: """Get all web tools""" return [ WebTools._create_url_encode_tool(), WebTools._create_url_decode_tool(), WebTools._create_parse_url_tool(), WebTools._create_validate_email_tool(), WebTools._create_extract_domain_tool(), ] @staticmethod def _create_url_encode_tool() -> MCPTool: """Create URL encode tool""" async def url_encode(text: str) -> str: """URL encode a string""" return urllib.parse.quote(text) return MCPTool( name="url_encode", description="URL encode a string for safe transmission", input_schema={ "type": "object", "properties": { "text": {"type": "string", "description": "Text to URL encode"}, }, "required": ["text"], }, handler=url_encode, ) @staticmethod def _create_url_decode_tool() -> MCPTool: """Create URL decode tool""" async def url_decode(encoded_text: str) -> str: """URL decode a string""" try: return urllib.parse.unquote(encoded_text) except Exception: raise ValueError("Invalid URL encoded string") return MCPTool( name="url_decode", description="URL decode a previously encoded string", input_schema={ "type": "object", "properties": { "encoded_text": {"type": "string", "description": "URL encoded text to decode"}, }, "required": ["encoded_text"], }, handler=url_decode, ) @staticmethod def _create_parse_url_tool() -> MCPTool: """Create URL parsing tool""" async def parse_url(url: str) -> Dict[str, str]: """Parse a URL and return its components""" try: parsed = urllib.parse.urlparse(url) return { "scheme": parsed.scheme, "netloc": parsed.netloc, "hostname": parsed.hostname, "port": str(parsed.port) if parsed.port else "", "path": parsed.path, "query": parsed.query, "fragment": parsed.fragment, } except Exception: raise ValueError("Invalid URL format") return MCPTool( name="parse_url", description="Parse a URL and return its components (scheme, host, path, etc.)", input_schema={ "type": "object", "properties": { "url": {"type": "string", "description": "URL to parse"}, }, "required": ["url"], }, handler=parse_url, ) @staticmethod def _create_validate_email_tool() -> MCPTool: """Create email validation tool""" async def validate_email(email: str) -> Dict[str, Any]: """Validate an email address format""" import re email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' is_valid = bool(re.match(email_pattern, email)) # Extract domain if is_valid and '@' in email: domain = email.split('@')[1] else: domain = "" return { "email": email, "is_valid": is_valid, "domain": domain, } return MCPTool( name="validate_email", description="Validate an email address format and extract domain", input_schema={ "type": "object", "properties": { "email": {"type": "string", "description": "Email address to validate"}, }, "required": ["email"], }, handler=validate_email, ) @staticmethod def _create_extract_domain_tool() -> MCPTool: """Create domain extraction tool""" async def extract_domain(url: str) -> str: """Extract the domain from a URL""" try: parsed = urllib.parse.urlparse(url) if parsed.hostname: return parsed.hostname else: # Fallback for URLs without scheme url_with_scheme = "http://" + url if "://" not in url else url parsed = urllib.parse.urlparse(url_with_scheme) return parsed.hostname or "" except Exception: return "" return MCPTool( name="extract_domain", description="Extract the domain name from a URL", input_schema={ "type": "object", "properties": { "url": {"type": "string", "description": "URL to extract domain from"}, }, "required": ["url"], }, handler=extract_domain, )