(ctx context.Context, req Request)
| 60 | } |
| 61 | |
| 62 | func (m *MCPProxyFactory) retrieveMCPServerConfigs(ctx context.Context, req Request) (map[string]mcp.ServerProxier, error) { |
| 63 | client, err := m.clientFn() |
| 64 | if err != nil { |
| 65 | return nil, xerrors.Errorf("acquire client: %w", err) |
| 66 | } |
| 67 | |
| 68 | srvCfgCtx, srvCfgCancel := context.WithTimeout(ctx, time.Second*10) |
| 69 | defer srvCfgCancel() |
| 70 | |
| 71 | // Fetch MCP server configs. |
| 72 | mcpSrvCfgs, err := client.GetMCPServerConfigs(srvCfgCtx, &proto.GetMCPServerConfigsRequest{ |
| 73 | UserId: req.InitiatorID.String(), |
| 74 | }) |
| 75 | if err != nil { |
| 76 | return nil, xerrors.Errorf("get MCP server configs: %w", err) |
| 77 | } |
| 78 | |
| 79 | proxiers := make(map[string]mcp.ServerProxier, len(mcpSrvCfgs.GetExternalAuthMcpConfigs())+1) // Extra one for Coder MCP server. |
| 80 | |
| 81 | if mcpSrvCfgs.GetCoderMcpConfig() != nil { |
| 82 | // Delegated callers (e.g., chatd) do not hold the user's API key |
| 83 | // secret and so cannot authenticate against the Coder MCP server. |
| 84 | // Skip the proxy in that case rather than attempting a connection |
| 85 | // with an empty bearer token, which will fail upstream. |
| 86 | if req.SessionKey == "" { |
| 87 | m.logger.Debug(ctx, "skipping Coder MCP server proxy: no session key (delegated request)", slog.F("mcp_server_id", mcpSrvCfgs.GetCoderMcpConfig().GetId())) |
| 88 | } else { |
| 89 | // Setup the Coder MCP server proxy. |
| 90 | coderMCPProxy, err := m.newStreamableHTTPServerProxy(mcpSrvCfgs.GetCoderMcpConfig(), req.SessionKey) // The session key is used to auth against our internal MCP server. |
| 91 | if err != nil { |
| 92 | m.logger.Warn(ctx, "failed to create MCP server proxy", slog.F("mcp_server_id", mcpSrvCfgs.GetCoderMcpConfig().GetId()), slog.Error(err)) |
| 93 | } else { |
| 94 | proxiers[InternalMCPServerID] = coderMCPProxy |
| 95 | } |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | if len(mcpSrvCfgs.GetExternalAuthMcpConfigs()) == 0 { |
| 100 | return proxiers, nil |
| 101 | } |
| 102 | |
| 103 | serverIDs := make([]string, 0, len(mcpSrvCfgs.GetExternalAuthMcpConfigs())) |
| 104 | for _, cfg := range mcpSrvCfgs.GetExternalAuthMcpConfigs() { |
| 105 | serverIDs = append(serverIDs, cfg.GetId()) |
| 106 | } |
| 107 | |
| 108 | accTokCtx, accTokCancel := context.WithTimeout(ctx, time.Second*10) |
| 109 | defer accTokCancel() |
| 110 | |
| 111 | // Request a batch of access tokens, one per given server ID. |
| 112 | resp, err := client.GetMCPServerAccessTokensBatch(accTokCtx, &proto.GetMCPServerAccessTokensBatchRequest{ |
| 113 | UserId: req.InitiatorID.String(), |
| 114 | McpServerConfigIds: serverIDs, |
| 115 | }) |
| 116 | if err != nil { |
| 117 | m.logger.Warn(ctx, "failed to retrieve access token(s)", slog.F("server_ids", serverIDs), slog.Error(err)) |
| 118 | } |
| 119 |
no test coverage detected