fix(mcp): gracefully handle Method not found for resources/list (#2239)

0xarcher created

Some MCP servers advertise resources capability but don't implement
resources/list, causing the entire MCP client to fail. This change
handles JSON-RPC error code -32601 gracefully by marking resources
as unavailable instead of failing.

Fixes #2227

Change summary

internal/agent/tools/mcp/resources.go | 13 +++++++++++++
1 file changed, 13 insertions(+)

Detailed changes

internal/agent/tools/mcp/resources.go 🔗

@@ -2,11 +2,13 @@ package mcp
 
 import (
 	"context"
+	"errors"
 	"iter"
 	"log/slog"
 
 	"github.com/charmbracelet/crush/internal/config"
 	"github.com/charmbracelet/crush/internal/csync"
+	"github.com/modelcontextprotocol/go-sdk/jsonrpc"
 	"github.com/modelcontextprotocol/go-sdk/mcp"
 )
 
@@ -81,11 +83,22 @@ func getResources(ctx context.Context, c *ClientSession) ([]*Resource, error) {
 	}
 	result, err := c.ListResources(ctx, &mcp.ListResourcesParams{})
 	if err != nil {
+		// Handle "Method not found" errors from MCP servers that don't support resources/list
+		if isMethodNotFoundError(err) {
+			slog.Warn("MCP server does not support resources/list", "error", err)
+			return nil, nil
+		}
 		return nil, err
 	}
 	return result.Resources, nil
 }
 
+// isMethodNotFoundError checks if the error is a JSON-RPC "Method not found" error.
+func isMethodNotFoundError(err error) bool {
+	var rpcErr *jsonrpc.Error
+	return errors.As(err, &rpcErr) && rpcErr != nil && rpcErr.Code == jsonrpc.CodeMethodNotFound
+}
+
 func updateResources(name string, resources []*Resource) int {
 	if len(resources) == 0 {
 		allResources.Del(name)