mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix: reuse shared tailnet for coderd-hosted MCP workspace tools (#24460)
## Problem Coderd can expose an MCP server at `/api/experimental/mcp/http` (we have this enabled on dogfood). Its workspace tools dialed agents through a per-call client-side tailnet stack. Every tool call re-created a WireGuard device, netstack, magicsock + UDP sockets, DERP connection, coordinator websocket, and their goroutines — in a process that already runs a long-lived shared tailnet. The duplicate stacks drove up resource usage under load. ## Fix Route this server's tool calls through the existing shared tailnet, so none of those transports are reconstructed per call. Closing an `AgentConn` now releases a tunnel reference instead of tearing down a transport. ## Potential follow-up `coder exp mcp server` still builds a fresh tailnet per call. It pays per-call latency and causes coordinator/DERP churn. A shared CLI tailnet is more involved — unlike coderd, the CLI has no existing shared tailnet to reuse, so it would need a new long-lived client-side tailnet with reconnect, sleep/wake, and idle-destination handling. There's less motivation to optimize this, given the client-side MCP does not compete for resources with coderd. Closes CODAGT-199 > Generated by mux, but reviewed by a human
This commit is contained in:
+4
-2
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/coder/coder/v2/coderd/httpmw"
|
||||
"github.com/coder/coder/v2/coderd/mcp"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
"github.com/coder/coder/v2/codersdk/toolsdk"
|
||||
)
|
||||
|
||||
type MCPToolset string
|
||||
@@ -34,6 +35,7 @@ func (api *API) mcpHTTPHandler() http.Handler {
|
||||
// Extract the original session token from the request
|
||||
authenticatedClient := codersdk.New(api.AccessURL,
|
||||
codersdk.WithSessionToken(httpmw.APITokenFromRequest(r)))
|
||||
toolOpt := toolsdk.WithAgentConnFunc(api.agentProvider.AgentConn)
|
||||
toolset := MCPToolset(r.URL.Query().Get("toolset"))
|
||||
// Default to standard toolset if no toolset is specified.
|
||||
if toolset == "" {
|
||||
@@ -42,11 +44,11 @@ func (api *API) mcpHTTPHandler() http.Handler {
|
||||
|
||||
switch toolset {
|
||||
case MCPToolsetStandard:
|
||||
if err := mcpServer.RegisterTools(authenticatedClient); err != nil {
|
||||
if err := mcpServer.RegisterTools(authenticatedClient, toolOpt); err != nil {
|
||||
api.Logger.Warn(r.Context(), "failed to register MCP tools", slog.Error(err))
|
||||
}
|
||||
case MCPToolsetChatGPT:
|
||||
if err := mcpServer.RegisterChatGPTTools(authenticatedClient); err != nil {
|
||||
if err := mcpServer.RegisterChatGPTTools(authenticatedClient, toolOpt); err != nil {
|
||||
api.Logger.Warn(r.Context(), "failed to register MCP tools", slog.Error(err))
|
||||
}
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user