Skip to content

Commit 3f47bf4

Browse files
committed
Revert "feat: explicit OAuth configuration for remote MCP servers (#2248)"
This reverts commit 093a412.
1 parent 093a412 commit 3f47bf4

File tree

11 files changed

+19
-446
lines changed

11 files changed

+19
-446
lines changed

agent-schema.json

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,48 +1205,13 @@
12051205
"additionalProperties": {
12061206
"type": "string"
12071207
}
1208-
},
1209-
"oauth": {
1210-
"$ref": "#/definitions/RemoteOAuthConfig",
1211-
"description": "Explicit OAuth configuration for remote MCP servers that do not support Dynamic Client Registration"
12121208
}
12131209
},
12141210
"required": [
12151211
"url"
12161212
],
12171213
"additionalProperties": false
12181214
},
1219-
"RemoteOAuthConfig": {
1220-
"type": "object",
1221-
"description": "Explicit OAuth configuration for remote MCP servers. Allows using pre-registered OAuth clients with servers that do not support Dynamic Client Registration (RFC 7591), such as the Slack MCP server.",
1222-
"properties": {
1223-
"client_id": {
1224-
"type": "string",
1225-
"description": "OAuth client ID (required for explicit OAuth)",
1226-
"examples": ["3660753192626.8903469228982"]
1227-
},
1228-
"client_secret": {
1229-
"type": "string",
1230-
"description": "OAuth client secret (optional, for confidential clients)"
1231-
},
1232-
"callback_port": {
1233-
"type": "integer",
1234-
"description": "Fixed port for the OAuth callback server (optional). When not specified, a random available port is used.",
1235-
"examples": [3118]
1236-
},
1237-
"scopes": {
1238-
"type": "array",
1239-
"description": "List of OAuth scopes to request (optional). When not specified, default scopes from the server are used.",
1240-
"items": {
1241-
"type": "string"
1242-
},
1243-
"examples": [
1244-
["search:read.public", "chat:write"]
1245-
]
1246-
}
1247-
},
1248-
"additionalProperties": false
1249-
},
12501215
"ScriptShellToolConfig": {
12511216
"type": "object",
12521217
"description": "Configuration for custom shell tool",

examples/slack-oauth-example.yaml

Lines changed: 0 additions & 96 deletions
This file was deleted.

pkg/config/latest/types.go

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -624,26 +624,9 @@ func (t *Toolset) UnmarshalYAML(unmarshal func(any) error) error {
624624
}
625625

626626
type Remote struct {
627-
URL string `json:"url"`
628-
TransportType string `json:"transport_type,omitempty"`
629-
Headers map[string]string `json:"headers,omitempty"`
630-
OAuth *RemoteOAuthConfig `json:"oauth,omitempty"`
631-
}
632-
633-
// RemoteOAuthConfig represents explicit OAuth configuration for remote MCP servers.
634-
// This allows using pre-registered OAuth clients with servers that do not support
635-
// Dynamic Client Registration (RFC 7591), such as the Slack MCP server.
636-
type RemoteOAuthConfig struct {
637-
// ClientID is the OAuth client ID (required for explicit OAuth)
638-
ClientID string `json:"client_id,omitempty"`
639-
// ClientSecret is the OAuth client secret (optional, for confidential clients)
640-
ClientSecret string `json:"client_secret,omitempty"`
641-
// CallbackPort is the fixed port for the OAuth callback server (optional)
642-
// When not specified, a random available port is used
643-
CallbackPort int `json:"callback_port,omitempty"`
644-
// Scopes is the list of OAuth scopes to request (optional)
645-
// When not specified, default scopes from the server are used
646-
Scopes []string `json:"scopes,omitempty"`
627+
URL string `json:"url"`
628+
TransportType string `json:"transport_type,omitempty"`
629+
Headers map[string]string `json:"headers,omitempty"`
647630
}
648631

649632
// DeferConfig represents the deferred loading configuration for a toolset.

pkg/runtime/remote_runtime.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,6 @@ func (r *RemoteRuntime) handleOAuthElicitation(ctx context.Context, req *Elicita
362362
state,
363363
oauth2.S256ChallengeFromVerifier(verifier),
364364
serverURL,
365-
nil, // scopes - use server defaults
366365
)
367366

368367
slog.Debug("Authorization URL built", "url", authURL)

pkg/teamloader/registry.go

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -250,16 +250,6 @@ func createMCPTool(ctx context.Context, toolset latest.Toolset, _ string, runCon
250250

251251
// TODO(dga): until the MCP Gateway supports oauth with docker agent, we fetch the remote url and directly connect to it.
252252
if serverSpec.Type == "remote" {
253-
// Check if explicit OAuth config is provided in the toolset
254-
if toolset.Remote.OAuth != nil {
255-
oauthConfig := &mcp.RemoteOAuthConfig{
256-
ClientID: toolset.Remote.OAuth.ClientID,
257-
ClientSecret: toolset.Remote.OAuth.ClientSecret,
258-
CallbackPort: toolset.Remote.OAuth.CallbackPort,
259-
Scopes: toolset.Remote.OAuth.Scopes,
260-
}
261-
return mcp.NewRemoteToolsetWithOAuth(toolset.Name, serverSpec.Remote.URL, serverSpec.Remote.TransportType, nil, oauthConfig), nil
262-
}
263253
return mcp.NewRemoteToolset(toolset.Name, serverSpec.Remote.URL, serverSpec.Remote.TransportType, nil), nil
264254
}
265255

@@ -301,17 +291,6 @@ func createMCPTool(ctx context.Context, toolset latest.Toolset, _ string, runCon
301291
headers := expander.ExpandMap(ctx, toolset.Remote.Headers)
302292
url := expander.Expand(ctx, toolset.Remote.URL, nil)
303293

304-
// Use explicit OAuth config if provided
305-
if toolset.Remote.OAuth != nil {
306-
oauthConfig := &mcp.RemoteOAuthConfig{
307-
ClientID: toolset.Remote.OAuth.ClientID,
308-
ClientSecret: toolset.Remote.OAuth.ClientSecret,
309-
CallbackPort: toolset.Remote.OAuth.CallbackPort,
310-
Scopes: toolset.Remote.OAuth.Scopes,
311-
}
312-
return mcp.NewRemoteToolsetWithOAuth(toolset.Name, url, toolset.Remote.TransportType, headers, oauthConfig), nil
313-
}
314-
315294
return mcp.NewRemoteToolset(toolset.Name, url, toolset.Remote.TransportType, headers), nil
316295

317296
default:

pkg/tools/mcp/mcp.go

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,6 @@ import (
2020
"github.com/docker/docker-agent/pkg/tools"
2121
)
2222

23-
// RemoteOAuthConfig represents explicit OAuth configuration for remote MCP servers.
24-
// This allows using pre-registered OAuth clients with servers that do not support
25-
// Dynamic Client Registration (RFC 7591), such as the Slack MCP server.
26-
type RemoteOAuthConfig struct {
27-
// ClientID is the OAuth client ID (required for explicit OAuth)
28-
ClientID string
29-
// ClientSecret is the OAuth client secret (optional, for confidential clients)
30-
ClientSecret string
31-
// CallbackPort is the fixed port for the OAuth callback server (optional)
32-
// When not specified, a random available port is used
33-
CallbackPort int
34-
// Scopes is the list of OAuth scopes to request (optional)
35-
// When not specified, default scopes from the server are used
36-
Scopes []string
37-
}
38-
3923
type mcpClient interface {
4024
Initialize(ctx context.Context, request *mcp.InitializeRequest) (*mcp.InitializeResult, error)
4125
ListTools(ctx context.Context, request *mcp.ListToolsParams) iter.Seq2[*mcp.Tool, error]
@@ -123,20 +107,6 @@ func NewRemoteToolset(name, urlString, transport string, headers map[string]stri
123107
}
124108
}
125109

126-
// NewRemoteToolsetWithOAuth creates a new MCP toolset from a remote MCP Server with explicit OAuth configuration.
127-
func NewRemoteToolsetWithOAuth(name, urlString, transport string, headers map[string]string, oauthConfig *RemoteOAuthConfig) *Toolset {
128-
slog.Debug("Creating Remote MCP toolset with OAuth", "url", urlString, "transport", transport, "headers", headers)
129-
130-
desc := buildRemoteDescription(urlString, transport)
131-
client := newRemoteClient(urlString, transport, headers, NewInMemoryTokenStore()).WithOAuthConfig(oauthConfig)
132-
return &Toolset{
133-
name: name,
134-
mcpClient: client,
135-
logID: urlString,
136-
description: desc,
137-
}
138-
}
139-
140110
// errServerUnavailable is returned by doStart when the MCP server could not be
141111
// reached but the error is non-fatal (e.g. EOF). The toolset is considered
142112
// "started" so the agent can proceed, but watchConnection must not be spawned

pkg/tools/mcp/oauth.go

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,10 @@ func resourceMetadataFromWWWAuth(wwwAuth string) string {
161161
type oauthTransport struct {
162162
base http.RoundTripper
163163
// TODO(rumpl): remove client reference, we need to find a better way to send elicitation requests
164-
client *remoteMCPClient
165-
tokenStore OAuthTokenStore
166-
baseURL string
167-
managed bool
168-
oauthConfig *RemoteOAuthConfig
164+
client *remoteMCPClient
165+
tokenStore OAuthTokenStore
166+
baseURL string
167+
managed bool
169168
}
170169

171170
func (t *oauthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
@@ -266,11 +265,6 @@ func (t *oauthTransport) handleManagedOAuthFlow(ctx context.Context, authServer,
266265
}
267266
}()
268267

269-
// Use explicit callback port if configured
270-
if t.oauthConfig != nil && t.oauthConfig.CallbackPort > 0 {
271-
callbackServer.SetPort(t.oauthConfig.CallbackPort)
272-
}
273-
274268
if err := callbackServer.Start(); err != nil {
275269
return fmt.Errorf("failed to start callback server: %w", err)
276270
}
@@ -281,22 +275,17 @@ func (t *oauthTransport) handleManagedOAuthFlow(ctx context.Context, authServer,
281275
var clientID string
282276
var clientSecret string
283277

284-
// Use explicit OAuth credentials if provided, otherwise attempt dynamic registration
285-
if t.oauthConfig != nil && t.oauthConfig.ClientID != "" {
286-
slog.Debug("Using explicit OAuth client ID from configuration")
287-
clientID = t.oauthConfig.ClientID
288-
clientSecret = t.oauthConfig.ClientSecret
289-
} else if authServerMetadata.RegistrationEndpoint != "" {
278+
if authServerMetadata.RegistrationEndpoint != "" {
290279
slog.Debug("Attempting dynamic client registration")
291-
clientID, clientSecret, err = RegisterClient(ctx, authServerMetadata, redirectURI, t.oauthConfig.Scopes)
280+
clientID, clientSecret, err = RegisterClient(ctx, authServerMetadata, redirectURI, nil)
292281
if err != nil {
293282
slog.Debug("Dynamic registration failed", "error", err)
294-
// If explicit client ID was not provided and registration failed, return error
295-
return fmt.Errorf("dynamic client registration failed and no explicit client ID provided: %w", err)
283+
// TODO(rumpl): fall back to requesting client ID from user
284+
return err
296285
}
297286
} else {
298-
// No dynamic registration support and no explicit credentials
299-
return errors.New("authorization server does not support dynamic client registration and no explicit OAuth credentials provided")
287+
// TODO(rumpl): fall back to requesting client ID from user
288+
return errors.New("authorization server does not support dynamic client registration")
300289
}
301290

302291
state, err := GenerateState()
@@ -307,20 +296,13 @@ func (t *oauthTransport) handleManagedOAuthFlow(ctx context.Context, authServer,
307296
callbackServer.SetExpectedState(state)
308297
verifier := GeneratePKCEVerifier()
309298

310-
// Use explicit scopes if provided, otherwise use server defaults
311-
scopes := authServerMetadata.ScopesSupported
312-
if t.oauthConfig != nil && len(t.oauthConfig.Scopes) > 0 {
313-
scopes = t.oauthConfig.Scopes
314-
}
315-
316299
authURL := BuildAuthorizationURL(
317300
authServerMetadata.AuthorizationEndpoint,
318301
clientID,
319302
redirectURI,
320303
state,
321304
oauth2.S256ChallengeFromVerifier(verifier),
322305
t.baseURL,
323-
scopes,
324306
)
325307

326308
result, err := t.client.requestElicitation(ctx, &mcpsdk.ElicitParams{

0 commit comments

Comments
 (0)