Skip to content
Open
13 changes: 10 additions & 3 deletions apps/backend/internal/agent/agents/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"errors"
"time"

"github.com/kandev/kandev/internal/agent/mcpconfig"
"github.com/kandev/kandev/internal/agent/usage"
"github.com/kandev/kandev/internal/agentruntime"
"github.com/kandev/kandev/pkg/agent"
Expand Down Expand Up @@ -157,7 +158,10 @@ type PassthroughOptions struct {
Resume bool // generic "continue last session" (e.g. -c, --resume latest)
PermissionValues map[string]bool // e.g. {"auto_approve": true}
WorkDir string
MCPConfigPath string // path to generated MCP config file for passthrough CLIs that support it
// MCPArgs are extra argv tokens produced by the agent's MCP passthrough
// strategy (e.g. claude's "--mcp-config <path>", codex's repeated "-c
// mcp_servers.…" overrides). Appended to the built command.
MCPArgs []string
// CLIFlagTokens are user-configured CLI flag argv tokens derived from
// AgentProfile.CLIFlags (only Enabled entries, shell-tokenised). Appended
// verbatim to the built passthrough command, mirroring CommandOptions.
Expand Down Expand Up @@ -253,8 +257,11 @@ type PassthroughConfig struct {
StabilityWindow time.Duration
ResumeFlag Param // generic "continue last session" (e.g. NewParam("-c"), NewParam("--resume", "latest"))
SessionResumeFlag Param // resume a specific session by ID (e.g. NewParam("--resume"))
MCPConfigFlag Param // flag used to load an MCP config file, e.g. NewParam("--mcp-config", "{mcp_config}")
WaitForTerminal bool
// MCPStrategy materializes resolved MCP servers into this CLI's passthrough
// shape (config file + flag, repeated -c overrides, project file, or env var)
// without touching the user's global config. Nil means no MCP injection.
MCPStrategy mcpconfig.PassthroughMCPStrategy
WaitForTerminal bool
// AutoInjectPrompt enables writing the task description to the PTY stdin
// after the first idle window. Default false preserves today's behavior.
AutoInjectPrompt bool
Expand Down
3 changes: 2 additions & 1 deletion apps/backend/internal/agent/agents/claude_acp.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
_ "embed"
"time"

"github.com/kandev/kandev/internal/agent/mcpconfig"
"github.com/kandev/kandev/internal/agent/usage"
"github.com/kandev/kandev/pkg/agent"
)
Expand Down Expand Up @@ -44,7 +45,7 @@ func NewClaudeACP() *ClaudeACP {
BufferMaxBytes: DefaultBufferMaxBytes,
ResumeFlag: NewParam("-c"),
SessionResumeFlag: NewParam("--resume"),
MCPConfigFlag: NewParam("--mcp-config", "{mcp_config}"),
MCPStrategy: mcpconfig.ClaudeStrategy{},
AutoInjectPrompt: true,
SubmitSequence: "\r",
DisableBracketedPaste: true,
Expand Down
2 changes: 2 additions & 0 deletions apps/backend/internal/agent/agents/codex_acp.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
_ "embed"
"time"

"github.com/kandev/kandev/internal/agent/mcpconfig"
"github.com/kandev/kandev/internal/agent/usage"
"github.com/kandev/kandev/pkg/agent"
)
Expand Down Expand Up @@ -56,6 +57,7 @@ func NewCodexACP() *CodexACP {
ModelFlag: NewParam("--model", "{model}"),
IdleTimeout: 3 * time.Second,
BufferMaxBytes: DefaultBufferMaxBytes,
MCPStrategy: mcpconfig.CodexStrategy{},
AutoInjectPrompt: true,
SubmitSequence: "\r",
},
Expand Down
4 changes: 4 additions & 0 deletions apps/backend/internal/agent/agents/cursor_acp.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
_ "embed"
"time"

"github.com/kandev/kandev/internal/agent/mcpconfig"
"github.com/kandev/kandev/internal/agent/usage"
"github.com/kandev/kandev/pkg/agent"
)
Expand Down Expand Up @@ -43,6 +44,9 @@ func NewCursorACP() *CursorACP {
ModelFlag: NewParam("--model", "{model}"),
IdleTimeout: 3 * time.Second,
BufferMaxBytes: DefaultBufferMaxBytes,
// cursor-agent has no MCP flag/env; write a project-local
// .cursor/mcp.json into the worktree (only if absent).
MCPStrategy: mcpconfig.CursorStrategy{},
},
},
}
Expand Down
19 changes: 0 additions & 19 deletions apps/backend/internal/agent/agents/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,25 +104,6 @@ func (b *CmdBuilder) Prompt(flag Param, prompt string) *CmdBuilder {
return b
}

// MCPConfig appends an MCP config flag when a passthrough CLI supports one.
// flag args support {mcp_config} placeholder, e.g. NewParam("--mcp-config", "{mcp_config}").
func (b *CmdBuilder) MCPConfig(flag Param, path string) *CmdBuilder {
if flag.IsEmpty() || path == "" {
return b
}
hasPlaceholder := false
for _, arg := range flag.args {
if strings.Contains(arg, "{mcp_config}") {
hasPlaceholder = true
}
b.args = append(b.args, strings.ReplaceAll(arg, "{mcp_config}", path))
}
if !hasPlaceholder {
b.args = append(b.args, path)
}
return b
}

// Flag appends arbitrary flag parts to the command.
func (b *CmdBuilder) Flag(parts ...string) *CmdBuilder {
b.args = append(b.args, parts...)
Expand Down
5 changes: 5 additions & 0 deletions apps/backend/internal/agent/agents/opencode_acp.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
_ "embed"
"time"

"github.com/kandev/kandev/internal/agent/mcpconfig"
"github.com/kandev/kandev/internal/agent/usage"
"github.com/kandev/kandev/pkg/agent"
)
Expand Down Expand Up @@ -43,6 +44,10 @@ func NewOpenCodeACP() *OpenCodeACP {
IdleTimeout: 3 * time.Second,
BufferMaxBytes: DefaultBufferMaxBytes,
ResumeFlag: NewParam("-c"),
// opencode has no MCP flag; write a temp opencode.json and point
// it there via the OPENCODE_CONFIG env var (merges, never writes
// ~/.config/opencode).
MCPStrategy: mcpconfig.OpenCodeStrategy{},
},
},
}
Expand Down
6 changes: 5 additions & 1 deletion apps/backend/internal/agent/agents/passthrough.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ func (p *StandardPassthrough) BuildPassthroughCommand(opts PassthroughOptions) C
case opts.Prompt != "":
b.Prompt(p.Cfg.PromptFlag, opts.Prompt)
}
b.MCPConfig(p.Cfg.MCPConfigFlag, opts.MCPConfigPath)

// MCP injection args go last so Claude Code's variadic --mcp-config does not
// swallow a positional prompt as an extra config path. Codex's `-c` overrides
// are order-insensitive, so trailing placement is safe for them too.
b.Flag(opts.MCPArgs...)

return b.Build()
}
Loading
Loading