Skip to main content
Glama
stv-io

AWS Terraform MCP Server

by stv-io

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
NameRequiredDescriptionDefault
module_urlYesURL or identifier of the Terraform module (e.g., "hashicorp/consul/aws")
versionNoSpecific version of the module to analyze
variablesNoVariables to use when analyzing the module

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
statusYes
outputsNoOutputs provided by the module
variablesNoVariables defined by the module
module_urlYes
module_nameYes
error_messageNoError message if execution failed
module_versionYes
readme_contentNoREADME content of the module
module_descriptionYes

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)}',
            )
  • 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
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It describes what the tool does (analyzes modules) and mentions the return type, but does not cover aspects like rate limits, authentication needs, or error handling. It adds some context but lacks comprehensive behavioral traits beyond the basic operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured and front-loaded with the purpose, followed by examples and parameter details. It is appropriately sized, but could be slightly more concise by reducing redundancy in parameter explanations. Every sentence adds value, though some information overlaps with the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity, 100% schema coverage, and the presence of an output schema, the description is mostly complete. It explains the purpose, usage, and parameters adequately, but could improve by addressing behavioral aspects like permissions or limitations. The output schema reduces the need to detail return values, making it sufficient but not exhaustive.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all parameters. The description adds minimal value by listing parameters and providing examples, but does not explain semantics beyond what the schema provides, such as format details or constraints. The baseline score of 3 is appropriate as the schema handles most documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Search for a user-provided Terraform registry module and understand its inputs, outputs, and usage.' It specifies the verb ('search'), resource ('Terraform registry module'), and scope ('analyzes its input variables, output variables, README, and other details'), distinguishing it from sibling tools like ExecuteTerraformCommand or RunCheckovScan, which perform different actions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use this tool, such as analyzing module details, but does not explicitly state when not to use it or name specific alternatives. It implies usage for understanding module structures, which helps differentiate from siblings like SearchAwsProviderDocs, but lacks explicit exclusions or comparisons.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/stv-io/aws-terraform-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server