Skip to content

Commit e092095

Browse files
fix(mcp): infer session start directory
1 parent 0f7bf83 commit e092095

2 files changed

Lines changed: 130 additions & 0 deletions

File tree

internal/mcp/mcp.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,12 @@ func handleSessionStart(s *store.Store, cfg MCPConfig, activity *SessionActivity
14301430
project, _ := store.NormalizeProject(detRes.Project)
14311431

14321432
activity.RecordToolCall(defaultSessionID(project))
1433+
if strings.TrimSpace(directory) == "" {
1434+
directory = strings.TrimSpace(detRes.Path)
1435+
if directory == "" {
1436+
directory = currentWorkingDirectory()
1437+
}
1438+
}
14331439

14341440
if err := s.CreateSession(id, project, directory); err != nil {
14351441
return mcp.NewToolResultError("Failed to start session: " + err.Error()), nil

internal/mcp/mcp_test.go

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2544,6 +2544,130 @@ func TestSessionStartUsesDefaultSessionID(t *testing.T) {
25442544
}
25452545
}
25462546

2547+
func TestSessionStartWithoutDirectoryUsesCurrentWorkingDirectory(t *testing.T) {
2548+
s := newMCPTestStore(t)
2549+
2550+
dir := t.TempDir()
2551+
initTestGitRepo(t, dir)
2552+
cmd := exec.Command("git", "-C", dir, "remote", "add", "origin",
2553+
"git@github.com:user/session-start-cwd-project.git")
2554+
if out, err := cmd.CombinedOutput(); err != nil {
2555+
t.Fatalf("git remote add: %v\n%s", err, out)
2556+
}
2557+
t.Chdir(dir)
2558+
if err := s.EnrollProject("session-start-cwd-project"); err != nil {
2559+
t.Fatalf("enroll project: %v", err)
2560+
}
2561+
2562+
start := handleSessionStart(s, MCPConfig{}, NewSessionActivity(10*time.Minute))
2563+
res, err := start(context.Background(), mcppkg.CallToolRequest{
2564+
Params: mcppkg.CallToolParams{Arguments: map[string]any{
2565+
"id": "session-start-cwd",
2566+
}},
2567+
})
2568+
if err != nil || res.IsError {
2569+
t.Fatalf("session start: err=%v isError=%v text=%s", err, res.IsError, callResultText(t, res))
2570+
}
2571+
2572+
sess, err := s.GetSession("session-start-cwd")
2573+
if err != nil {
2574+
t.Fatalf("get session: %v", err)
2575+
}
2576+
wantDir, err := filepath.EvalSymlinks(dir)
2577+
if err != nil {
2578+
t.Fatalf("eval expected dir: %v", err)
2579+
}
2580+
gotDir, err := filepath.EvalSymlinks(sess.Directory)
2581+
if err != nil {
2582+
t.Fatalf("eval session dir: %v", err)
2583+
}
2584+
if gotDir != wantDir {
2585+
t.Fatalf("expected directory=%q, got %q", wantDir, gotDir)
2586+
}
2587+
assertSessionSyncMutationDirectory(t, s, "session-start-cwd", sess.Directory)
2588+
}
2589+
2590+
func TestSessionStartWithWhitespaceDirectoryUsesCurrentWorkingDirectory(t *testing.T) {
2591+
s := newMCPTestStore(t)
2592+
2593+
dir := t.TempDir()
2594+
initTestGitRepo(t, dir)
2595+
cmd := exec.Command("git", "-C", dir, "remote", "add", "origin",
2596+
"git@github.com:user/session-start-whitespace-project.git")
2597+
if out, err := cmd.CombinedOutput(); err != nil {
2598+
t.Fatalf("git remote add: %v\n%s", err, out)
2599+
}
2600+
t.Chdir(dir)
2601+
if err := s.EnrollProject("session-start-whitespace-project"); err != nil {
2602+
t.Fatalf("enroll project: %v", err)
2603+
}
2604+
2605+
start := handleSessionStart(s, MCPConfig{}, NewSessionActivity(10*time.Minute))
2606+
res, err := start(context.Background(), mcppkg.CallToolRequest{
2607+
Params: mcppkg.CallToolParams{Arguments: map[string]any{
2608+
"id": "session-start-whitespace",
2609+
"directory": " \t\n ",
2610+
}},
2611+
})
2612+
if err != nil || res.IsError {
2613+
t.Fatalf("session start: err=%v isError=%v text=%s", err, res.IsError, callResultText(t, res))
2614+
}
2615+
2616+
sess, err := s.GetSession("session-start-whitespace")
2617+
if err != nil {
2618+
t.Fatalf("get session: %v", err)
2619+
}
2620+
wantDir, err := filepath.EvalSymlinks(dir)
2621+
if err != nil {
2622+
t.Fatalf("eval expected dir: %v", err)
2623+
}
2624+
gotDir, err := filepath.EvalSymlinks(sess.Directory)
2625+
if err != nil {
2626+
t.Fatalf("eval session dir: %v", err)
2627+
}
2628+
if gotDir != wantDir {
2629+
t.Fatalf("expected directory=%q, got %q", wantDir, gotDir)
2630+
}
2631+
assertSessionSyncMutationDirectory(t, s, "session-start-whitespace", sess.Directory)
2632+
}
2633+
2634+
func TestSessionStartWithExplicitDirectoryPreservesDirectory(t *testing.T) {
2635+
s := newMCPTestStore(t)
2636+
2637+
dir := t.TempDir()
2638+
initTestGitRepo(t, dir)
2639+
cmd := exec.Command("git", "-C", dir, "remote", "add", "origin",
2640+
"git@github.com:user/session-start-explicit-project.git")
2641+
if out, err := cmd.CombinedOutput(); err != nil {
2642+
t.Fatalf("git remote add: %v\n%s", err, out)
2643+
}
2644+
t.Chdir(dir)
2645+
if err := s.EnrollProject("session-start-explicit-project"); err != nil {
2646+
t.Fatalf("enroll project: %v", err)
2647+
}
2648+
explicitDir := filepath.Join(t.TempDir(), "explicit-worktree")
2649+
2650+
start := handleSessionStart(s, MCPConfig{}, NewSessionActivity(10*time.Minute))
2651+
res, err := start(context.Background(), mcppkg.CallToolRequest{
2652+
Params: mcppkg.CallToolParams{Arguments: map[string]any{
2653+
"id": "session-start-explicit",
2654+
"directory": explicitDir,
2655+
}},
2656+
})
2657+
if err != nil || res.IsError {
2658+
t.Fatalf("session start: err=%v isError=%v text=%s", err, res.IsError, callResultText(t, res))
2659+
}
2660+
2661+
sess, err := s.GetSession("session-start-explicit")
2662+
if err != nil {
2663+
t.Fatalf("get session: %v", err)
2664+
}
2665+
if sess.Directory != explicitDir {
2666+
t.Fatalf("expected directory=%q, got %q", explicitDir, sess.Directory)
2667+
}
2668+
assertSessionSyncMutationDirectory(t, s, "session-start-explicit", explicitDir)
2669+
}
2670+
25472671
// ─── Batch 4: Write handler schema + auto-detect ─────────────────────────────
25482672

25492673
// TestWriteSchema_NoProjectField asserts that the 6 write tools do NOT include

0 commit comments

Comments
 (0)