@@ -8,76 +8,84 @@ import { LogId } from "../common/logger.js";
88
99type PayloadOf < K extends keyof SessionEvents > = SessionEvents [ K ] [ 0 ] ;
1010
11- type ResourceConfiguration = { name : string ; uri : string ; config : ResourceMetadata } ;
11+ export interface ResourceConfiguration {
12+ name : string ;
13+ uri : string ;
14+ config : ResourceMetadata ;
15+ }
1216
13- export function ReactiveResource < Value , RelevantEvents extends readonly ( keyof SessionEvents ) [ ] > (
14- { name, uri, config : resourceConfig } : ResourceConfiguration ,
15- {
16- initial,
17- events,
18- } : {
19- initial : Value ;
20- events : RelevantEvents ;
21- }
22- ) {
23- type SomeEvent = RelevantEvents [ number ] ;
17+ export interface ReactiveResourceOptions < Value , RelevantEvents extends readonly ( keyof SessionEvents ) [ ] > {
18+ initial : Value ;
19+ events : RelevantEvents ;
20+ }
2421
25- abstract class NewReactiveResource {
26- protected readonly session : Session ;
27- protected readonly config : UserConfig ;
28- protected current : Value ;
22+ export abstract class ReactiveResource < Value , RelevantEvents extends readonly ( keyof SessionEvents ) [ ] > {
23+ protected readonly session : Session ;
24+ protected readonly config : UserConfig ;
25+ protected current : Value ;
26+ protected readonly name : string ;
27+ protected readonly uri : string ;
28+ protected readonly resourceConfig : ResourceMetadata ;
29+ protected readonly events : RelevantEvents ;
2930
30- constructor (
31- protected readonly server : Server ,
32- protected readonly telemetry : Telemetry ,
33- current ?: Value
34- ) {
35- this . current = current ?? initial ;
36- this . session = server . session ;
37- this . config = server . userConfig ;
31+ constructor (
32+ resourceConfiguration : ResourceConfiguration ,
33+ options : ReactiveResourceOptions < Value , RelevantEvents > ,
34+ protected readonly server : Server ,
35+ protected readonly telemetry : Telemetry ,
36+ current ?: Value
37+ ) {
38+ this . name = resourceConfiguration . name ;
39+ this . uri = resourceConfiguration . uri ;
40+ this . resourceConfig = resourceConfiguration . config ;
41+ this . events = options . events ;
42+ this . current = current ?? options . initial ;
43+ this . session = server . session ;
44+ this . config = server . userConfig ;
3845
39- for ( const event of events ) {
40- this . session . on ( event , ( ...args : SessionEvents [ typeof event ] ) => {
41- this . reduceApply ( event , ( args as unknown [ ] ) [ 0 ] as PayloadOf < typeof event > ) ;
42- void this . triggerUpdate ( ) ;
43- } ) ;
44- }
45- }
46+ this . setupEventListeners ( ) ;
47+ }
4648
47- public register ( ) : void {
48- this . server . mcpServer . registerResource ( name , uri , resourceConfig , this . resourceCallback ) ;
49+ private setupEventListeners ( ) : void {
50+ for ( const event of this . events ) {
51+ this . session . on ( event , ( ...args : SessionEvents [ typeof event ] ) => {
52+ this . reduceApply ( event , ( args as unknown [ ] ) [ 0 ] as PayloadOf < typeof event > ) ;
53+ void this . triggerUpdate ( ) ;
54+ } ) ;
4955 }
56+ }
5057
51- private resourceCallback : ReadResourceCallback = ( uri ) => ( {
52- contents : [
53- {
54- text : this . toOutput ( ) ,
55- mimeType : "application/json" ,
56- uri : uri . href ,
57- } ,
58- ] ,
59- } ) ;
58+ public register ( ) : void {
59+ this . server . mcpServer . registerResource ( this . name , this . uri , this . resourceConfig , this . resourceCallback ) ;
60+ }
6061
61- private async triggerUpdate ( ) {
62- try {
63- await this . server . mcpServer . server . sendResourceUpdated ( { uri } ) ;
64- this . server . mcpServer . sendResourceListChanged ( ) ;
65- } catch ( error : unknown ) {
66- this . session . logger . warning ( {
67- id : LogId . resourceUpdateFailure ,
68- context : "resource" ,
69- message : `Could not send the latest resources to the client: ${ error as string } ` ,
70- } ) ;
71- }
72- }
62+ private resourceCallback : ReadResourceCallback = ( uri ) => ( {
63+ contents : [
64+ {
65+ text : this . toOutput ( ) ,
66+ mimeType : "application/json" ,
67+ uri : uri . href ,
68+ } ,
69+ ] ,
70+ } ) ;
7371
74- reduceApply ( eventName : SomeEvent , ...event : PayloadOf < SomeEvent > [ ] ) : void {
75- this . current = this . reduce ( eventName , ...event ) ;
72+ private async triggerUpdate ( ) : Promise < void > {
73+ try {
74+ await this . server . mcpServer . server . sendResourceUpdated ( { uri : this . uri } ) ;
75+ this . server . mcpServer . sendResourceListChanged ( ) ;
76+ } catch ( error : unknown ) {
77+ this . session . logger . warning ( {
78+ id : LogId . resourceUpdateFailure ,
79+ context : "resource" ,
80+ message : `Could not send the latest resources to the client: ${ error as string } ` ,
81+ } ) ;
7682 }
83+ }
7784
78- protected abstract reduce ( eventName : SomeEvent , ...event : PayloadOf < SomeEvent > [ ] ) : Value ;
79- abstract toOutput ( ) : string ;
85+ protected reduceApply ( eventName : RelevantEvents [ number ] , ...event : PayloadOf < RelevantEvents [ number ] > [ ] ) : void {
86+ this . current = this . reduce ( eventName , ... event ) ;
8087 }
8188
82- return NewReactiveResource ;
89+ protected abstract reduce ( eventName : RelevantEvents [ number ] , ...event : PayloadOf < RelevantEvents [ number ] > [ ] ) : Value ;
90+ public abstract toOutput ( ) : string ;
8391}
0 commit comments