Skip to content

AddMCPServer() creates MCPToolManager without inheriting OAuth AuthHandler and TokenStoreFactory #3

Description

@ezynda3

Bug Description

When Agent.AddMCPServer() is called on a Kit host that had no MCP servers configured at init time, it creates a new MCPToolManager but does not set AuthHandler or TokenStoreFactory on it. This means OAuth-enabled remote MCP servers added at runtime via AddMCPServer() will fail to authenticate — the 401 response is not recognized as an OAuth trigger because oauthFlow is nil on the new tool manager.

Root Cause

In internal/agent/agent.go, the AddMCPServer() method (line ~845) creates a bare tool manager when one doesn't exist:

func (a *Agent) AddMCPServer(ctx context.Context, name string, cfg config.MCPServerConfig) (int, error) {
	a.ensureMCPTools()

	if a.toolManager == nil {
		a.toolManager = tools.NewMCPToolManager()
		a.toolManager.SetModel(a.model)
		a.toolManager.SetOnToolsChanged(func() {
			a.rebuildFantasyAgent()
		})
		// BUG: AuthHandler and TokenStoreFactory are NOT set here
	}

	count, err := a.toolManager.AddServer(ctx, name, cfg)
	// ...
}

Compare this with the initial agent creation in NewAgent() (line ~238) which does set them:

if agentConfig.MCPConfig != nil && len(agentConfig.MCPConfig.MCPServers) > 0 {
	toolManager := tools.NewMCPToolManager()
	toolManager.SetModel(providerResult.Model)
	if agentConfig.AuthHandler != nil {
		toolManager.SetAuthHandler(agentConfig.AuthHandler)    // ✅ Set here
	}
	if agentConfig.TokenStoreFactory != nil {
		toolManager.SetTokenStoreFactory(agentConfig.TokenStoreFactory)  // ✅ Set here
	}
	// ...
}

The Agent struct does not store AuthHandler or TokenStoreFactory — they're only available in the AgentConfig during NewAgent(). So when AddMCPServer() needs to create a new tool manager later, it has no way to access them.

Impact

Any SDK user who:

  1. Creates a Kit host with kit.New() passing MCPAuthHandler and MCPTokenStoreFactory
  2. Does NOT configure any MCP servers in the initial config
  3. Later calls host.AddMCPServer() to add a remote OAuth-enabled server

...will get a failure because the connection pool has no oauthFlow set. The 401 from the remote server is treated as a plain error instead of triggering the OAuth authorization flow.

Reproduction

host, _ := kit.New(ctx, &kit.Options{
	Model:        "anthropic/claude-sonnet-4-20250514",
	NoSession:    true,
	SkipConfig:   true,
	MCPAuthHandler: myAuthHandler,
	MCPTokenStoreFactory: myTokenStoreFactory,
})

// This fails because the new MCPToolManager has no auth handler
n, err := host.AddMCPServer(ctx, "github", kit.MCPServerConfig{
	Type: "remote",
	URL:  "https://api.githubcopilot.com/mcp/",
})
// err: "initialization timeout or failed: transport error: unauthorized (401)"
// Expected: OAuth flow should be triggered via myAuthHandler

Suggested Fix

Store AuthHandler and TokenStoreFactory on the Agent struct, then use them in AddMCPServer():

// In Agent struct, add fields:
type Agent struct {
	// ... existing fields ...
	authHandler       tools.MCPAuthHandler
	tokenStoreFactory tools.TokenStoreFactory
}

// In NewAgent(), store them:
a.authHandler = agentConfig.AuthHandler
a.tokenStoreFactory = agentConfig.TokenStoreFactory

// In AddMCPServer(), use them:
if a.toolManager == nil {
	a.toolManager = tools.NewMCPToolManager()
	a.toolManager.SetModel(a.model)
	if a.authHandler != nil {
		a.toolManager.SetAuthHandler(a.authHandler)
	}
	if a.tokenStoreFactory != nil {
		a.toolManager.SetTokenStoreFactory(a.tokenStoreFactory)
	}
	a.toolManager.SetOnToolsChanged(func() {
		a.rebuildFantasyAgent()
	})
}

Environment

  • Kit: v0.48.0
  • mcp-go: v0.47.1
  • Go: 1.26.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions