Skip to content

Commit a3009db

Browse files
- Added MCP validate.
1 parent a701e5f commit a3009db

File tree

7 files changed

+23
-11
lines changed

7 files changed

+23
-11
lines changed

docs/mcp.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ Then, assuming you have a `stackql` MCP server serving streamable HTTP on port `
4444

4545
./build/stackql_mcp_client exec --client-type=http --url=http://127.0.0.1:9992 --exec.action list_methods --exec.args '{"provider": "google", "service": "compute", "resource": "networks"}'
4646

47+
./build/stackql_mcp_client exec --client-type=http --url=http://127.0.0.1:9992 --exec.action validate_query_json_v2 --exec.args '{"sql": "select name from google.compute.networks where project = '"'"'stackql-demo'"'"';"}'
48+
4749
./build/stackql_mcp_client exec --client-type=http --url=http://127.0.0.1:9992 --exec.action query_json_v2 --exec.args '{"sql": "select name from google.compute.networks where project = '"'"'stackql-demo'"'"';"}'
4850

4951
```

internal/stackql/mcpbackend/mcp_reverse_proxy_backend_service.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,13 @@ func (b *stackqlMCPReverseProxyService) ExecQuery(ctx context.Context, query str
8484
return b.execQuery(ctx, query)
8585
}
8686

87-
func (b *stackqlMCPReverseProxyService) ValidateQuery(ctx context.Context, query string) (map[string]any, error) {
88-
return map[string]any{}, nil
87+
func (b *stackqlMCPReverseProxyService) ValidateQuery(ctx context.Context, query string) ([]map[string]any, error) {
88+
explainQuery := fmt.Sprintf("EXPLAIN %s", query)
89+
rows, err := b.query(ctx, explainQuery, unlimitedRowLimit)
90+
if err != nil {
91+
return nil, err
92+
}
93+
return rows, nil
8994
}
9095

9196
func (b *stackqlMCPReverseProxyService) execQuery(ctx context.Context, query string) (map[string]any, error) {

internal/stackql/mcpbackend/mcp_service_stackql.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,13 @@ func (b *stackqlMCPService) ExecQuery(ctx context.Context, query string) (map[st
324324
return b.execQuery(ctx, query)
325325
}
326326

327-
func (b *stackqlMCPService) ValidateQuery(ctx context.Context, query string) (map[string]any, error) {
328-
return map[string]any{}, nil
327+
func (b *stackqlMCPService) ValidateQuery(ctx context.Context, query string) ([]map[string]any, error) {
328+
explainQuery := fmt.Sprintf("EXPLAIN %s", query)
329+
rows, err := b.runPreprocessedQueryJSON(ctx, explainQuery, unlimitedRowLimit)
330+
if err != nil {
331+
return nil, err
332+
}
333+
return rows, nil
329334
}
330335

331336
func (b *stackqlMCPService) execQuery(ctx context.Context, query string) (map[string]any, error) {

internal/stackql/primitivebuilder/explain.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,12 @@ func (nb *ExplainBuilder) Build() error {
5454
}
5555
oneLinerOutput := time.Now().Format("2006-01-02T15:04:05-07:00 MST")
5656
resultMap := map[string]any{
57-
"query": nb.handlerCtx.GetRawQuery(),
57+
"query": nb.handlerCtx.GetQuery(),
5858
"timestamp": oneLinerOutput,
59+
"result": "OK",
5960
"valid": true,
6061
}
61-
columns := []string{"query", "timestamp", "valid"}
62+
columns := []string{"query", "result", "timestamp", "valid"}
6263
return util.PrepareResultSet(
6364
internaldto.NewPrepareResultSetPlusRawDTO(
6465
nil,

pkg/mcp_server/backend.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ type Backend interface {
2929
ExecQuery(ctx context.Context, query string) (map[string]any, error)
3030

3131
// Execute a SQL query that does not return rows
32-
ValidateQuery(ctx context.Context, query string) (map[string]any, error)
32+
ValidateQuery(ctx context.Context, query string) ([]map[string]any, error)
3333

3434
// Execute a SQL query and return JSON rows with typed input (preferred)
3535
RunQueryJSON(ctx context.Context, input dto.QueryJSONInput) ([]map[string]interface{}, error)

pkg/mcp_server/example_backend.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ func (b *ExampleBackend) RunQueryJSON(ctx context.Context, input dto.QueryJSONIn
5252
return []map[string]interface{}{}, nil
5353
}
5454

55-
func (b *ExampleBackend) ValidateQuery(ctx context.Context, query string) (map[string]any, error) {
56-
return map[string]any{}, nil
55+
func (b *ExampleBackend) ValidateQuery(ctx context.Context, query string) ([]map[string]any, error) {
56+
return []map[string]any{}, nil
5757
}
5858

5959
// func (b *ExampleBackend) ListTableResources(ctx context.Context, hI dto.HierarchyInput) ([]string, error) {

pkg/mcp_server/server.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,7 @@ func newMCPServer(config *Config, backend Backend, logger *logrus.Logger) (MCPSe
230230
Description: "Explain a SQL query and return a JSON object expressing success, or else an error.",
231231
},
232232
func(ctx context.Context, req *mcp.CallToolRequest, args dto.QueryJSONInput) (*mcp.CallToolResult, any, error) {
233-
args.SQL = fmt.Sprintf("EXPLAIN %s", args.SQL)
234-
arr, err := backend.RunQueryJSON(ctx, args)
233+
arr, err := backend.ValidateQuery(ctx, args.SQL)
235234
if err != nil {
236235
return nil, nil, err
237236
}

0 commit comments

Comments
 (0)