connectServer establishes a connection to a single MCP server and returns the connected client. It does not modify any Manager state.
(ctx context.Context, cfg ServerConfig)
| 923 | // and returns the connected client. It does not modify any Manager |
| 924 | // state. |
| 925 | func (m *Manager) connectServer(ctx context.Context, cfg ServerConfig) (*client.Client, error) { |
| 926 | tr, err := m.createTransport(ctx, cfg) |
| 927 | if err != nil { |
| 928 | return nil, xerrors.Errorf("create transport for %q: %w", cfg.Name, err) |
| 929 | } |
| 930 | |
| 931 | c := client.NewClient(tr) |
| 932 | |
| 933 | connectCtx, cancel := context.WithTimeout(ctx, connectTimeout) |
| 934 | defer cancel() |
| 935 | |
| 936 | // Use the parent ctx (not connectCtx) so the subprocess outlives |
| 937 | // the connect/initialize handshake. connectCtx bounds only the |
| 938 | // Initialize call below. The subprocess is cleaned up when the |
| 939 | // Manager is closed or ctx is canceled. |
| 940 | if err := c.Start(ctx); err != nil { |
| 941 | _ = c.Close() |
| 942 | return nil, xerrors.Errorf("start %q: %w", cfg.Name, err) |
| 943 | } |
| 944 | |
| 945 | _, err = c.Initialize(connectCtx, mcp.InitializeRequest{ |
| 946 | Params: mcp.InitializeParams{ |
| 947 | ProtocolVersion: mcp.LATEST_PROTOCOL_VERSION, |
| 948 | ClientInfo: mcp.Implementation{ |
| 949 | Name: "coder-agent", |
| 950 | Version: buildinfo.Version(), |
| 951 | }, |
| 952 | }, |
| 953 | }) |
| 954 | if err != nil { |
| 955 | _ = c.Close() |
| 956 | return nil, xerrors.Errorf("initialize %q: %w", cfg.Name, err) |
| 957 | } |
| 958 | |
| 959 | return c, nil |
| 960 | } |
| 961 | |
| 962 | // createTransport builds the mcp-go transport for a server config. |
| 963 | func (m *Manager) createTransport(ctx context.Context, cfg ServerConfig) (transport.Interface, error) { |