awslabs.terraform-mcp-server 0.0.7__tar.gz → 0.0.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of awslabs.terraform-mcp-server might be problematic. Click here for more details.

Files changed (49) hide show
  1. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/PKG-INFO +1 -1
  2. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/pyproject.toml +1 -1
  3. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/tests/test_search_user_provided_module.py +294 -0
  4. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/uv.lock +1 -1
  5. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/.gitignore +0 -0
  6. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/.pre-commit-config.yaml +0 -0
  7. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/.python-version +0 -0
  8. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/CHANGELOG.md +0 -0
  9. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/README.md +0 -0
  10. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/__init__.py +0 -0
  11. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/__init__.py +0 -0
  12. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/impl/resources/__init__.py +0 -0
  13. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/impl/resources/terraform_aws_provider_resources_listing.py +0 -0
  14. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/impl/resources/terraform_awscc_provider_resources_listing.py +0 -0
  15. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/impl/tools/__init__.py +0 -0
  16. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/impl/tools/execute_terraform_command.py +0 -0
  17. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/impl/tools/run_checkov_scan.py +0 -0
  18. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/impl/tools/search_aws_provider_docs.py +0 -0
  19. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/impl/tools/search_awscc_provider_docs.py +0 -0
  20. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/impl/tools/search_specific_aws_ia_modules.py +0 -0
  21. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/impl/tools/search_user_provided_module.py +0 -0
  22. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/impl/tools/utils.py +0 -0
  23. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/models/__init__.py +0 -0
  24. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/models/models.py +0 -0
  25. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/scripts/generate_aws_provider_resources.py +0 -0
  26. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/scripts/generate_awscc_provider_resources.py +0 -0
  27. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/scripts/scrape_aws_terraform_best_practices.py +0 -0
  28. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/server.py +0 -0
  29. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/static/AWSCC_PROVIDER_RESOURCES.md +0 -0
  30. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/static/AWS_PROVIDER_RESOURCES.md +0 -0
  31. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/static/AWS_TERRAFORM_BEST_PRACTICES.md +0 -0
  32. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/static/MCP_INSTRUCTIONS.md +0 -0
  33. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/static/TERRAFORM_WORKFLOW_GUIDE.md +0 -0
  34. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/awslabs/terraform_mcp_server/static/__init__.py +0 -0
  35. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/run_tests.sh +0 -0
  36. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/tests/.gitignore +0 -0
  37. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/tests/README.md +0 -0
  38. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/tests/__init__.py +0 -0
  39. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/tests/conftest.py +0 -0
  40. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/tests/test_command_impl.py +0 -0
  41. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/tests/test_execute_terraform_command.py +0 -0
  42. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/tests/test_models.py +0 -0
  43. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/tests/test_parameter_annotations.py +0 -0
  44. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/tests/test_resources.py +0 -0
  45. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/tests/test_run_checkov_scan.py +0 -0
  46. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/tests/test_server.py +0 -0
  47. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/tests/test_tool_implementations.py +0 -0
  48. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/tests/test_utils.py +0 -0
  49. {awslabs_terraform_mcp_server-0.0.7 → awslabs_terraform_mcp_server-0.0.8}/tests/test_utils_additional.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: awslabs.terraform-mcp-server
3
- Version: 0.0.7
3
+ Version: 0.0.8
4
4
  Summary: An AWS Labs Model Context Protocol (MCP) server for terraform
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: beautifulsoup4>=4.12.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "awslabs.terraform-mcp-server"
3
- version = "0.0.7"
3
+ version = "0.0.8"
4
4
  description = "An AWS Labs Model Context Protocol (MCP) server for terraform"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -834,6 +834,250 @@ async def test_get_module_details_with_api_error(mock_requests_get):
834
834
  assert result == {}
835
835
 
836
836
 
837
+ @patch('requests.get')
838
+ async def test_get_module_details_no_readme_content(mock_requests_get):
839
+ """Test get_module_details when no README content is found through any method."""
840
+ # Setup mock for registry API response without README
841
+ registry_response = MockResponse(
842
+ 200,
843
+ json_data={
844
+ 'id': 'hashicorp/consul/aws/0.11.0',
845
+ 'name': 'consul',
846
+ 'namespace': 'hashicorp',
847
+ 'provider': 'aws',
848
+ 'version': '0.11.0',
849
+ 'description': 'Terraform module which can be used to deploy a Consul cluster on AWS',
850
+ 'source': 'https://github.com/hashicorp/terraform-aws-consul',
851
+ 'published_at': '2023-01-01T00:00:00Z',
852
+ # No readme field
853
+ },
854
+ )
855
+
856
+ # Setup mock for GitHub README requests to return 404
857
+ github_readme_response = MockResponse(404)
858
+
859
+ def mock_get_side_effect(url):
860
+ parsed_url = urlparse(url)
861
+ hostname = parsed_url.netloc
862
+
863
+ if hostname == 'registry.terraform.io':
864
+ return registry_response
865
+ elif hostname == 'raw.githubusercontent.com' and 'README.md' in parsed_url.path:
866
+ return github_readme_response
867
+ else:
868
+ return MockResponse(404)
869
+
870
+ mock_requests_get.side_effect = mock_get_side_effect
871
+
872
+ # Mock GitHub release details and variables.tf to return empty values
873
+ with patch(
874
+ 'awslabs.terraform_mcp_server.impl.tools.utils.get_github_release_details'
875
+ ) as mock_release:
876
+ with patch(
877
+ 'awslabs.terraform_mcp_server.impl.tools.utils.get_variables_tf'
878
+ ) as mock_variables:
879
+ mock_release.return_value = {'details': {}, 'version': None}
880
+ mock_variables.return_value = (None, [])
881
+
882
+ # Call the function
883
+ result = await get_module_details('hashicorp', 'consul', 'aws', '0.11.0')
884
+
885
+ # Verify the result doesn't have readme_content
886
+ assert result is not None
887
+ assert 'readme_content' not in result
888
+
889
+
890
+ @patch('requests.get')
891
+ async def test_get_module_details_with_variables_content(mock_requests_get):
892
+ """Test get_module_details when variables are found in variables.tf."""
893
+ # Setup mock for registry API response with GitHub source URL
894
+ registry_response = MockResponse(
895
+ 200,
896
+ json_data={
897
+ 'id': 'hashicorp/consul/aws/0.11.0',
898
+ 'name': 'consul',
899
+ 'namespace': 'hashicorp',
900
+ 'provider': 'aws',
901
+ 'version': '0.11.0',
902
+ 'description': 'Terraform module which can be used to deploy a Consul cluster on AWS',
903
+ 'source': 'https://github.com/hashicorp/terraform-aws-consul',
904
+ 'published_at': '2023-01-01T00:00:00Z',
905
+ },
906
+ )
907
+
908
+ # Setup mock for GitHub requests
909
+ def mock_get_side_effect(url, **kwargs): # Accept any keyword arguments
910
+ parsed_url = urlparse(url)
911
+ hostname = parsed_url.netloc
912
+ path = parsed_url.path
913
+
914
+ if hostname == 'registry.terraform.io':
915
+ return registry_response
916
+ elif hostname == 'raw.githubusercontent.com' and 'README.md' in path:
917
+ return MockResponse(404) # No README found
918
+ elif hostname == 'raw.githubusercontent.com' and 'variables.tf' in path:
919
+ if '/main/' in path:
920
+ # Return variables.tf for main branch
921
+ return MockResponse(
922
+ 200,
923
+ text="""
924
+ variable "cluster_name" {
925
+ description = "What to name the Consul cluster"
926
+ type = string
927
+ }
928
+
929
+ variable "num_servers" {
930
+ description = "The number of Consul server nodes to deploy"
931
+ type = number
932
+ default = 3
933
+ }
934
+ """,
935
+ )
936
+ else:
937
+ return MockResponse(404)
938
+ else:
939
+ return MockResponse(404)
940
+
941
+ mock_requests_get.side_effect = mock_get_side_effect
942
+
943
+ # Skip mocking get_variables_tf and directly use the implementation
944
+ # This will ensure the variables_content is processed correctly
945
+
946
+ # Call the function
947
+ result = await get_module_details('hashicorp', 'consul', 'aws', '0.11.0')
948
+
949
+ # Verify the variables were added to the result
950
+ assert result is not None
951
+ assert 'variables' in result
952
+ assert len(result['variables']) == 2
953
+ assert result['variables'][0]['name'] == 'cluster_name'
954
+ assert result['variables'][0]['type'] == 'string'
955
+ assert result['variables'][0]['required'] is True
956
+ assert result['variables'][1]['name'] == 'num_servers'
957
+ assert result['variables'][1]['type'] == 'number'
958
+ assert result['variables'][1]['required'] is False
959
+ assert result['variables'][1]['default'] == '3'
960
+
961
+
962
+ @patch('requests.get')
963
+ async def test_get_module_details_with_variables_in_master_branch(mock_requests_get):
964
+ """Test get_module_details when variables are found in master branch (fallback)."""
965
+ # Setup mock for registry API response with GitHub source URL
966
+ registry_response = MockResponse(
967
+ 200,
968
+ json_data={
969
+ 'id': 'hashicorp/consul/aws/0.11.0',
970
+ 'name': 'consul',
971
+ 'namespace': 'hashicorp',
972
+ 'provider': 'aws',
973
+ 'version': '0.11.0',
974
+ 'description': 'Terraform module which can be used to deploy a Consul cluster on AWS',
975
+ 'source': 'https://github.com/hashicorp/terraform-aws-consul',
976
+ 'published_at': '2023-01-01T00:00:00Z',
977
+ },
978
+ )
979
+
980
+ # Setup mock for GitHub requests
981
+ def mock_get_side_effect(url, **kwargs): # Accept any keyword arguments
982
+ parsed_url = urlparse(url)
983
+ hostname = parsed_url.netloc
984
+ path = parsed_url.path
985
+
986
+ if hostname == 'registry.terraform.io':
987
+ return registry_response
988
+ elif hostname == 'raw.githubusercontent.com' and 'README.md' in path:
989
+ return MockResponse(404) # No README found
990
+ elif hostname == 'raw.githubusercontent.com' and 'variables.tf' in path:
991
+ if '/main/' in path:
992
+ return MockResponse(404) # No variables.tf in main branch
993
+ elif '/master/' in path:
994
+ # Return variables.tf for master branch
995
+ return MockResponse(
996
+ 200,
997
+ text="""
998
+ variable "cluster_name" {
999
+ description = "What to name the Consul cluster (master branch)"
1000
+ type = string
1001
+ }
1002
+ """,
1003
+ )
1004
+ else:
1005
+ return MockResponse(404)
1006
+ else:
1007
+ return MockResponse(404)
1008
+
1009
+ mock_requests_get.side_effect = mock_get_side_effect
1010
+
1011
+ # Call the function
1012
+ result = await get_module_details('hashicorp', 'consul', 'aws', '0.11.0')
1013
+
1014
+ # Verify the variables from master branch were added to the result
1015
+ assert result is not None
1016
+ assert 'variables' in result
1017
+ assert len(result['variables']) == 1
1018
+ assert result['variables'][0]['name'] == 'cluster_name'
1019
+ assert (
1020
+ result['variables'][0]['description'] == 'What to name the Consul cluster (master branch)'
1021
+ )
1022
+ assert result['variables'][0]['required'] is True
1023
+
1024
+
1025
+ @patch('requests.get')
1026
+ async def test_get_module_details_with_version_from_github(mock_requests_get):
1027
+ """Test get_module_details when version is found from GitHub and no module version is set."""
1028
+ # Setup mock for registry API response with GitHub source URL but no version
1029
+ registry_response = MockResponse(
1030
+ 200,
1031
+ json_data={
1032
+ 'id': 'hashicorp/consul/aws',
1033
+ 'name': 'consul',
1034
+ 'namespace': 'hashicorp',
1035
+ 'provider': 'aws',
1036
+ # No version field
1037
+ 'description': 'Terraform module which can be used to deploy a Consul cluster on AWS',
1038
+ 'source': 'https://github.com/hashicorp/terraform-aws-consul',
1039
+ 'published_at': '2023-01-01T00:00:00Z',
1040
+ },
1041
+ )
1042
+
1043
+ # Setup mock for GitHub requests
1044
+ def mock_get_side_effect(url, **kwargs): # Accept any keyword arguments
1045
+ parsed_url = urlparse(url)
1046
+ hostname = parsed_url.netloc
1047
+ path = parsed_url.path
1048
+
1049
+ if hostname == 'registry.terraform.io':
1050
+ return registry_response
1051
+ elif hostname == 'raw.githubusercontent.com' and 'README.md' in path:
1052
+ return MockResponse(404) # No README found
1053
+ elif hostname == 'api.github.com':
1054
+ # Mock GitHub API responses
1055
+ if '/releases/latest' in path:
1056
+ return MockResponse(
1057
+ 200,
1058
+ json_data={
1059
+ 'tag_name': 'v1.2.3',
1060
+ 'published_at': '2023-01-01T00:00:00Z',
1061
+ },
1062
+ )
1063
+ elif '/tags' in path:
1064
+ return MockResponse(
1065
+ 200, json_data=[{'name': 'v1.2.3', 'commit': {'sha': '123456'}}]
1066
+ )
1067
+ return MockResponse(404)
1068
+
1069
+ mock_requests_get.side_effect = mock_get_side_effect
1070
+
1071
+ # Call the function directly without mocking get_github_release_details
1072
+ # This will test the actual code path that sets the version from GitHub
1073
+ result = await get_module_details('hashicorp', 'consul', 'aws', None)
1074
+
1075
+ # Verify the version from GitHub was used
1076
+ assert result is not None
1077
+ assert 'version' in result
1078
+ assert result['version'] == '1.2.3' # Should be set from GitHub version
1079
+
1080
+
837
1081
  @patch('awslabs.terraform_mcp_server.impl.tools.search_user_provided_module.get_module_details')
838
1082
  async def test_search_user_provided_module_impl_with_variables_from_root(mock_get_module_details):
839
1083
  """Test search_user_provided_module_impl with variables from root."""
@@ -918,6 +1162,56 @@ async def test_search_user_provided_module_impl_with_outputs_from_root(mock_get_
918
1162
  assert result.outputs[1].description == 'The ARN of the VPC'
919
1163
 
920
1164
 
1165
+ @patch('awslabs.terraform_mcp_server.impl.tools.search_user_provided_module.get_module_details')
1166
+ async def test_search_user_provided_module_impl_no_readme_content(mock_get_module_details):
1167
+ """Test search_user_provided_module_impl when no README content is found."""
1168
+ # Setup mock with module details but no readme_content
1169
+ mock_get_module_details.return_value = {
1170
+ 'name': 'vpc',
1171
+ 'namespace': 'terraform-aws-modules',
1172
+ 'provider': 'aws',
1173
+ 'version': '3.14.0',
1174
+ 'description': 'Terraform module which creates VPC resources on AWS',
1175
+ # No readme_content key
1176
+ 'variables': [
1177
+ {
1178
+ 'name': 'name',
1179
+ 'type': 'string',
1180
+ 'description': 'Name to be used on all the resources as identifier',
1181
+ 'default': None,
1182
+ 'required': True,
1183
+ }
1184
+ ],
1185
+ 'outputs': [
1186
+ {
1187
+ 'name': 'vpc_id',
1188
+ 'description': 'The ID of the VPC',
1189
+ }
1190
+ ],
1191
+ }
1192
+
1193
+ # Create request
1194
+ request = SearchUserProvidedModuleRequest(
1195
+ module_url='terraform-aws-modules/vpc/aws', version=None, variables=None
1196
+ )
1197
+
1198
+ # Call the function
1199
+ result = await search_user_provided_module_impl(request)
1200
+
1201
+ # Verify the result
1202
+ assert result.status == 'success'
1203
+ assert result.module_name == 'vpc'
1204
+ assert result.module_url == 'terraform-aws-modules/vpc/aws'
1205
+ assert result.module_version == '3.14.0'
1206
+ assert result.module_description == 'Terraform module which creates VPC resources on AWS'
1207
+ assert len(result.variables) == 1
1208
+ assert result.variables[0].name == 'name'
1209
+ assert len(result.outputs) == 1
1210
+ assert result.outputs[0].name == 'vpc_id'
1211
+ assert result.readme_content == '' # Should be empty string, not None
1212
+ assert result.error_message is None
1213
+
1214
+
921
1215
  def format_json(obj: Any) -> str:
922
1216
  """Format an object as pretty JSON."""
923
1217
  if hasattr(obj, 'model_dump'):
@@ -179,7 +179,7 @@ wheels = [
179
179
 
180
180
  [[package]]
181
181
  name = "awslabs-terraform-mcp-server"
182
- version = "0.0.6"
182
+ version = "0.0.7"
183
183
  source = { editable = "." }
184
184
  dependencies = [
185
185
  { name = "beautifulsoup4" },