Repository navigation
feat(search): add schema-backed query guidance (2/6) - #587
Open
sowju-hashicorp wants to merge 1 commit into
Open
sowju-hashicorp wants to merge 1 commit into
sowju-hashicorp wants to merge 1 commit into
Conversation
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Schema validation and rendering can lose required nested structure and produce examples that violate supplied types or cardinality.
7 open issues
Decode and recursively render nested attribute types · New Reject missing or null resource schemas · New Render tuple element types individually · New Show requiredness for nested sub-attributes · New Generate examples for block minimum cardinality · New Traverse nested child blocks in schemas and examples · New Generate placeholders recursively from compound types · New
What changed in this PR
Adds credential-free query configuration guidance to the Terraform Search toolset, building on provider discovery. Both MCP SDKs share the generator; query execution remains outside this release.
Changes:
- Adds schema parsing, resource selection, attribute catalogs, examples, and variable guidance.
- Registers the generator on both SDKs without requiring Terraform credentials.
- Extends tests and documentation for transport parity, credential gating, logging suppression, and workflow boundaries.
| File | Description |
|---|---|
| README.md | Documents generator usage and release boundaries. |
| pkg/toolsets/toolsets.go | Updates the Search toolset description. |
| pkg/toolsets/search.go | Adds credential-free generator metadata. |
| pkg/toolsets/search_test.go | Tests tool selection and credential gating. |
| pkg/tools/search/provider_list_schema_list_test.go | Connects discovered schemas to generation. |
| pkg/tools/search/generate_query_configuration.go | Implements shared guidance and the legacy tool. |
| pkg/tools/search/generate_query_configuration_test.go | Tests parsing, catalogs, examples, and guidance. |
| pkg/tools/search/descriptions.go | Exports the shared generator description. |
| pkg/tools/search/descriptions_test.go | Checks generator description contracts. |
| pkg/tools/factories.go | Registers the legacy SDK generator. |
| pkg/tools/factories_test.go | Tests registration without credentials. |
| pkg/mcp-official/tools/tools.go | Registers the official SDK generator. |
| pkg/mcp-official/tools/tools_test.go | Tests registration, discovery integration, and parity. |
| pkg/mcp-official/tools/search/search.go | Adds official SDK arguments and handler. |
| pkg/mcp-official/tools/search/search_test.go | Tests annotations and input validation. |
| pkg/mcp-official/tools/middleware/tool_logging_test.go | Tests official SDK logging suppression. |
| pkg/instructions/instructions.md | Defines the discovery-to-guidance workflow. |
| pkg/instructions/instructions_test.go | Checks guidance and release boundaries. |
| pkg/client/tool_logging_middleware_test.go | Tests legacy SDK argument suppression. |
| CHANGELOG.md | Announces configuration guidance support. |
Review effort: Balanced
Comment on lines
+66
to
+70
| type listResourceAttribute struct { | ||
| Description string `json:"description"` | ||
| Required bool `json:"required"` | ||
| Optional bool `json:"optional"` | ||
| Type any `json:"type"` // "string" | "bool" | "number" | ["list","string"] | ... |
Comment on lines
+201
to
+223
| // resource-type map. It uses a structural heuristic: a bare map whose first | ||
| // entry has a "block" child is the resource-type map; anything else is treated | ||
| // as the wrapped file format. | ||
| func parseListResourceSchemas(raw string) (map[string]listResourceEntry, error) { | ||
| // Try the bare map first. A valid bare map has entries with a "block" key | ||
| // rather than a top-level "list_resource_schemas" key. | ||
| var bare map[string]listResourceEntry | ||
| if err := json.Unmarshal([]byte(raw), &bare); err == nil { | ||
| if _, hasWrapper := bare["list_resource_schemas"]; !hasWrapper { | ||
| return bare, nil | ||
| } | ||
| } | ||
|
|
||
| // Try the wrapped file format. | ||
| var wrapped listResourceSchemaFile | ||
| if err := json.Unmarshal([]byte(raw), &wrapped); err != nil { | ||
| return nil, fmt.Errorf("input is not valid JSON: %w", err) | ||
| } | ||
| if wrapped.ListResourceSchemas == nil { | ||
| return nil, fmt.Errorf("no list_resource_schemas key found in input") | ||
| } | ||
| return wrapped.ListResourceSchemas, nil | ||
| } |
| } | ||
| } | ||
| // ["list","string"], ["set","string"], ["map","string"], etc. | ||
| return fmt.Sprintf("%s(%s)", outer, humanType(v[1])) |
| subNames := sortedKeys(subAttrs) | ||
| subSummary := make([]string, 0, len(subNames)) | ||
| for _, sub := range subNames { | ||
| subSummary = append(subSummary, fmt.Sprintf("`%s` (%s)", sub, humanType(subAttrs[sub].Type))) |
Comment on lines
+572
to
+575
| result = append(result, map[string]any{ | ||
| "attribute": name, | ||
| "value": buildExampleBlockValue(bt.Block.Attributes), | ||
| }) |
Comment on lines
+583
to
+587
| func buildExampleBlockValue(subAttrs map[string]listResourceAttribute) map[string]any { | ||
| obj := make(map[string]any, len(subAttrs)) | ||
| for _, name := range sortedKeys(subAttrs) { | ||
| attr := subAttrs[name] | ||
| obj[name] = exampleValueForType(name, attr.Type) |
Comment on lines
+596
to
+610
| func exampleValueForType(attrName string, rawType any) any { | ||
| t := humanType(rawType) | ||
| switch { | ||
| case t == "bool" || t == "boolean": | ||
| return false | ||
| case t == "number": | ||
| return 0 | ||
| case strings.HasPrefix(t, "list") || strings.HasPrefix(t, "set"): | ||
| return []string{"<value>"} | ||
| case strings.HasPrefix(t, "map") || strings.HasPrefix(t, "object"): | ||
| return map[string]string{"<key>": "<value>"} | ||
| default: | ||
| return fmt.Sprintf("<your-%s>", strings.ReplaceAll(attrName, "_", "-")) | ||
| } | ||
| } |
mjyocca
added this pull request to stack #593
October 22, 2026 16:45
mjyocca
force-pushed
the
sowju/search-02-configuration
branch
from
October 22, 2026 18:54
76af936 to
87eb91c
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
PR 2 of 6 in the Terraform Search stack.
Branch:
sowju/search-02-configurationBase:
sowju/search-01-discoveryAdds
generate_query_configurationto guide callers in constructing a Terraform Search query from discovered provider capabilities.Changes
Security impact
Validation
Reviewer focus
Stack scope
Depends on PR 1 for provider discovery and shared foundation. Set this PR's base to
sowju/search-01-discoveryso the diff shows only query guidance.Query execution/status, validated summaries, import preparation, and Plan verification are deferred to subsequent PRs.
Next branch:
sowju/search-03-execution, based on this branch.Some source-preserved tool guidance references later execution/status/summary tools. Those tools are not registered here; this is an incremental review layer, not the complete Search workflow.
Rollback
Revert this PR before dependent layers merge. If dependent layers have merged, coordinate their rollback in reverse dependency order. PR 1's provider discovery can remain in place. No data migration or infrastructure rollback is required.
PCI review checklist
I have documented a clear reason for, and description of, the change I am making.
If applicable, I've documented a plan to revert these changes if they require more than reverting the pull request.
If applicable, I've documented the impact of any changes to security controls.
Examples of changes to security controls include using new access control methods, adding or removing logging pipelines, etc.