• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / cli / 19194338182

08 Nov 2025 02:29PM UTC coverage: 53.056% (-1.6%) from 54.689%
19194338182

Pull #4383

github

web-flow
Merge a898faa1b into af2b11bea
Pull Request #4383: feat(mcp): add `supabase mcp init` command to configure MCP clients

0 of 355 new or added lines in 9 files covered. (0.0%)

5 existing lines in 1 file now uncovered.

6388 of 12040 relevant lines covered (53.06%)

5.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/internal/mcp/init/cursor.go
1
package mcpinit
2

3
import (
4
        "context"
5
        "encoding/json"
6
        "fmt"
7
        "os"
8
        "path/filepath"
9

10
        "github.com/spf13/afero"
11
        "github.com/supabase/cli/internal/utils"
12
)
13

14
// cursorClient implements the Client interface for Cursor
15
type cursorClient struct {
16
        baseClient
17
}
18

NEW
19
func newCursorClient() *cursorClient {
×
NEW
20
        return &cursorClient{
×
NEW
21
                baseClient: baseClient{
×
NEW
22
                        name:                "cursor",
×
NEW
23
                        displayName:         "Cursor",
×
NEW
24
                        installInstructions: "Download from https://cursor.sh",
×
NEW
25
                        checkInstalled: func() bool {
×
NEW
26
                                return commandExists("cursor") || appExists("Cursor")
×
NEW
27
                        },
×
28
                },
29
        }
30
}
31

NEW
32
func (c *cursorClient) Configure(ctx context.Context, fsys afero.Fs) error {
×
NEW
33
        fmt.Println("Configuring Cursor...")
×
NEW
34
        fmt.Println()
×
NEW
35

×
NEW
36
        choice, err := utils.PromptChoice(ctx, "Where would you like to add the configuration?", []utils.PromptItem{
×
NEW
37
                {Summary: "project", Details: "Project-local (in .cursor/mcp.json)"},
×
NEW
38
                {Summary: "global", Details: "Global (in your home directory)"},
×
NEW
39
        })
×
NEW
40
        if err != nil {
×
NEW
41
                return err
×
NEW
42
        }
×
43

NEW
44
        var configPath string
×
NEW
45
        if choice.Summary == "global" {
×
NEW
46
                // Global config
×
NEW
47
                homeDir, _ := os.UserHomeDir()
×
NEW
48
                configPath = filepath.Join(homeDir, ".cursor", "mcp.json")
×
NEW
49
        } else {
×
NEW
50
                // Project-local config
×
NEW
51
                cwd, _ := os.Getwd()
×
NEW
52
                configPath = filepath.Join(cwd, ".cursor", "mcp.json")
×
NEW
53
        }
×
54

55
        // Prepare the Supabase MCP server config
NEW
56
        supabaseConfig := map[string]interface{}{
×
NEW
57
                "type": "http",
×
NEW
58
                "url":  "http://localhost:54321/mcp",
×
NEW
59
        }
×
NEW
60

×
NEW
61
        // Read existing config if it exists
×
NEW
62
        var config map[string]interface{}
×
NEW
63
        existingData, err := afero.ReadFile(fsys, configPath)
×
NEW
64
        if err == nil && len(existingData) > 0 {
×
NEW
65
                if err := json.Unmarshal(existingData, &config); err != nil {
×
NEW
66
                        // If existing file is invalid JSON, start fresh
×
NEW
67
                        config = make(map[string]interface{})
×
NEW
68
                }
×
NEW
69
        } else {
×
NEW
70
                config = make(map[string]interface{})
×
NEW
71
        }
×
72

73
        // Ensure mcpServers exists
NEW
74
        mcpServers, ok := config["mcpServers"].(map[string]interface{})
×
NEW
75
        if !ok {
×
NEW
76
                mcpServers = make(map[string]interface{})
×
NEW
77
                config["mcpServers"] = mcpServers
×
NEW
78
        }
×
79

80
        // Add or update Supabase server
NEW
81
        mcpServers["supabase"] = supabaseConfig
×
NEW
82

×
NEW
83
        // Ensure directory exists
×
NEW
84
        configDir := filepath.Dir(configPath)
×
NEW
85
        if err := fsys.MkdirAll(configDir, 0755); err != nil {
×
NEW
86
                return fmt.Errorf("failed to create config directory: %w", err)
×
NEW
87
        }
×
88

89
        // Write config
NEW
90
        configJSON, err := json.MarshalIndent(config, "", "  ")
×
NEW
91
        if err != nil {
×
NEW
92
                return fmt.Errorf("failed to marshal config: %w", err)
×
NEW
93
        }
×
94

NEW
95
        if err := afero.WriteFile(fsys, configPath, configJSON, 0644); err != nil {
×
NEW
96
                return fmt.Errorf("failed to write config file: %w", err)
×
NEW
97
        }
×
98

99
        // Generate example for display
NEW
100
        configExample, _ := json.MarshalIndent(map[string]interface{}{
×
NEW
101
                "mcpServers": map[string]interface{}{
×
NEW
102
                        "supabase": supabaseConfig,
×
NEW
103
                },
×
NEW
104
        }, "", "  ")
×
NEW
105

×
NEW
106
        fmt.Println()
×
NEW
107
        fmt.Printf("✓ Successfully configured Cursor at: %s\n", configPath)
×
NEW
108
        fmt.Println()
×
NEW
109
        fmt.Println("Configuration added:")
×
NEW
110
        fmt.Println(string(configExample))
×
NEW
111
        fmt.Println()
×
NEW
112
        fmt.Println("Next steps:")
×
NEW
113
        fmt.Println("  1. Open Cursor")
×
NEW
114
        fmt.Println("  2. Navigate to Cursor Settings > Tools & MCP")
×
NEW
115
        fmt.Println("  3. Enable the 'supabase' MCP server")
×
NEW
116
        fmt.Println()
×
NEW
117
        fmt.Println("The Supabase MCP server will then be available in Cursor!")
×
NEW
118
        return nil
×
119
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc