Skip to content

[duplicate-code] Duplicate Code Pattern: MCP Session Nil Validation Checks #972

@github-actions

Description

@github-actions

🔍 Duplicate Code Pattern: MCP Session Validation Checks

Part of duplicate code analysis: #970

Summary

The internal/mcp/connection.go file contains 6 identical session nil checks across different MCP method wrappers. Each method performs the exact same validation before executing its SDK call.

Duplication Details

Pattern: Repeated Session Nil Validation

  • Severity: Medium
  • Occurrences: 6 instances
  • Locations:
    • internal/mcp/connection.go:
      • Line 821-823: listTools()
      • Line 833-835: callTool()
      • Line 867-869: listResources()
      • Line 879-881: readResource()
      • Line 901-903: listPrompts()
      • Line 913-915: getPrompt()

Code Sample:

func (c *Connection) listTools() (*Response, error) {
	if c.session == nil {
		return nil, fmt.Errorf("SDK session not available for plain JSON-RPC transport")
	}
	result, err := c.session.ListTools(c.ctx, &sdk.ListToolsParams{})
	if err != nil {
		return nil, err
	}
	return marshalToResponse(result)
}

func (c *Connection) listResources() (*Response, error) {
	if c.session == nil {
		return nil, fmt.Errorf("SDK session not available for plain JSON-RPC transport")
	}
	result, err := c.session.ListResources(c.ctx, &sdk.ListResourcesParams{})
	if err != nil {
		return nil, err
	}
	return marshalToResponse(result)
}
// ... 4 more methods with identical session nil check

Impact Analysis

  • Maintainability: Medium Impact - Error message changes require updating 6 locations
  • Bug Risk: Medium - Risk of inconsistent error messages if updates are missed
  • Code Bloat: ~18 lines of duplicate validation code (6 checks × 3 lines each)
  • Consistency: Error messages could diverge over time if not carefully maintained

Refactoring Recommendations

1. Extract Session Validation Helper (Recommended)

Create a helper method to centralize the session validation:

// In connection.go
func (c *Connection) requireSession() error {
	if c.session == nil {
		return fmt.Errorf("SDK session not available for plain JSON-RPC transport")
	}
	return nil
}

// Updated methods use the helper:
func (c *Connection) listTools() (*Response, error) {
	if err := c.requireSession(); err != nil {
		return nil, err
	}
	result, err := c.session.ListTools(c.ctx, &sdk.ListToolsParams{})
	if err != nil {
		return nil, err
	}
	return marshalToResponse(result)
}

func (c *Connection) listResources() (*Response, error) {
	if err := c.requireSession(); err != nil {
		return nil, err
	}
	result, err := c.session.ListResources(c.ctx, &sdk.ListResourcesParams{})
	if err != nil {
		return nil, err
	}
	return marshalToResponse(result)
}
// ... other methods follow same pattern
  • Location: internal/mcp/connection.go (add requireSession helper method)
  • Estimated Effort: 1 hour
  • Benefits:
    • Single point of truth for session validation
    • Consistent error messages across all methods
    • Easier to enhance validation logic (e.g., add logging, metrics)
    • Reduces code by ~12 lines

2. Alternative: Method Decorator Pattern (More Complex)

For a more sophisticated approach, consider a decorator that wraps SDK calls:

type sdkCall func() (interface{}, error)

func (c *Connection) withSession(call sdkCall) (*Response, error) {
	if c.session == nil {
		return nil, fmt.Errorf("SDK session not available for plain JSON-RPC transport")
	}
	result, err := call()
	if err != nil {
		return nil, err
	}
	return marshalToResponse(result)
}

// Usage:
func (c *Connection) listTools() (*Response, error) {
	return c.withSession(func() (interface{}, error) {
		return c.session.ListTools(c.ctx, &sdk.ListToolsParams{})
	})
}
  • Estimated Effort: 2-3 hours
  • Benefits: More DRY, but adds complexity with closures

Implementation Checklist

  • Review duplication findings
  • Create requireSession() helper method in Connection struct
  • Update listTools() to use helper
  • Update callTool() to use helper
  • Update listResources() to use helper
  • Update readResource() to use helper
  • Update listPrompts() to use helper
  • Update getPrompt() to use helper
  • Run make test-all to verify no functionality broken
  • Run make lint to ensure code quality

Parent Issue

See parent analysis report: #970
Related to #970

AI generated by Duplicate Code Detector

  • expires on Feb 23, 2026, 10:32 AM UTC

Metadata

Metadata

Assignees

Type

No type
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