| 421 | } |
| 422 | |
| 423 | func handleListProjects(ctx context.Context, req *mcp.CallToolRequest, input ListProjectsInput) (*mcp.CallToolResult, any, error) { |
| 424 | // Expand ~ to home directory |
| 425 | path := input.Path |
| 426 | if strings.HasPrefix(path, "~/") { |
| 427 | home := os.Getenv("HOME") |
| 428 | path = filepath.Join(home, path[2:]) |
| 429 | } |
| 430 | |
| 431 | absPath, err := filepath.Abs(path) |
| 432 | if err != nil { |
| 433 | return errorResult("Invalid path: " + err.Error()), nil, nil |
| 434 | } |
| 435 | |
| 436 | entries, err := os.ReadDir(absPath) |
| 437 | if err != nil { |
| 438 | return errorResult("Cannot read directory: " + err.Error()), nil, nil |
| 439 | } |
| 440 | |
| 441 | pattern := strings.ToLower(input.Pattern) |
| 442 | var projects []string |
| 443 | |
| 444 | for _, entry := range entries { |
| 445 | if !entry.IsDir() { |
| 446 | continue |
| 447 | } |
| 448 | name := entry.Name() |
| 449 | |
| 450 | // Skip hidden directories and common non-project dirs |
| 451 | if strings.HasPrefix(name, ".") { |
| 452 | continue |
| 453 | } |
| 454 | |
| 455 | // Filter by pattern if provided |
| 456 | if pattern != "" && !strings.Contains(strings.ToLower(name), pattern) { |
| 457 | continue |
| 458 | } |
| 459 | |
| 460 | // Get project stats |
| 461 | projectPath := filepath.Join(absPath, name) |
| 462 | stats := getProjectStats(projectPath) |
| 463 | |
| 464 | projects = append(projects, fmt.Sprintf("%-30s %s", name+"/", stats)) |
| 465 | } |
| 466 | |
| 467 | if len(projects) == 0 { |
| 468 | if pattern != "" { |
| 469 | return textResult(fmt.Sprintf("No projects matching '%s' in %s", input.Pattern, absPath)), nil, nil |
| 470 | } |
| 471 | return textResult("No project directories found in " + absPath), nil, nil |
| 472 | } |
| 473 | |
| 474 | header := fmt.Sprintf("Projects in %s", absPath) |
| 475 | if pattern != "" { |
| 476 | header = fmt.Sprintf("Projects matching '%s' in %s", input.Pattern, absPath) |
| 477 | } |
| 478 | |
| 479 | return textResult(fmt.Sprintf("%s:\n\n%s", header, strings.Join(projects, "\n"))), nil, nil |
| 480 | } |