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:
@ -22,9 +22,8 @@ func NewDeps(client *codersdk.Client, opts ...func(*Deps)) (Deps, error) {
|
||||
for _, opt := range opts {
|
||||
opt(&d)
|
||||
}
|
||||
if d.coderClient == nil {
|
||||
return Deps{}, xerrors.New("developer error: coder client may not be nil")
|
||||
}
|
||||
// Allow nil client for unauthenticated operation
|
||||
// This enables tools that don't require user authentication to function
|
||||
return d, nil
|
||||
}
|
||||
|
||||
@ -54,6 +53,11 @@ type HandlerFunc[Arg, Ret any] func(context.Context, Deps, Arg) (Ret, error)
|
||||
type Tool[Arg, Ret any] struct {
|
||||
aisdk.Tool
|
||||
Handler HandlerFunc[Arg, Ret]
|
||||
|
||||
// UserClientOptional indicates whether this tool can function without a valid
|
||||
// user authentication token. If true, the tool will be available even when
|
||||
// running in an unauthenticated mode with just an agent token.
|
||||
UserClientOptional bool
|
||||
}
|
||||
|
||||
// Generic returns a type-erased version of a TypedTool where the arguments and
|
||||
@ -63,7 +67,8 @@ type Tool[Arg, Ret any] struct {
|
||||
// conversion.
|
||||
func (t Tool[Arg, Ret]) Generic() GenericTool {
|
||||
return GenericTool{
|
||||
Tool: t.Tool,
|
||||
Tool: t.Tool,
|
||||
UserClientOptional: t.UserClientOptional,
|
||||
Handler: wrap(func(ctx context.Context, deps Deps, args json.RawMessage) (json.RawMessage, error) {
|
||||
var typedArgs Arg
|
||||
if err := json.Unmarshal(args, &typedArgs); err != nil {
|
||||
@ -85,6 +90,11 @@ func (t Tool[Arg, Ret]) Generic() GenericTool {
|
||||
type GenericTool struct {
|
||||
aisdk.Tool
|
||||
Handler GenericHandlerFunc
|
||||
|
||||
// UserClientOptional indicates whether this tool can function without a valid
|
||||
// user authentication token. If true, the tool will be available even when
|
||||
// running in an unauthenticated mode with just an agent token.
|
||||
UserClientOptional bool
|
||||
}
|
||||
|
||||
// GenericHandlerFunc is a function that handles a tool call.
|
||||
@ -195,6 +205,7 @@ var ReportTask = Tool[ReportTaskArgs, codersdk.Response]{
|
||||
Required: []string{"summary", "link", "state"},
|
||||
},
|
||||
},
|
||||
UserClientOptional: true,
|
||||
Handler: func(ctx context.Context, deps Deps, args ReportTaskArgs) (codersdk.Response, error) {
|
||||
if deps.agentClient == nil {
|
||||
return codersdk.Response{}, xerrors.New("tool unavailable as CODER_AGENT_TOKEN or CODER_AGENT_TOKEN_FILE not set")
|
||||
|
Reference in New Issue
Block a user