mirror of
https://github.com/coder/coder.git
synced 2025-07-12 00:14:10 +00:00
feat(cli): make MCP server work without user authentication (#17688)
Part of #17649 --- # Allow MCP server to run without authentication This PR enhances the MCP server to operate without requiring authentication, making it more flexible for environments where authentication isn't available or necessary. Key changes: - Replaced `InitClient` with `TryInitClient` to allow the MCP server to start without credentials - Added graceful handling when URL or authentication is missing - Made authentication status visible in server logs - Added logic to skip user-dependent tools when no authenticated user is present - Made the `coder_report_task` tool available with just an agent token (no user token required) - Added comprehensive tests to verify operation without authentication These changes allow the MCP server to function in more environments while still using authentication when available, improving flexibility for CI/CD and other automated environments.
This commit is contained in:
52
cli/root.go
52
cli/root.go
@ -571,6 +571,58 @@ func (r *RootCmd) InitClient(client *codersdk.Client) serpent.MiddlewareFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// TryInitClient is similar to InitClient but doesn't error when credentials are missing.
|
||||
// This allows commands to run without requiring authentication, but still use auth if available.
|
||||
func (r *RootCmd) TryInitClient(client *codersdk.Client) serpent.MiddlewareFunc {
|
||||
return func(next serpent.HandlerFunc) serpent.HandlerFunc {
|
||||
return func(inv *serpent.Invocation) error {
|
||||
conf := r.createConfig()
|
||||
var err error
|
||||
// Read the client URL stored on disk.
|
||||
if r.clientURL == nil || r.clientURL.String() == "" {
|
||||
rawURL, err := conf.URL().Read()
|
||||
// If the configuration files are absent, just continue without URL
|
||||
if err != nil {
|
||||
// Continue with a nil or empty URL
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
r.clientURL, err = url.Parse(strings.TrimSpace(rawURL))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
// Read the token stored on disk.
|
||||
if r.token == "" {
|
||||
r.token, err = conf.Session().Read()
|
||||
// Even if there isn't a token, we don't care.
|
||||
// Some API routes can be unauthenticated.
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Only configure the client if we have a URL
|
||||
if r.clientURL != nil && r.clientURL.String() != "" {
|
||||
err = r.configureClient(inv.Context(), client, r.clientURL, inv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client.SetSessionToken(r.token)
|
||||
|
||||
if r.debugHTTP {
|
||||
client.PlainLogger = os.Stderr
|
||||
client.SetLogBodies(true)
|
||||
}
|
||||
client.DisableDirectConnections = r.disableDirect
|
||||
}
|
||||
return next(inv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HeaderTransport creates a new transport that executes `--header-command`
|
||||
// if it is set to add headers for all outbound requests.
|
||||
func (r *RootCmd) HeaderTransport(ctx context.Context, serverURL *url.URL) (*codersdk.HeaderTransport, error) {
|
||||
|
Reference in New Issue
Block a user