SearchUserProvidedModule
Analyze Terraform registry modules to understand inputs, outputs, and usage for AWS infrastructure development.
Instructions
Search for a user-provided Terraform registry module and understand its inputs, outputs, and usage.
This tool takes a Terraform registry module URL and analyzes its input variables,
output variables, README, and other details to provide comprehensive information
about the module.
The module URL should be in the format "namespace/name/provider" (e.g., "hashicorp/consul/aws")
or "registry.terraform.io/namespace/name/provider".
Examples:
- To search for the HashiCorp Consul module:
search_user_provided_module(module_url='hashicorp/consul/aws')
- To search for a specific version of a module:
search_user_provided_module(module_url='terraform-aws-modules/vpc/aws', version='3.14.0')
- To search for a module with specific variables:
search_user_provided_module(
module_url='terraform-aws-modules/eks/aws',
variables={'cluster_name': 'my-cluster', 'vpc_id': 'vpc-12345'}
)
Parameters:
module_url: URL or identifier of the Terraform module (e.g., "hashicorp/consul/aws")
version: Optional specific version of the module to analyze
variables: Optional dictionary of variables to use when analyzing the module
Returns:
A SearchUserProvidedModuleResult object containing module information
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| module_url | Yes | URL or identifier of the Terraform module (e.g., "hashicorp/consul/aws") | |
| version | No | Specific version of the module to analyze | |
| variables | No | Variables to use when analyzing the module |
Implementation Reference
- Core handler implementation that parses module URL, fetches details from Terraform Registry API and GitHub, extracts variables and outputs, processes README, and returns structured result.async def search_user_provided_module_impl( request: SearchUserProvidedModuleRequest, ) -> SearchUserProvidedModuleResult: """Analyze a Terraform module from the registry. This tool takes a Terraform registry module URL and analyzes its input variables, output variables, README, and other details to provide comprehensive information about the module. Parameters: request: Details about the Terraform module to analyze Returns: A SearchUserProvidedModuleResult object containing module information """ logger.info(f'Analyzing Terraform module: {request.module_url}') try: # Parse the module URL to extract namespace, name, and provider module_parts = parse_module_url(request.module_url) if not module_parts: return SearchUserProvidedModuleResult( status='error', module_name='unknown', module_url=request.module_url, module_version='unknown', module_description='', variables=[], outputs=[], readme_content=None, error_message=f'Invalid module URL format: {request.module_url}. Expected format: [namespace]/[name]/[provider] or registry.terraform.io/[namespace]/[name]/[provider]', ) namespace, name, provider = module_parts # Fetch module details from Terraform Registry module_details = await get_module_details(namespace, name, provider, request.version) if not module_details: return SearchUserProvidedModuleResult( status='error', module_name=name, module_url=request.module_url, module_version=request.version or 'latest', module_description='', variables=[], outputs=[], readme_content=None, error_message=f'Failed to fetch module details from Terraform Registry: {request.module_url}', ) # Extract module information module_version = module_details.get('version', request.version or 'latest') module_description = clean_description(module_details.get('description', '')) readme_content = module_details.get('readme_content', '') # Get variables and outputs variables = [] outputs = [] # Extract variables from module details if 'variables' in module_details and module_details['variables']: variables = [TerraformVariable(**var_data) for var_data in module_details['variables']] elif 'root' in module_details and 'inputs' in module_details['root']: # Extract from registry API format for var_name, var_data in module_details['root']['inputs'].items(): variables.append( TerraformVariable( name=var_name, type=var_data.get('type', ''), description=var_data.get('description', ''), default=var_data.get('default'), required=var_data.get('required', True), ) ) # Extract outputs from module details if 'outputs' in module_details and module_details['outputs']: outputs = [ TerraformOutput(name=output['name'], description=output.get('description', '')) for output in module_details['outputs'] ] elif 'root' in module_details and 'outputs' in module_details['root']: # Extract from registry API format for output_name, output_data in module_details['root']['outputs'].items(): outputs.append( TerraformOutput( name=output_name, description=output_data.get('description', ''), ) ) elif readme_content: # Try to extract outputs from README extracted_outputs = extract_outputs_from_readme(readme_content) if extracted_outputs: outputs = [ TerraformOutput(name=output['name'], description=output.get('description', '')) for output in extracted_outputs ] # Create the result result = SearchUserProvidedModuleResult( status='success', module_name=name, module_url=request.module_url, module_version=module_version, module_description=module_description, variables=variables, outputs=outputs, readme_content=readme_content, error_message=None, ) return result except Exception as e: logger.error(f'Error analyzing Terraform module: {e}') logger.debug(f'Stack trace: {traceback.format_exc()}') return SearchUserProvidedModuleResult( status='error', module_name=request.module_url.split('/')[-2] if '/' in request.module_url else 'unknown', module_url=request.module_url, module_version=request.version or 'latest', module_description='', variables=[], outputs=[], readme_content=None, error_message=f'Error analyzing Terraform module: {str(e)}', )
- awslabs/terraform_mcp_server/server.py:341-387 (registration)MCP tool registration decorator and thin wrapper function that constructs the request and delegates to the impl handler.@mcp.tool(name='SearchUserProvidedModule') async def search_user_provided_module( module_url: str = Field( ..., description='URL or identifier of the Terraform module (e.g., "hashicorp/consul/aws")' ), version: Optional[str] = Field(None, description='Specific version of the module to analyze'), variables: Optional[Dict[str, Any]] = Field( None, description='Variables to use when analyzing the module' ), ) -> SearchUserProvidedModuleResult: """Search for a user-provided Terraform registry module and understand its inputs, outputs, and usage. This tool takes a Terraform registry module URL and analyzes its input variables, output variables, README, and other details to provide comprehensive information about the module. The module URL should be in the format "namespace/name/provider" (e.g., "hashicorp/consul/aws") or "registry.terraform.io/namespace/name/provider". Examples: - To search for the HashiCorp Consul module: search_user_provided_module(module_url='hashicorp/consul/aws') - To search for a specific version of a module: search_user_provided_module(module_url='terraform-aws-modules/vpc/aws', version='3.14.0') - To search for a module with specific variables: search_user_provided_module( module_url='terraform-aws-modules/eks/aws', variables={'cluster_name': 'my-cluster', 'vpc_id': 'vpc-12345'} ) Parameters: module_url: URL or identifier of the Terraform module (e.g., "hashicorp/consul/aws") version: Optional specific version of the module to analyze variables: Optional dictionary of variables to use when analyzing the module Returns: A SearchUserProvidedModuleResult object containing module information """ request = SearchUserProvidedModuleRequest( module_url=module_url, version=version, variables=variables, ) return await search_user_provided_module_impl(request)
- Pydantic model defining the input schema for the tool request.class SearchUserProvidedModuleRequest(BaseModel): """Request model for searching user-provided Terraform modules. Attributes: module_url: URL of the Terraform module in the registry (e.g., 'hashicorp/consul/aws'). version: Optional specific version of the module to analyze. variables: Optional dictionary of variables to use when analyzing the module. """ module_url: str = Field( ..., description='URL or identifier of the Terraform module (e.g., "hashicorp/consul/aws")' ) version: Optional[str] = Field(None, description='Specific version of the module to analyze') variables: Optional[Dict[str, Any]] = Field( None, description='Variables to use when analyzing the module' )
- Pydantic model defining the output schema/result structure for the tool.class SearchUserProvidedModuleResult(BaseModel): """Result model for searching user-provided Terraform modules. Attributes: status: Execution status (success/error). module_name: Name of the analyzed module. module_url: URL of the module in the registry. module_version: Version of the module that was analyzed. module_description: Description of the module. variables: List of variables defined by the module. outputs: List of outputs provided by the module. readme_content: The README content of the module. error_message: Optional error message if execution failed. """ status: Literal['success', 'error'] module_name: str module_url: str module_version: str module_description: str variables: List[TerraformVariable] = Field([], description='Variables defined by the module') outputs: List[TerraformOutput] = Field([], description='Outputs provided by the module') readme_content: Optional[str] = Field(None, description='README content of the module') error_message: Optional[str] = Field(None, description='Error message if execution failed')
- Helper function to parse the module URL into namespace, name, and provider components.def parse_module_url(module_url: str) -> Optional[Tuple[str, str, str]]: """Parse a Terraform module URL to extract namespace, name, and provider. Args: module_url: The module URL or identifier (e.g., "hashicorp/consul/aws" or "registry.terraform.io/hashicorp/consul/aws") Returns: Tuple containing (namespace, name, provider) or None if invalid format """ # First, handle registry.terraform.io URLs (with or without scheme) parsed_url = None # If URL has a scheme (http://, https://) if '://' in module_url: parsed_url = urlparse(module_url) # For URLs without scheme, add a dummy scheme to enable proper URL parsing else: parsed_url = urlparse(f'https://{module_url}') # Check if this is a registry.terraform.io URL if parsed_url.netloc == 'registry.terraform.io': # Extract path and remove leading slash path = parsed_url.path.lstrip('/') parts = path.split('/') else: # Simple module path format (namespace/name/provider) parts = module_url.split('/') # Ensure we have at least namespace/name/provider if len(parts) < 3: return None namespace = parts[0] name = parts[1] provider = parts[2] return namespace, name, provider