Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 28 additions & 10 deletions cmd/kh/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,46 @@ func main() {
// rootCmd is created first so the HTTPClient closure can read --host after flag parsing.
var rootCmd *cobra.Command

// resolveActiveHost returns the effective host using the priority chain:
// --host flag > KH_HOST env > hosts.yml default > config.yml > built-in default.
resolveActiveHost := func() string {
var flagHost string
if rootCmd != nil {
if f := rootCmd.PersistentFlags().Lookup("host"); f != nil {
flagHost = f.Value.String()
}
}
envHost := os.Getenv("KH_HOST")
hosts, err := config.ReadHosts()
if err != nil {
if flagHost != "" {
return flagHost
}
if envHost != "" {
return envHost
}
return "app.keeperhub.com"
}
return hosts.ActiveHost(flagHost, envHost)
}

f := &cmdutil.Factory{
AppVersion: version.Version,
IOStreams: ios,
Config: func() (config.Config, error) {
return config.ReadConfig()
},
BaseURL: func() string {
return khhttp.BuildBaseURL(resolveActiveHost())
},
HTTPClient: func() (*khhttp.Client, error) {
activeHost := resolveActiveHost()

hosts, err := config.ReadHosts()
if err != nil {
return nil, err
}

// Priority: --host flag > KH_HOST env > hosts.yml default > built-in default
var flagHost string
if rootCmd != nil {
if f := rootCmd.PersistentFlags().Lookup("host"); f != nil {
flagHost = f.Value.String()
}
}
envHost := os.Getenv("KH_HOST")
activeHost := hosts.ActiveHost(flagHost, envHost)

// Resolve token using the auth chain: KH_API_KEY > keyring > hosts.yml
resolved, err := auth.ResolveToken(activeHost)
if err != nil {
Expand Down
7 changes: 1 addition & 6 deletions cmd/serve/schemas.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,7 @@ func fetchMCPSchemas(f *cmdutil.Factory) (*SchemasResponse, error) {
return nil, fmt.Errorf("creating HTTP client: %w", err)
}

cfg, err := f.Config()
if err != nil {
return nil, fmt.Errorf("reading config: %w", err)
}

url := khhttp.BuildBaseURL(cmdutil.ResolveHost(nil, cfg)) + "/api/mcp/schemas"
url := f.BaseURL() + "/api/mcp/schemas"
req, err := client.NewRequest(http.MethodGet, url, nil)
if err != nil {
return nil, fmt.Errorf("building request: %w", err)
Expand Down
1 change: 1 addition & 0 deletions cmd/serve/serve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func newServeFactory(server *httptest.Server, ios *iostreams.IOStreams) *cmdutil
IOStreams: ios,
HTTPClient: func() (*khhttp.Client, error) { return client, nil },
Config: func() (config.Config, error) { return config.Config{DefaultHost: server.URL}, nil },
BaseURL: func() string { return server.URL },
}
}

Expand Down
15 changes: 2 additions & 13 deletions cmd/serve/tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"net/http"
"strings"

khhttp "github.com/keeperhub/cli/internal/http"
"github.com/keeperhub/cli/pkg/cmdutil"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
Expand Down Expand Up @@ -89,12 +88,7 @@ func MakeToolHandler(f *cmdutil.Factory, actionType string) mcp.ToolHandler {
return nil, fmt.Errorf("creating HTTP client: %w", err)
}

cfg, err := f.Config()
if err != nil {
return nil, fmt.Errorf("reading config: %w", err)
}

url := khhttp.BuildBaseURL(cmdutil.ResolveHost(nil, cfg)) + "/api/execute/" + actionType
url := f.BaseURL() + "/api/execute/" + actionType
httpReq, err := client.NewRequest(http.MethodPost, url, bytes.NewReader(bodyBytes))
if err != nil {
return nil, fmt.Errorf("building request: %w", err)
Expand Down Expand Up @@ -163,12 +157,7 @@ func makeStaticHandler(
return nil, fmt.Errorf("creating HTTP client: %w", err)
}

cfg, err := f.Config()
if err != nil {
return nil, fmt.Errorf("reading config: %w", err)
}

baseURL := khhttp.BuildBaseURL(cmdutil.ResolveHost(nil, cfg))
baseURL := f.BaseURL()
targetURL := buildURL(args, baseURL)

var body io.Reader
Expand Down
5 changes: 5 additions & 0 deletions pkg/cmdutil/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ type Factory struct {
// The client automatically injects version headers and per-host credentials.
HTTPClient func() (*khhttp.Client, error)

// BaseURL returns the resolved base URL for API requests, accounting for
// --host flag, KH_HOST env, and config defaults. Use this instead of
// ResolveHost when a cobra.Command is not available (e.g. MCP serve mode).
BaseURL func() string

// IOStreams provides the standard input/output streams.
IOStreams *iostreams.IOStreams
}
Loading