Skip to content

Commit 88cba49

Browse files
committed
feat: add interactive MCP configuration to supabase init
- Replace --mcp-client flag with interactive prompts - Add yes/no prompt: 'Configure Supabase MCP server locally?' - Add dropdown selection for client choice (Claude Code, Cursor, VS Code, Other) - Add 'Other' option for manual configuration - Update all clients to use local MCP server (http://localhost:54321/mcp) - Fix VS Code config property from 'mcpServers' to 'servers' - Replace VS Code scope selection with interactive dropdown (project/global) This implements the requirements from Linear issue AI-81.
1 parent 79948e4 commit 88cba49

File tree

5 files changed

+70
-31
lines changed

5 files changed

+70
-31
lines changed

cmd/init.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,23 @@ var (
5050
return err
5151
}
5252

53-
// Optionally configure MCP client if flag is provided
54-
mcpClient, _ := cmd.Flags().GetString("mcp-client")
55-
if mcpClient != "" {
56-
if err := mcpinit.Run(ctx, fsys, mcpClient); err != nil {
53+
// Prompt for MCP configuration if in interactive mode
54+
console := utils.NewConsole()
55+
if configureMCP, err := console.PromptYesNo(ctx, "Configure Supabase MCP server locally?", false); err != nil {
56+
return err
57+
} else if configureMCP {
58+
clientName, err := mcpinit.PromptMCPClient(ctx)
59+
if err != nil {
5760
return err
5861
}
62+
// Skip configuration if user selected "other"
63+
if clientName != "other" {
64+
if err := mcpinit.Run(ctx, fsys, clientName); err != nil {
65+
return err
66+
}
67+
}
5968
}
69+
6070
return nil
6171
},
6272
PostRun: func(cmd *cobra.Command, args []string) {
@@ -73,6 +83,5 @@ func init() {
7383
flags.BoolVar(createIntellijSettings, "with-intellij-settings", false, "Generate IntelliJ IDEA settings for Deno.")
7484
flags.BoolVar(&initParams.UseOrioleDB, "use-orioledb", false, "Use OrioleDB storage engine for Postgres.")
7585
flags.BoolVar(&initParams.Overwrite, "force", false, "Overwrite existing "+utils.ConfigPath+".")
76-
flags.String("mcp-client", "", "Configure Supabase MCP for a client (e.g., claude-code, cursor, vscode). Runs after project init if provided.")
7786
rootCmd.AddCommand(initCmd)
7887
}

internal/mcp/init/claude_code.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,11 @@ func newClaudeCodeClient() *claudeCodeClient {
2828
}
2929

3030
func (c *claudeCodeClient) Configure(ctx context.Context, fsys afero.Fs) error {
31-
fmt.Println("Adding Supabase MCP server to Claude Code...")
31+
fmt.Println("Configuring Claude Code...")
3232
fmt.Println()
3333

34-
// Build the claude mcp add command
35-
// #nosec G204 -- command and URL are controlled constants
36-
cmd := exec.CommandContext(ctx, "claude", "mcp", "add", "--transport", "http", "supabase", "https://mcp.supabase.com/mcp")
34+
// Run the 'claude mcp add' command
35+
cmd := exec.CommandContext(ctx, "claude", "mcp", "add", "--transport", "http", "supabase", "http://localhost:54321/mcp")
3736

3837
cmd.Stdout = os.Stdout
3938
cmd.Stderr = os.Stderr

internal/mcp/init/cursor.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func (c *cursorClient) Configure(ctx context.Context, fsys afero.Fs) error {
5959

6060
// Prepare the Supabase MCP server config
6161
supabaseConfig := map[string]interface{}{
62-
"url": "https://mcp.supabase.com/mcp",
62+
"url": "http://localhost:54321/mcp",
6363
}
6464

6565
// Read existing config if it exists
@@ -107,7 +107,7 @@ func (c *cursorClient) Configure(ctx context.Context, fsys afero.Fs) error {
107107
fmt.Println(`{
108108
"mcpServers": {
109109
"supabase": {
110-
"url": "https://mcp.supabase.com/mcp"
110+
"url": "http://localhost:54321/mcp"
111111
}
112112
}
113113
}`)

internal/mcp/init/init.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import (
44
"context"
55
"fmt"
66

7+
tea "github.com/charmbracelet/bubbletea"
78
"github.com/spf13/afero"
9+
"github.com/supabase/cli/internal/utils"
810
)
911

1012
// clientRegistry holds all supported clients
@@ -14,6 +16,30 @@ var clientRegistry = []Client{
1416
newVSCodeClient(),
1517
}
1618

19+
// PromptMCPClient prompts the user to select an MCP client from the available options
20+
func PromptMCPClient(ctx context.Context, opts ...tea.ProgramOption) (string, error) {
21+
// Add all clients plus "Other" option
22+
items := make([]utils.PromptItem, len(clientRegistry)+1)
23+
for i, client := range clientRegistry {
24+
items[i] = utils.PromptItem{
25+
Summary: client.Name(),
26+
Details: client.DisplayName(),
27+
}
28+
}
29+
// Add "Other" option at the end
30+
items[len(clientRegistry)] = utils.PromptItem{
31+
Summary: "other",
32+
Details: "Configure it manually",
33+
}
34+
35+
choice, err := utils.PromptChoice(ctx, "Which client do you want to configure?", items, opts...)
36+
if err != nil {
37+
return "", err
38+
}
39+
40+
return choice.Summary, nil
41+
}
42+
1743
func Run(ctx context.Context, fsys afero.Fs, clientFlag string) error {
1844
// If a specific client is requested
1945
if clientFlag != "" {

internal/mcp/init/vscode.go

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import (
77
"os"
88
"path/filepath"
99

10+
tea "github.com/charmbracelet/bubbletea"
1011
"github.com/spf13/afero"
12+
"github.com/supabase/cli/internal/utils"
1113
)
1214

1315
// vscodeClient implements the Client interface for VS Code
@@ -32,22 +34,25 @@ func (c *vscodeClient) Configure(ctx context.Context, fsys afero.Fs) error {
3234
fmt.Println("Configuring VS Code...")
3335
fmt.Println()
3436

35-
// Prompt for config scope
36-
fmt.Println("Where would you like to add the configuration?")
37-
fmt.Println(" 1. Project-local (in .vscode/mcp.json)")
38-
fmt.Println(" 2. Global (in your home directory)")
39-
fmt.Print("Choice [1]: ")
40-
41-
var choice string
42-
if _, err := fmt.Scanln(&choice); err != nil && err.Error() != "unexpected newline" {
43-
return fmt.Errorf("failed to read choice: %w", err)
37+
// Prompt for config scope using dropdown
38+
items := []utils.PromptItem{
39+
{
40+
Summary: "project",
41+
Details: "Project-local (in .vscode/mcp.json)",
42+
},
43+
{
44+
Summary: "global",
45+
Details: "Global (in your home directory)",
46+
},
4447
}
45-
if choice == "" {
46-
choice = "1"
48+
49+
choice, err := utils.PromptChoice(ctx, "Where would you like to add the configuration?", items, tea.WithOutput(os.Stderr))
50+
if err != nil {
51+
return err
4752
}
4853

4954
var configPath string
50-
if choice == "2" {
55+
if choice.Summary == "global" {
5156
// Global config
5257
homeDir, _ := os.UserHomeDir()
5358
configPath = filepath.Join(homeDir, ".vscode", "mcp.json")
@@ -60,7 +65,7 @@ func (c *vscodeClient) Configure(ctx context.Context, fsys afero.Fs) error {
6065
// Prepare the Supabase MCP server config
6166
supabaseConfig := map[string]interface{}{
6267
"type": "http",
63-
"url": "https://mcp.supabase.com/mcp",
68+
"url": "http://localhost:54321/mcp",
6469
}
6570

6671
// Read existing config if it exists
@@ -75,15 +80,15 @@ func (c *vscodeClient) Configure(ctx context.Context, fsys afero.Fs) error {
7580
config = make(map[string]interface{})
7681
}
7782

78-
// Ensure mcpServers exists
79-
mcpServers, ok := config["mcpServers"].(map[string]interface{})
83+
// Ensure servers exists
84+
servers, ok := config["servers"].(map[string]interface{})
8085
if !ok {
81-
mcpServers = make(map[string]interface{})
82-
config["mcpServers"] = mcpServers
86+
servers = make(map[string]interface{})
87+
config["servers"] = servers
8388
}
8489

8590
// Add or update Supabase server
86-
mcpServers["supabase"] = supabaseConfig
91+
servers["supabase"] = supabaseConfig
8792

8893
// Ensure directory exists
8994
configDir := filepath.Dir(configPath)
@@ -106,10 +111,10 @@ func (c *vscodeClient) Configure(ctx context.Context, fsys afero.Fs) error {
106111
fmt.Println()
107112
fmt.Println("Configuration added:")
108113
fmt.Println(`{
109-
"mcpServers": {
114+
"servers": {
110115
"supabase": {
111116
"type": "http",
112-
"url": "https://mcp.supabase.com/mcp"
117+
"url": "http://localhost:54321/mcp"
113118
}
114119
}
115120
}`)

0 commit comments

Comments
 (0)