Skip to content

Commit 1098059

Browse files
committed
Refactor client to remove circular dependency
Move capability discovery from Client to StdioSession to break the circular dependency where session.GetClient().AddToMCPServerWithSession(session) was called. This cleaner design separates concerns and makes the code more maintainable.
1 parent d9e601a commit 1098059

File tree

4 files changed

+122
-275
lines changed

4 files changed

+122
-275
lines changed

internal/client/client.go

Lines changed: 0 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -134,83 +134,6 @@ func DefaultTransportCreator(conf *config.MCPClientConfig) (MCPClientInterface,
134134
return nil, errors.New("invalid client type: must have either command or url")
135135
}
136136

137-
// AddToMCPServer connects the client to an MCP server
138-
func (c *Client) AddToMCPServer(ctx context.Context, clientInfo mcp.Implementation, mcpServer *server.MCPServer) error {
139-
return c.AddToMCPServerWithTokenCheck(ctx, clientInfo, mcpServer, "", false, nil, "", "", nil)
140-
}
141-
142-
// AddToMCPServerWithTokenCheck connects the client to an MCP server with optional token checking
143-
func (c *Client) AddToMCPServerWithTokenCheck(
144-
ctx context.Context,
145-
clientInfo mcp.Implementation,
146-
mcpServer *server.MCPServer,
147-
userEmail string,
148-
requiresToken bool,
149-
tokenStore storage.UserTokenStore,
150-
serverName string,
151-
setupBaseURL string,
152-
tokenSetup *config.TokenSetupConfig,
153-
) error {
154-
return c.AddToMCPServerWithSession(ctx, clientInfo, mcpServer, userEmail, requiresToken, tokenStore, serverName, setupBaseURL, tokenSetup, nil)
155-
}
156-
157-
// AddToMCPServerWithSession connects the client to an MCP server with optional session-specific tools
158-
func (c *Client) AddToMCPServerWithSession(
159-
ctx context.Context,
160-
clientInfo mcp.Implementation,
161-
mcpServer *server.MCPServer,
162-
userEmail string,
163-
requiresToken bool,
164-
tokenStore storage.UserTokenStore,
165-
serverName string,
166-
setupBaseURL string,
167-
tokenSetup *config.TokenSetupConfig,
168-
session server.ClientSession,
169-
) error {
170-
if c.needManualStart {
171-
err := c.client.Start(ctx)
172-
if err != nil {
173-
return err
174-
}
175-
}
176-
initRequest := mcp.InitializeRequest{}
177-
initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION
178-
initRequest.Params.ClientInfo = clientInfo
179-
initRequest.Params.Capabilities = mcp.ClientCapabilities{
180-
Experimental: make(map[string]interface{}),
181-
Roots: nil,
182-
Sampling: nil,
183-
}
184-
_, err := c.client.Initialize(ctx, initRequest)
185-
if err != nil {
186-
return err
187-
}
188-
internal.Logf("<%s> Successfully initialized MCP client", c.name)
189-
190-
// Start capability discovery
191-
internal.LogInfoWithFields("client", "Starting MCP capability discovery", map[string]interface{}{
192-
"server": c.name,
193-
})
194-
195-
err = c.addToolsToServer(ctx, mcpServer, userEmail, requiresToken, tokenStore, serverName, setupBaseURL, tokenSetup, session)
196-
if err != nil {
197-
return err
198-
}
199-
_ = c.addPromptsToServer(ctx, mcpServer)
200-
_ = c.addResourcesToServer(ctx, mcpServer)
201-
_ = c.addResourceTemplatesToServer(ctx, mcpServer)
202-
203-
internal.LogInfoWithFields("client", "MCP capability discovery completed", map[string]interface{}{
204-
"server": c.name,
205-
"userTokenRequired": requiresToken,
206-
})
207-
208-
if c.needPing {
209-
go c.startPingTask(ctx)
210-
}
211-
return nil
212-
}
213-
214137
// startPingTask runs a goroutine that pings the MCP server every 30 seconds.
215138
// The goroutine lifecycle is tied to the provided context:
216139
// - For stdio clients: context is cancelled when the request ends, stopping pings

internal/client/session_manager.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ import (
1010

1111
"github.com/dgellow/mcp-front/internal"
1212
"github.com/dgellow/mcp-front/internal/config"
13+
"github.com/dgellow/mcp-front/internal/storage"
1314
"github.com/mark3labs/mcp-go/mcp"
15+
"github.com/mark3labs/mcp-go/server"
1416
)
1517

1618
var (
@@ -217,6 +219,75 @@ func (s *StdioSession) GetClient() *Client {
217219
return s.client
218220
}
219221

222+
// DiscoverAndRegisterCapabilities discovers and registers capabilities from the stdio process
223+
func (s *StdioSession) DiscoverAndRegisterCapabilities(
224+
ctx context.Context,
225+
mcpServer *server.MCPServer,
226+
userEmail string,
227+
requiresToken bool,
228+
tokenStore storage.UserTokenStore,
229+
serverName string,
230+
setupBaseURL string,
231+
tokenSetup *config.TokenSetupConfig,
232+
session server.ClientSession,
233+
) error {
234+
// Initialize the client
235+
if s.client.needManualStart {
236+
if err := s.client.client.Start(ctx); err != nil {
237+
return err
238+
}
239+
}
240+
241+
initRequest := mcp.InitializeRequest{}
242+
initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION
243+
initRequest.Params.ClientInfo = mcp.Implementation{
244+
Name: serverName,
245+
Version: "1.0",
246+
}
247+
initRequest.Params.Capabilities = mcp.ClientCapabilities{
248+
Experimental: make(map[string]interface{}),
249+
Roots: nil,
250+
Sampling: nil,
251+
}
252+
253+
_, err := s.client.client.Initialize(ctx, initRequest)
254+
if err != nil {
255+
return err
256+
}
257+
internal.Logf("<%s> Successfully initialized MCP client", serverName)
258+
259+
// Start capability discovery
260+
internal.LogInfoWithFields("client", "Starting MCP capability discovery", map[string]interface{}{
261+
"server": serverName,
262+
})
263+
264+
// Discover and register tools
265+
if err := s.client.addToolsToServer(ctx, mcpServer, userEmail, requiresToken, tokenStore, serverName, setupBaseURL, tokenSetup, session); err != nil {
266+
return err
267+
}
268+
269+
// Discover and register prompts
270+
_ = s.client.addPromptsToServer(ctx, mcpServer)
271+
272+
// Discover and register resources
273+
_ = s.client.addResourcesToServer(ctx, mcpServer)
274+
275+
// Discover and register resource templates
276+
_ = s.client.addResourceTemplatesToServer(ctx, mcpServer)
277+
278+
internal.LogInfoWithFields("client", "MCP capability discovery completed", map[string]interface{}{
279+
"server": serverName,
280+
"userTokenRequired": requiresToken,
281+
})
282+
283+
// Start ping task if needed
284+
if s.client.needPing {
285+
go s.client.startPingTask(ctx)
286+
}
287+
288+
return nil
289+
}
290+
220291
// checkUserLimits verifies user hasn't exceeded session limits
221292
func (sm *StdioSessionManager) checkUserLimits(userEmail string) error {
222293
if userEmail == "" {

0 commit comments

Comments
 (0)