@@ -3,19 +3,21 @@ package connector
33import (
44 "context"
55 "fmt"
6- "github.com/viant/jsonrpc"
76 "net/url"
87 "reflect"
98 "time"
109
10+ "github.com/viant/jsonrpc"
11+
12+ "os"
13+ "path/filepath"
14+ "strings"
15+
1116 "github.com/google/uuid"
1217 "github.com/viant/mcp-protocol/client"
1318 "github.com/viant/mcp-protocol/schema"
1419 "github.com/viant/scy"
1520 "github.com/viant/scy/cred"
16- "os"
17- "path/filepath"
18- "strings"
1921)
2022
2123// Add registers or updates a connector in the caller's namespace. If its secret
@@ -24,27 +26,36 @@ import (
2426// MCP Elicit protocol, a browser flow is initiated to collect the secret
2527// value. The method never returns the secret and therefore is safe over MCP
2628// RPC.
27- func (s * Service ) Add (ctx context.Context , connector * Connector ) error {
29+ func (s * Service ) Add (ctx context.Context , connector * Connector ) ( * AddOutput , error ) {
2830 pend , err := s .GeneratePendingSecret (ctx , connector )
2931 if err != nil {
30- return err
32+ return nil , err
3133 }
3234 pend .MCP = s .mcpClient
3335 connector .secrets = s .secrets
36+
3437 // If client can handle the Elicit protocol generate it and optionally wait.
3538 if impl , ok := s .mcpClient .(client.Operations ); ok && impl .Implements (schema .MethodElicitationCreate ) {
39+ elicitID := uuid .New ().String ()
40+ pend .ElicitID = elicitID
41+ oobURL := pend .CallbackURL
42+ if strings .Contains (oobURL , "?" ) {
43+ oobURL += "&elicitationId=" + url .QueryEscape (elicitID )
44+ } else {
45+ oobURL += "?elicitationId=" + url .QueryEscape (elicitID )
46+ }
3647 elicitResult , _ := impl .Elicit (ctx , & jsonrpc.TypedRequest [* schema.ElicitRequest ]{
3748 Request : & schema.ElicitRequest {
3849 Params : schema.ElicitRequestParams {
39- ElicitationId : uuid . New (). String () ,
50+ ElicitationId : elicitID ,
4051 Message : "Open URL to provide secrets for " + connector .Name + " connector" ,
4152 Mode : "oob" ,
42- Url : pend . CallbackURL ,
53+ Url : oobURL ,
4354 }}})
4455
4556 if elicitResult != nil {
4657 if elicitResult .Action != schema .ElicitResultActionAccept {
47- return fmt .Errorf ("user reject providing credentials %v" , err )
58+ return nil , fmt .Errorf ("user reject providing credentials %v" , err )
4859 }
4960 }
5061 // Wait for secret submission up to 5 min.
@@ -60,10 +71,17 @@ func (s *Service) Add(ctx context.Context, connector *Connector) error {
6071 pend .NS .Connectors .Put (connector .Name , connector )
6172 }
6273 case <- time .After (5 * time .Minute ):
74+ // Timed out – return pending state with callback URL
75+ return & AddOutput {Status : "ok" , State : "PENDING_SECRET" , CallbackURL : pend .CallbackURL , Connector : connector .Name }, nil
6376 case <- ctx .Done ():
77+ return nil , ctx .Err ()
6478 }
79+ // Secret submitted within wait window – connector activated
80+ return & AddOutput {Status : "ok" , Connector : connector .Name }, nil
6581 }
66- return nil
82+ // Client cannot handle Elicit – the connector remains pending waiting for
83+ // secret to be supplied out-of-band; return pending state with callback URL.
84+ return & AddOutput {Status : "ok" , State : "PENDING_SECRET" , CallbackURL : pend .CallbackURL , Connector : connector .Name }, nil
6785}
6886
6987func (s * Service ) GeneratePendingSecret (ctx context.Context , connector * Connector ) (* PendingSecret , error ) {
0 commit comments