handleAnalyzeSQL is the MCP tool handler for "analyze_sql". It fans out all six analysis tools concurrently and merges the results.
(ctx context.Context, req mcpmcp.CallToolRequest)
| 336 | // handleAnalyzeSQL is the MCP tool handler for "analyze_sql". |
| 337 | // It fans out all six analysis tools concurrently and merges the results. |
| 338 | func handleAnalyzeSQL(ctx context.Context, req mcpmcp.CallToolRequest) (*mcpmcp.CallToolResult, error) { |
| 339 | sql := req.GetString("sql", "") |
| 340 | if sql == "" { |
| 341 | return nil, fmt.Errorf("parameter 'sql' is required and must not be empty") |
| 342 | } |
| 343 | |
| 344 | type namedResult struct { |
| 345 | name string |
| 346 | data map[string]any |
| 347 | err error |
| 348 | } |
| 349 | |
| 350 | tasks := []struct { |
| 351 | name string |
| 352 | fn func() (map[string]any, error) |
| 353 | }{ |
| 354 | {"validate", func() (map[string]any, error) { return validateSQLInternal(sql, "") }}, |
| 355 | {"parse", func() (map[string]any, error) { return parseSQLInternal(sql) }}, |
| 356 | {"metadata", func() (map[string]any, error) { return extractMetadataInternal(sql) }}, |
| 357 | {"security", func() (map[string]any, error) { return securityScanInternal(sql) }}, |
| 358 | {"lint", func() (map[string]any, error) { return lintSQLInternal(sql) }}, |
| 359 | {"format", func() (map[string]any, error) { return formatSQLInternal(sql, 2, false, false) }}, |
| 360 | } |
| 361 | |
| 362 | results := make(chan namedResult, len(tasks)) |
| 363 | var wg sync.WaitGroup |
| 364 | for _, t := range tasks { |
| 365 | wg.Add(1) |
| 366 | go func(t struct { |
| 367 | name string |
| 368 | fn func() (map[string]any, error) |
| 369 | }) { |
| 370 | defer wg.Done() |
| 371 | data, err := t.fn() |
| 372 | results <- namedResult{name: t.name, data: data, err: err} |
| 373 | }(t) |
| 374 | } |
| 375 | wg.Wait() |
| 376 | close(results) |
| 377 | |
| 378 | combined := make(map[string]any, len(tasks)+1) |
| 379 | errs := make(map[string]string) |
| 380 | for r := range results { |
| 381 | if r.err != nil { |
| 382 | errs[r.name] = r.err.Error() |
| 383 | } else { |
| 384 | combined[r.name] = r.data |
| 385 | } |
| 386 | } |
| 387 | if len(errs) > 0 { |
| 388 | combined["errors"] = errs |
| 389 | } |
| 390 | return toolResult(combined) |
| 391 | } |