@@ -15,6 +15,7 @@ import (
1515 "github.com/mark3labs/mcphost/internal/models"
1616 "github.com/mark3labs/mcphost/internal/ui"
1717 "github.com/spf13/cobra"
18+ "github.com/spf13/viper"
1819 "gopkg.in/yaml.v3"
1920)
2021
3233 promptFlag string
3334 quietFlag bool
3435 scriptFlag bool
36+ maxSteps int
3537 scriptMCPConfig * config.Config // Used to override config in script mode
3638)
3739
@@ -79,7 +81,7 @@ func init() {
7981 rootCmd .PersistentFlags ().
8082 StringVar (& systemPromptFile , "system-prompt" , "" , "system prompt json file" )
8183 rootCmd .PersistentFlags ().
82- IntVar (& messageWindow , "message-window" , 10 , "number of messages to keep in context" )
84+ IntVar (& messageWindow , "message-window" , 40 , "number of messages to keep in context" )
8385 rootCmd .PersistentFlags ().
8486 StringVarP (& modelFlag , "model" , "m" , "anthropic:claude-sonnet-4-20250514" ,
8587 "model to use (format: provider:model)" )
@@ -91,13 +93,27 @@ func init() {
9193 BoolVar (& quietFlag , "quiet" , false , "suppress all output (only works with --prompt)" )
9294 rootCmd .PersistentFlags ().
9395 BoolVar (& scriptFlag , "script" , false , "run in script mode (parse YAML frontmatter and prompt from file)" )
96+ rootCmd .PersistentFlags ().
97+ IntVar (& maxSteps , "max-steps" , 0 , "maximum number of agent steps (0 for unlimited)" )
9498
9599 flags := rootCmd .PersistentFlags ()
96100 flags .StringVar (& openaiBaseURL , "openai-url" , "" , "base URL for OpenAI API" )
97101 flags .StringVar (& anthropicBaseURL , "anthropic-url" , "" , "base URL for Anthropic API" )
98102 flags .StringVar (& openaiAPIKey , "openai-api-key" , "" , "OpenAI API key" )
99103 flags .StringVar (& anthropicAPIKey , "anthropic-api-key" , "" , "Anthropic API key" )
100104 flags .StringVar (& googleAPIKey , "google-api-key" , "" , "Google (Gemini) API key" )
105+
106+ // Bind flags to viper for config file support
107+ viper .BindPFlag ("system-prompt" , rootCmd .PersistentFlags ().Lookup ("system-prompt" ))
108+ viper .BindPFlag ("message-window" , rootCmd .PersistentFlags ().Lookup ("message-window" ))
109+ viper .BindPFlag ("model" , rootCmd .PersistentFlags ().Lookup ("model" ))
110+ viper .BindPFlag ("debug" , rootCmd .PersistentFlags ().Lookup ("debug" ))
111+ viper .BindPFlag ("max-steps" , rootCmd .PersistentFlags ().Lookup ("max-steps" ))
112+ viper .BindPFlag ("openai-url" , rootCmd .PersistentFlags ().Lookup ("openai-url" ))
113+ viper .BindPFlag ("anthropic-url" , rootCmd .PersistentFlags ().Lookup ("anthropic-url" ))
114+ viper .BindPFlag ("openai-api-key" , rootCmd .PersistentFlags ().Lookup ("openai-api-key" ))
115+ viper .BindPFlag ("anthropic-api-key" , rootCmd .PersistentFlags ().Lookup ("anthropic-api-key" ))
116+ viper .BindPFlag ("google-api-key" , rootCmd .PersistentFlags ().Lookup ("google-api-key" ))
101117}
102118
103119func runMCPHost (ctx context.Context ) error {
@@ -135,6 +151,66 @@ func runNormalMode(ctx context.Context) error {
135151 }
136152 }
137153
154+ // Set up viper to read from the same config file for flag values
155+ if configFile == "" {
156+ // Use default config file locations
157+ homeDir , err := os .UserHomeDir ()
158+ if err == nil {
159+ viper .SetConfigName (".mcphost" )
160+ viper .AddConfigPath (homeDir )
161+ viper .SetConfigType ("yaml" )
162+ if err := viper .ReadInConfig (); err != nil {
163+ // Try .mcphost.json
164+ viper .SetConfigType ("json" )
165+ if err := viper .ReadInConfig (); err != nil {
166+ // Try legacy .mcp files
167+ viper .SetConfigName (".mcp" )
168+ viper .SetConfigType ("yaml" )
169+ if err := viper .ReadInConfig (); err != nil {
170+ viper .SetConfigType ("json" )
171+ viper .ReadInConfig () // Ignore error if no config found
172+ }
173+ }
174+ }
175+ }
176+ } else {
177+ // Use specified config file
178+ viper .SetConfigFile (configFile )
179+ viper .ReadInConfig () // Ignore error if file doesn't exist
180+ }
181+
182+ // Override flag values with config file values (using viper's bound values)
183+ if viper .GetString ("system-prompt" ) != "" {
184+ systemPromptFile = viper .GetString ("system-prompt" )
185+ }
186+ if viper .GetInt ("message-window" ) != 0 {
187+ messageWindow = viper .GetInt ("message-window" )
188+ }
189+ if viper .GetString ("model" ) != "" {
190+ modelFlag = viper .GetString ("model" )
191+ }
192+ if viper .GetBool ("debug" ) {
193+ debugMode = viper .GetBool ("debug" )
194+ }
195+ if viper .GetInt ("max-steps" ) != 0 {
196+ maxSteps = viper .GetInt ("max-steps" )
197+ }
198+ if viper .GetString ("openai-url" ) != "" {
199+ openaiBaseURL = viper .GetString ("openai-url" )
200+ }
201+ if viper .GetString ("anthropic-url" ) != "" {
202+ anthropicBaseURL = viper .GetString ("anthropic-url" )
203+ }
204+ if viper .GetString ("openai-api-key" ) != "" {
205+ openaiAPIKey = viper .GetString ("openai-api-key" )
206+ }
207+ if viper .GetString ("anthropic-api-key" ) != "" {
208+ anthropicAPIKey = viper .GetString ("anthropic-api-key" )
209+ }
210+ if viper .GetString ("google-api-key" ) != "" {
211+ googleAPIKey = viper .GetString ("google-api-key" )
212+ }
213+
138214 systemPrompt , err := config .LoadSystemPrompt (systemPromptFile )
139215 if err != nil {
140216 return fmt .Errorf ("failed to load system prompt: %v" , err )
@@ -152,11 +228,16 @@ func runNormalMode(ctx context.Context) error {
152228 }
153229
154230 // Create agent configuration
231+ agentMaxSteps := maxSteps
232+ if agentMaxSteps == 0 {
233+ agentMaxSteps = 1000 // Set a high limit for "unlimited"
234+ }
235+
155236 agentConfig := & agent.AgentConfig {
156237 ModelConfig : modelConfig ,
157238 MCPConfig : mcpConfig ,
158239 SystemPrompt : systemPrompt ,
159- MaxSteps : 20 ,
240+ MaxSteps : agentMaxSteps ,
160241 MessageWindow : messageWindow ,
161242 }
162243
0 commit comments