@@ -567,11 +567,25 @@ func (s *Server) Connect(ctx context.Context, t Transport) (*ServerSession, erro
567567 return connect (ctx , t , s )
568568}
569569
570- func (s * Server ) callInitializedHandler (ctx context.Context , ss * ServerSession , params * InitializedParams ) (Result , error ) {
571- if s .opts .KeepAlive > 0 {
572- ss .startKeepalive (s .opts .KeepAlive )
570+ func (ss * ServerSession ) initialized (ctx context.Context , params * InitializedParams ) (Result , error ) {
571+ if ss . server .opts .KeepAlive > 0 {
572+ ss .startKeepalive (ss . server .opts .KeepAlive )
573573 }
574- return callNotificationHandler (ctx , s .opts .InitializedHandler , ss , params )
574+ ss .mu .Lock ()
575+ hasParams := ss .initializeParams != nil
576+ wasInitialized := ss ._initialized
577+ if hasParams {
578+ ss ._initialized = true
579+ }
580+ ss .mu .Unlock ()
581+
582+ if ! hasParams {
583+ return nil , fmt .Errorf ("%q before %q" , notificationInitialized , methodInitialize )
584+ }
585+ if wasInitialized {
586+ return nil , fmt .Errorf ("duplicate %q received" , notificationInitialized )
587+ }
588+ return callNotificationHandler (ctx , ss .server .opts .InitializedHandler , ss , params )
575589}
576590
577591func (s * Server ) callRootsListChangedHandler (ctx context.Context , ss * ServerSession , params * RootsListChangedParams ) (Result , error ) {
@@ -603,7 +617,7 @@ type ServerSession struct {
603617 mu sync.Mutex
604618 logLevel LoggingLevel
605619 initializeParams * InitializeParams
606- initialized bool
620+ _initialized bool
607621 keepaliveCancel context.CancelFunc
608622}
609623
@@ -702,7 +716,7 @@ var serverMethodInfos = map[string]methodInfo{
702716 methodSetLevel : newMethodInfo (sessionMethod ((* ServerSession ).setLevel ), 0 ),
703717 methodSubscribe : newMethodInfo (serverMethod ((* Server ).subscribe ), 0 ),
704718 methodUnsubscribe : newMethodInfo (serverMethod ((* Server ).unsubscribe ), 0 ),
705- notificationInitialized : newMethodInfo (serverMethod ((* Server ). callInitializedHandler ), notification | missingParamsOK ),
719+ notificationInitialized : newMethodInfo (sessionMethod ((* ServerSession ). initialized ), notification | missingParamsOK ),
706720 notificationRootsListChanged : newMethodInfo (serverMethod ((* Server ).callRootsListChangedHandler ), notification | missingParamsOK ),
707721 notificationProgress : newMethodInfo (sessionMethod ((* ServerSession ).callProgressNotificationHandler ), notification ),
708722}
@@ -729,13 +743,13 @@ func (ss *ServerSession) getConn() *jsonrpc2.Connection { return ss.conn }
729743// handle invokes the method described by the given JSON RPC request.
730744func (ss * ServerSession ) handle (ctx context.Context , req * jsonrpc.Request ) (any , error ) {
731745 ss .mu .Lock ()
732- initialized := ss .initialized
746+ initialized := ss ._initialized
733747 ss .mu .Unlock ()
734748 // From the spec:
735749 // "The client SHOULD NOT send requests other than pings before the server
736750 // has responded to the initialize request."
737751 switch req .Method {
738- case "initialize" , "ping" :
752+ case methodInitialize , methodPing , notificationInitialized :
739753 default :
740754 if ! initialized {
741755 return nil , fmt .Errorf ("method %q is invalid during session initialization" , req .Method )
@@ -753,16 +767,8 @@ func (ss *ServerSession) initialize(ctx context.Context, params *InitializeParam
753767 return nil , fmt .Errorf ("%w: \" params\" must be be provided" , jsonrpc2 .ErrInvalidParams )
754768 }
755769 ss .mu .Lock ()
756- defer ss .mu .Unlock ()
757770 ss .initializeParams = params
758-
759- // Mark the connection as initialized when this method exits.
760- // TODO(#26): Technically, the server should not be considered initialized
761- // until it has *responded*, but since jsonrpc2 is currently serialized we
762- // can mark the session as initialized here. If we ever implement a
763- // concurrency model (#26), we need to guarantee that initialize is not
764- // handled concurrently to other requests.
765- ss .initialized = true
771+ ss .mu .Unlock ()
766772
767773 // If we support the client's version, reply with it. Otherwise, reply with our
768774 // latest version.
0 commit comments