@vurb/core 3.3.0 → 3.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +677 -677
- package/dist/cli/constants.js +59 -59
- package/dist/cli/templates/config.js +26 -26
- package/dist/cli/templates/core.js +95 -95
- package/dist/cli/templates/middleware.js +25 -25
- package/dist/cli/templates/readme.js +142 -142
- package/dist/cli/templates/testing.js +84 -84
- package/dist/cli/templates/tools.js +46 -46
- package/dist/cli/templates/vectors/database.js +69 -69
- package/dist/cli/templates/vectors/oauth.js +63 -63
- package/dist/cli/templates/vectors/openapi.js +97 -97
- package/dist/core/middleware/AuditTrail.d.ts +128 -0
- package/dist/core/middleware/AuditTrail.d.ts.map +1 -0
- package/dist/core/middleware/AuditTrail.js +94 -0
- package/dist/core/middleware/AuditTrail.js.map +1 -0
- package/dist/core/middleware/InputFirewall.d.ts +95 -0
- package/dist/core/middleware/InputFirewall.d.ts.map +1 -0
- package/dist/core/middleware/InputFirewall.js +104 -0
- package/dist/core/middleware/InputFirewall.js.map +1 -0
- package/dist/core/middleware/RateLimiter.d.ts +151 -0
- package/dist/core/middleware/RateLimiter.d.ts.map +1 -0
- package/dist/core/middleware/RateLimiter.js +121 -0
- package/dist/core/middleware/RateLimiter.js.map +1 -0
- package/dist/core/middleware/index.d.ts +6 -0
- package/dist/core/middleware/index.d.ts.map +1 -1
- package/dist/core/middleware/index.js +4 -0
- package/dist/core/middleware/index.js.map +1 -1
- package/dist/index.d.ts +28 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/dist/introspection/SemanticProbe.js +49 -49
- package/dist/observability/TelemetryEvent.d.ts +61 -1
- package/dist/observability/TelemetryEvent.d.ts.map +1 -1
- package/dist/presenter/JudgeChain.d.ts +129 -0
- package/dist/presenter/JudgeChain.d.ts.map +1 -0
- package/dist/presenter/JudgeChain.js +215 -0
- package/dist/presenter/JudgeChain.js.map +1 -0
- package/dist/presenter/PostProcessor.d.ts.map +1 -1
- package/dist/presenter/PostProcessor.js +11 -66
- package/dist/presenter/PostProcessor.js.map +1 -1
- package/dist/presenter/Presenter.d.ts +175 -37
- package/dist/presenter/Presenter.d.ts.map +1 -1
- package/dist/presenter/Presenter.js +265 -154
- package/dist/presenter/Presenter.js.map +1 -1
- package/dist/presenter/PresenterPipeline.d.ts +147 -0
- package/dist/presenter/PresenterPipeline.d.ts.map +1 -0
- package/dist/presenter/PresenterPipeline.js +271 -0
- package/dist/presenter/PresenterPipeline.js.map +1 -0
- package/dist/presenter/PromptFirewall.d.ts +160 -0
- package/dist/presenter/PromptFirewall.d.ts.map +1 -0
- package/dist/presenter/PromptFirewall.js +228 -0
- package/dist/presenter/PromptFirewall.js.map +1 -0
- package/dist/presenter/ResponseBuilder.d.ts +13 -0
- package/dist/presenter/ResponseBuilder.d.ts.map +1 -1
- package/dist/presenter/ResponseBuilder.js +28 -1
- package/dist/presenter/ResponseBuilder.js.map +1 -1
- package/dist/presenter/TelemetryCollector.d.ts +48 -0
- package/dist/presenter/TelemetryCollector.d.ts.map +1 -0
- package/dist/presenter/TelemetryCollector.js +93 -0
- package/dist/presenter/TelemetryCollector.js.map +1 -0
- package/dist/presenter/definePresenter.d.ts +112 -0
- package/dist/presenter/definePresenter.d.ts.map +1 -1
- package/dist/presenter/definePresenter.js +110 -0
- package/dist/presenter/definePresenter.js.map +1 -1
- package/dist/presenter/index.d.ts +6 -2
- package/dist/presenter/index.d.ts.map +1 -1
- package/dist/presenter/index.js +5 -1
- package/dist/presenter/index.js.map +1 -1
- package/dist/presenter/ui.d.ts +31 -8
- package/dist/presenter/ui.d.ts.map +1 -1
- package/dist/presenter/ui.js +16 -16
- package/dist/presenter/ui.js.map +1 -1
- package/dist/prompt/FluentPromptBuilder.d.ts.map +1 -1
- package/dist/resource/ResourceBuilder.d.ts +129 -0
- package/dist/resource/ResourceBuilder.d.ts.map +1 -0
- package/dist/resource/ResourceBuilder.js +93 -0
- package/dist/resource/ResourceBuilder.js.map +1 -0
- package/dist/resource/ResourceRegistry.d.ts +147 -0
- package/dist/resource/ResourceRegistry.d.ts.map +1 -0
- package/dist/resource/ResourceRegistry.js +234 -0
- package/dist/resource/ResourceRegistry.js.map +1 -0
- package/dist/resource/SubscriptionManager.d.ts +67 -0
- package/dist/resource/SubscriptionManager.d.ts.map +1 -0
- package/dist/resource/SubscriptionManager.js +86 -0
- package/dist/resource/SubscriptionManager.js.map +1 -0
- package/dist/resource/index.d.ts +13 -0
- package/dist/resource/index.d.ts.map +1 -0
- package/dist/resource/index.js +13 -0
- package/dist/resource/index.js.map +1 -0
- package/dist/server/ServerAttachment.d.ts +26 -0
- package/dist/server/ServerAttachment.d.ts.map +1 -1
- package/dist/server/ServerAttachment.js +70 -2
- package/dist/server/ServerAttachment.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResourceBuilder.js","sourceRoot":"","sources":["../../src/resource/ResourceBuilder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AA2FH,4DAA4D;AAE5D,MAAM,mBAAmB;IACJ,KAAK,CAAS;IACd,IAAI,CAAS;IACb,YAAY,CAAqB;IACjC,SAAS,CAAqB;IAC9B,KAAK,CAAW;IAChB,aAAa,CAAU;IACvB,YAAY,CAAgC;IAC5C,QAAQ,CAA4B;IAErD,YAAY,IAAY,EAAE,MAAgC;QACtD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,QAAQ,IAAI,kBAAkB,CAAC;QACvD,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QAC/B,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,YAAY,IAAI,KAAK,CAAC;QAClD,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC;IACnC,CAAC;IAED,OAAO,KAAa,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACxC,MAAM,KAAa,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACtC,OAAO,KAAe,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1C,cAAc,KAAc,OAAO,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;IAExD,uBAAuB;QACnB,MAAM,GAAG,GAAmB;YACxB,GAAG,EAAE,IAAI,CAAC,IAAI;YACd,IAAI,EAAE,IAAI,CAAC,KAAK;YAChB,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChE,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvD,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnE,CAAC;QACF,OAAO,GAAG,CAAC;IACf,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAW,EAAE,GAAa;QACjC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACnC,CAAC;CACJ;AAED,4DAA4D;AAE5D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,cAAc,CAC1B,IAAY,EACZ,MAAgC;IAEhC,OAAO,IAAI,mBAAmB,CAAW,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ResourceRegistry — Centralized Resource Registration & Routing
|
|
3
|
+
*
|
|
4
|
+
* The single place where all resource builders are registered and where
|
|
5
|
+
* incoming `resources/list`, `resources/read`, `resources/subscribe`,
|
|
6
|
+
* and `resources/unsubscribe` requests are routed.
|
|
7
|
+
*
|
|
8
|
+
* Mirrors the design of {@link PromptRegistry} with resource-specific features:
|
|
9
|
+
* - O(1) routing via Map lookup
|
|
10
|
+
* - URI template matching for dynamic resources
|
|
11
|
+
* - Subscription tracking via {@link SubscriptionManager}
|
|
12
|
+
* - Lifecycle sync via `notifyChanged()` (→ `notifications/resources/list_changed`)
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { ResourceRegistry, defineResource } from '@vurb/core';
|
|
17
|
+
*
|
|
18
|
+
* const resourceRegistry = new ResourceRegistry<AppContext>();
|
|
19
|
+
* resourceRegistry.register(stockPrice);
|
|
20
|
+
* resourceRegistry.register(deployStatus);
|
|
21
|
+
*
|
|
22
|
+
* registry.attachToServer(server, {
|
|
23
|
+
* contextFactory: createContext,
|
|
24
|
+
* resources: resourceRegistry,
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @see {@link defineResource} for creating resource builders
|
|
29
|
+
* @see {@link SubscriptionManager} for push notification tracking
|
|
30
|
+
*
|
|
31
|
+
* @module
|
|
32
|
+
*/
|
|
33
|
+
import { type ResourceBuilder, type McpResourceDef } from './ResourceBuilder.js';
|
|
34
|
+
import { SubscriptionManager, type ResourceNotificationSink } from './SubscriptionManager.js';
|
|
35
|
+
/** Callback for sending `notifications/resources/list_changed`. */
|
|
36
|
+
export type ResourceListChangedSink = () => void;
|
|
37
|
+
export declare class ResourceRegistry<TContext = void> {
|
|
38
|
+
private readonly _builders;
|
|
39
|
+
private readonly _subscriptions;
|
|
40
|
+
private _listChangedSink?;
|
|
41
|
+
private _notifyDebounceTimer;
|
|
42
|
+
/**
|
|
43
|
+
* Register a single resource builder.
|
|
44
|
+
*
|
|
45
|
+
* @param builder - A resource builder (from `defineResource()`)
|
|
46
|
+
* @throws If a resource with the same name is already registered
|
|
47
|
+
*/
|
|
48
|
+
register(builder: ResourceBuilder<TContext>): void;
|
|
49
|
+
/**
|
|
50
|
+
* Register multiple resource builders at once.
|
|
51
|
+
*/
|
|
52
|
+
registerAll(...builders: ResourceBuilder<TContext>[]): void;
|
|
53
|
+
/**
|
|
54
|
+
* Get all registered MCP Resource definitions for `resources/list`.
|
|
55
|
+
*
|
|
56
|
+
* Returns compiled resource metadata including URIs, descriptions,
|
|
57
|
+
* MIME types, and annotations.
|
|
58
|
+
*/
|
|
59
|
+
listResources(): McpResourceDef[];
|
|
60
|
+
/**
|
|
61
|
+
* Read a resource by URI for `resources/read`.
|
|
62
|
+
*
|
|
63
|
+
* Matches the requested URI against registered resource URI templates.
|
|
64
|
+
* Returns the resource content or throws if no matching resource is found.
|
|
65
|
+
*
|
|
66
|
+
* @param uri - The URI requested by the client
|
|
67
|
+
* @param ctx - Application context (from contextFactory)
|
|
68
|
+
* @returns MCP-compatible resource read result
|
|
69
|
+
*/
|
|
70
|
+
readResource(uri: string, ctx: TContext): Promise<{
|
|
71
|
+
contents: Array<{
|
|
72
|
+
uri: string;
|
|
73
|
+
mimeType?: string;
|
|
74
|
+
text?: string;
|
|
75
|
+
blob?: string;
|
|
76
|
+
}>;
|
|
77
|
+
}>;
|
|
78
|
+
/**
|
|
79
|
+
* Subscribe to push notifications for a resource URI.
|
|
80
|
+
*
|
|
81
|
+
* Only succeeds if the resource is marked as `subscribable`.
|
|
82
|
+
*
|
|
83
|
+
* @param uri - The resource URI to subscribe to
|
|
84
|
+
* @returns `true` if subscription was accepted, `false` if resource is not subscribable
|
|
85
|
+
*/
|
|
86
|
+
subscribe(uri: string): boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Unsubscribe from push notifications for a resource URI.
|
|
89
|
+
*
|
|
90
|
+
* @param uri - The resource URI to unsubscribe from
|
|
91
|
+
*/
|
|
92
|
+
unsubscribe(uri: string): void;
|
|
93
|
+
/**
|
|
94
|
+
* Emit a resource update notification to subscribed clients.
|
|
95
|
+
*
|
|
96
|
+
* Only emits if the URI is subscribed. Uses the subscription manager's
|
|
97
|
+
* notification sink (wired by ServerAttachment).
|
|
98
|
+
*
|
|
99
|
+
* @param uri - The URI of the resource that changed
|
|
100
|
+
*/
|
|
101
|
+
notifyUpdated(uri: string): Promise<void>;
|
|
102
|
+
/**
|
|
103
|
+
* Set the notification sink for `notifications/resources/updated`.
|
|
104
|
+
*
|
|
105
|
+
* Called by ServerAttachment when wiring the registry to the MCP server.
|
|
106
|
+
*
|
|
107
|
+
* @internal
|
|
108
|
+
*/
|
|
109
|
+
setNotificationSink(sink: ResourceNotificationSink): void;
|
|
110
|
+
/**
|
|
111
|
+
* Set the sink for `notifications/resources/list_changed`.
|
|
112
|
+
*
|
|
113
|
+
* @internal — Called by ServerAttachment
|
|
114
|
+
*/
|
|
115
|
+
setListChangedSink(sink: ResourceListChangedSink): void;
|
|
116
|
+
/**
|
|
117
|
+
* Notify all connected clients that the resource catalog has changed.
|
|
118
|
+
*
|
|
119
|
+
* Sends `notifications/resources/list_changed`. Debounced: multiple
|
|
120
|
+
* calls within 100ms are coalesced into one notification.
|
|
121
|
+
*/
|
|
122
|
+
notifyChanged(): void;
|
|
123
|
+
/** Check if a resource with the given name is registered. */
|
|
124
|
+
has(name: string): boolean;
|
|
125
|
+
/** Number of registered resources. */
|
|
126
|
+
get size(): number;
|
|
127
|
+
/** Whether any registered resource supports subscriptions. */
|
|
128
|
+
get hasSubscribableResources(): boolean;
|
|
129
|
+
/** Get the subscription manager (for testing and advanced wiring). */
|
|
130
|
+
get subscriptions(): SubscriptionManager;
|
|
131
|
+
/** Remove all registered resources and cancel pending timers. */
|
|
132
|
+
clear(): void;
|
|
133
|
+
/**
|
|
134
|
+
* Find a builder by exact URI match or template match.
|
|
135
|
+
*
|
|
136
|
+
* First tries exact match (O(1) via Map lookup on URI).
|
|
137
|
+
* Falls back to template matching (O(n) scan, but n is tiny).
|
|
138
|
+
*/
|
|
139
|
+
private _findByUri;
|
|
140
|
+
/**
|
|
141
|
+
* Check if a URI matches a template pattern.
|
|
142
|
+
*
|
|
143
|
+
* Template: `stock://prices/{symbol}` matches `stock://prices/AAPL`
|
|
144
|
+
*/
|
|
145
|
+
private _matchesTemplate;
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=ResourceRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResourceRegistry.d.ts","sourceRoot":"","sources":["../../src/resource/ResourceRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAwB,MAAM,sBAAsB,CAAC;AACvG,OAAO,EAAE,mBAAmB,EAAE,KAAK,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAI9F,mEAAmE;AACnE,MAAM,MAAM,uBAAuB,GAAG,MAAM,IAAI,CAAC;AAIjD,qBAAa,gBAAgB,CAAC,QAAQ,GAAG,IAAI;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgD;IAC1E,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,OAAO,CAAC,gBAAgB,CAAC,CAA0B;IACnD,OAAO,CAAC,oBAAoB,CAA4C;IAIxE;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC,QAAQ,CAAC,GAAG,IAAI;IAQlD;;OAEG;IACH,WAAW,CAAC,GAAG,QAAQ,EAAE,eAAe,CAAC,QAAQ,CAAC,EAAE,GAAG,IAAI;IAQ3D;;;;;OAKG;IACH,aAAa,IAAI,cAAc,EAAE;IAQjC;;;;;;;;;OASG;IACG,YAAY,CACd,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,QAAQ,GACd,OAAO,CAAC;QAAE,QAAQ,EAAE,KAAK,CAAC;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC;IAqBjG;;;;;;;OAOG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAS/B;;;;OAIG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI9B;;;;;;;OAOG;IACG,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C;;;;;;OAMG;IACH,mBAAmB,CAAC,IAAI,EAAE,wBAAwB,GAAG,IAAI;IAMzD;;;;OAIG;IACH,kBAAkB,CAAC,IAAI,EAAE,uBAAuB,GAAG,IAAI;IAIvD;;;;;OAKG;IACH,aAAa,IAAI,IAAI;IAgBrB,6DAA6D;IAC7D,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAE1B,sCAAsC;IACtC,IAAI,IAAI,IAAI,MAAM,CAAgC;IAElD,8DAA8D;IAC9D,IAAI,wBAAwB,IAAI,OAAO,CAKtC;IAED,sEAAsE;IACtE,IAAI,aAAa,IAAI,mBAAmB,CAEvC;IAED,iEAAiE;IACjE,KAAK,IAAI,IAAI;IAWb;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAclB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;CAM3B"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ResourceRegistry — Centralized Resource Registration & Routing
|
|
3
|
+
*
|
|
4
|
+
* The single place where all resource builders are registered and where
|
|
5
|
+
* incoming `resources/list`, `resources/read`, `resources/subscribe`,
|
|
6
|
+
* and `resources/unsubscribe` requests are routed.
|
|
7
|
+
*
|
|
8
|
+
* Mirrors the design of {@link PromptRegistry} with resource-specific features:
|
|
9
|
+
* - O(1) routing via Map lookup
|
|
10
|
+
* - URI template matching for dynamic resources
|
|
11
|
+
* - Subscription tracking via {@link SubscriptionManager}
|
|
12
|
+
* - Lifecycle sync via `notifyChanged()` (→ `notifications/resources/list_changed`)
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { ResourceRegistry, defineResource } from '@vurb/core';
|
|
17
|
+
*
|
|
18
|
+
* const resourceRegistry = new ResourceRegistry<AppContext>();
|
|
19
|
+
* resourceRegistry.register(stockPrice);
|
|
20
|
+
* resourceRegistry.register(deployStatus);
|
|
21
|
+
*
|
|
22
|
+
* registry.attachToServer(server, {
|
|
23
|
+
* contextFactory: createContext,
|
|
24
|
+
* resources: resourceRegistry,
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @see {@link defineResource} for creating resource builders
|
|
29
|
+
* @see {@link SubscriptionManager} for push notification tracking
|
|
30
|
+
*
|
|
31
|
+
* @module
|
|
32
|
+
*/
|
|
33
|
+
import {} from './ResourceBuilder.js';
|
|
34
|
+
import { SubscriptionManager } from './SubscriptionManager.js';
|
|
35
|
+
// ── Registry ─────────────────────────────────────────────
|
|
36
|
+
export class ResourceRegistry {
|
|
37
|
+
_builders = new Map();
|
|
38
|
+
_subscriptions = new SubscriptionManager();
|
|
39
|
+
_listChangedSink;
|
|
40
|
+
_notifyDebounceTimer;
|
|
41
|
+
// ── Registration ─────────────────────────────────────
|
|
42
|
+
/**
|
|
43
|
+
* Register a single resource builder.
|
|
44
|
+
*
|
|
45
|
+
* @param builder - A resource builder (from `defineResource()`)
|
|
46
|
+
* @throws If a resource with the same name is already registered
|
|
47
|
+
*/
|
|
48
|
+
register(builder) {
|
|
49
|
+
const name = builder.getName();
|
|
50
|
+
if (this._builders.has(name)) {
|
|
51
|
+
throw new Error(`Resource "${name}" is already registered.`);
|
|
52
|
+
}
|
|
53
|
+
this._builders.set(name, builder);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Register multiple resource builders at once.
|
|
57
|
+
*/
|
|
58
|
+
registerAll(...builders) {
|
|
59
|
+
for (const builder of builders) {
|
|
60
|
+
this.register(builder);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// ── List & Read (MCP protocol) ───────────────────────
|
|
64
|
+
/**
|
|
65
|
+
* Get all registered MCP Resource definitions for `resources/list`.
|
|
66
|
+
*
|
|
67
|
+
* Returns compiled resource metadata including URIs, descriptions,
|
|
68
|
+
* MIME types, and annotations.
|
|
69
|
+
*/
|
|
70
|
+
listResources() {
|
|
71
|
+
const resources = [];
|
|
72
|
+
for (const builder of this._builders.values()) {
|
|
73
|
+
resources.push(builder.buildResourceDefinition());
|
|
74
|
+
}
|
|
75
|
+
return resources;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Read a resource by URI for `resources/read`.
|
|
79
|
+
*
|
|
80
|
+
* Matches the requested URI against registered resource URI templates.
|
|
81
|
+
* Returns the resource content or throws if no matching resource is found.
|
|
82
|
+
*
|
|
83
|
+
* @param uri - The URI requested by the client
|
|
84
|
+
* @param ctx - Application context (from contextFactory)
|
|
85
|
+
* @returns MCP-compatible resource read result
|
|
86
|
+
*/
|
|
87
|
+
async readResource(uri, ctx) {
|
|
88
|
+
const builder = this._findByUri(uri);
|
|
89
|
+
if (!builder) {
|
|
90
|
+
return { contents: [] };
|
|
91
|
+
}
|
|
92
|
+
const content = await builder.read(uri, ctx);
|
|
93
|
+
const def = builder.buildResourceDefinition();
|
|
94
|
+
return {
|
|
95
|
+
contents: [{
|
|
96
|
+
uri,
|
|
97
|
+
...(def.mimeType ? { mimeType: def.mimeType } : {}),
|
|
98
|
+
...(content.text !== undefined ? { text: content.text } : {}),
|
|
99
|
+
...(content.blob !== undefined ? { blob: content.blob } : {}),
|
|
100
|
+
}],
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// ── Subscription Management ──────────────────────────
|
|
104
|
+
/**
|
|
105
|
+
* Subscribe to push notifications for a resource URI.
|
|
106
|
+
*
|
|
107
|
+
* Only succeeds if the resource is marked as `subscribable`.
|
|
108
|
+
*
|
|
109
|
+
* @param uri - The resource URI to subscribe to
|
|
110
|
+
* @returns `true` if subscription was accepted, `false` if resource is not subscribable
|
|
111
|
+
*/
|
|
112
|
+
subscribe(uri) {
|
|
113
|
+
const builder = this._findByUri(uri);
|
|
114
|
+
if (!builder || !builder.isSubscribable()) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
this._subscriptions.subscribe(uri);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Unsubscribe from push notifications for a resource URI.
|
|
122
|
+
*
|
|
123
|
+
* @param uri - The resource URI to unsubscribe from
|
|
124
|
+
*/
|
|
125
|
+
unsubscribe(uri) {
|
|
126
|
+
this._subscriptions.unsubscribe(uri);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Emit a resource update notification to subscribed clients.
|
|
130
|
+
*
|
|
131
|
+
* Only emits if the URI is subscribed. Uses the subscription manager's
|
|
132
|
+
* notification sink (wired by ServerAttachment).
|
|
133
|
+
*
|
|
134
|
+
* @param uri - The URI of the resource that changed
|
|
135
|
+
*/
|
|
136
|
+
async notifyUpdated(uri) {
|
|
137
|
+
await this._subscriptions.notify(uri);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Set the notification sink for `notifications/resources/updated`.
|
|
141
|
+
*
|
|
142
|
+
* Called by ServerAttachment when wiring the registry to the MCP server.
|
|
143
|
+
*
|
|
144
|
+
* @internal
|
|
145
|
+
*/
|
|
146
|
+
setNotificationSink(sink) {
|
|
147
|
+
this._subscriptions.setSink(sink);
|
|
148
|
+
}
|
|
149
|
+
// ── Lifecycle Sync ───────────────────────────────────
|
|
150
|
+
/**
|
|
151
|
+
* Set the sink for `notifications/resources/list_changed`.
|
|
152
|
+
*
|
|
153
|
+
* @internal — Called by ServerAttachment
|
|
154
|
+
*/
|
|
155
|
+
setListChangedSink(sink) {
|
|
156
|
+
this._listChangedSink = sink;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Notify all connected clients that the resource catalog has changed.
|
|
160
|
+
*
|
|
161
|
+
* Sends `notifications/resources/list_changed`. Debounced: multiple
|
|
162
|
+
* calls within 100ms are coalesced into one notification.
|
|
163
|
+
*/
|
|
164
|
+
notifyChanged() {
|
|
165
|
+
if (!this._listChangedSink)
|
|
166
|
+
return;
|
|
167
|
+
if (this._notifyDebounceTimer !== undefined) {
|
|
168
|
+
clearTimeout(this._notifyDebounceTimer);
|
|
169
|
+
}
|
|
170
|
+
const sink = this._listChangedSink;
|
|
171
|
+
this._notifyDebounceTimer = setTimeout(() => {
|
|
172
|
+
sink();
|
|
173
|
+
this._notifyDebounceTimer = undefined;
|
|
174
|
+
}, 100);
|
|
175
|
+
}
|
|
176
|
+
// ── Query ────────────────────────────────────────────
|
|
177
|
+
/** Check if a resource with the given name is registered. */
|
|
178
|
+
has(name) { return this._builders.has(name); }
|
|
179
|
+
/** Number of registered resources. */
|
|
180
|
+
get size() { return this._builders.size; }
|
|
181
|
+
/** Whether any registered resource supports subscriptions. */
|
|
182
|
+
get hasSubscribableResources() {
|
|
183
|
+
for (const builder of this._builders.values()) {
|
|
184
|
+
if (builder.isSubscribable())
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
/** Get the subscription manager (for testing and advanced wiring). */
|
|
190
|
+
get subscriptions() {
|
|
191
|
+
return this._subscriptions;
|
|
192
|
+
}
|
|
193
|
+
/** Remove all registered resources and cancel pending timers. */
|
|
194
|
+
clear() {
|
|
195
|
+
this._builders.clear();
|
|
196
|
+
this._subscriptions.clear();
|
|
197
|
+
if (this._notifyDebounceTimer !== undefined) {
|
|
198
|
+
clearTimeout(this._notifyDebounceTimer);
|
|
199
|
+
this._notifyDebounceTimer = undefined;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// ── Private ──────────────────────────────────────────
|
|
203
|
+
/**
|
|
204
|
+
* Find a builder by exact URI match or template match.
|
|
205
|
+
*
|
|
206
|
+
* First tries exact match (O(1) via Map lookup on URI).
|
|
207
|
+
* Falls back to template matching (O(n) scan, but n is tiny).
|
|
208
|
+
*/
|
|
209
|
+
_findByUri(uri) {
|
|
210
|
+
// Fast path: exact URI match
|
|
211
|
+
for (const builder of this._builders.values()) {
|
|
212
|
+
if (builder.getUri() === uri)
|
|
213
|
+
return builder;
|
|
214
|
+
}
|
|
215
|
+
// Slow path: URI template matching
|
|
216
|
+
for (const builder of this._builders.values()) {
|
|
217
|
+
if (this._matchesTemplate(builder.getUri(), uri))
|
|
218
|
+
return builder;
|
|
219
|
+
}
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Check if a URI matches a template pattern.
|
|
224
|
+
*
|
|
225
|
+
* Template: `stock://prices/{symbol}` matches `stock://prices/AAPL`
|
|
226
|
+
*/
|
|
227
|
+
_matchesTemplate(template, uri) {
|
|
228
|
+
// Convert template to regex: replace {placeholder} with (.+)
|
|
229
|
+
const regexStr = template.replace(/\{[^}]+\}/g, '([^/]+)');
|
|
230
|
+
const regex = new RegExp(`^${regexStr}$`);
|
|
231
|
+
return regex.test(uri);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=ResourceRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResourceRegistry.js","sourceRoot":"","sources":["../../src/resource/ResourceRegistry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SubscriptionManager — Push Notification Tracking
|
|
3
|
+
*
|
|
4
|
+
* Tracks which resource URIs are subscribed and routes
|
|
5
|
+
* `notifications/resources/updated` to the MCP transport layer.
|
|
6
|
+
*
|
|
7
|
+
* Designed to be embedded within {@link ResourceRegistry}.
|
|
8
|
+
* Supports both in-process usage (framework) and external
|
|
9
|
+
* delegation (runtime Redis bridge).
|
|
10
|
+
*
|
|
11
|
+
* @see {@link ResourceRegistry} for the public API
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Notification sink for `notifications/resources/updated`.
|
|
17
|
+
*
|
|
18
|
+
* Set by ServerAttachment to bridge into the MCP transport.
|
|
19
|
+
*/
|
|
20
|
+
export type ResourceNotificationSink = (uri: string) => void | Promise<void>;
|
|
21
|
+
export declare class SubscriptionManager {
|
|
22
|
+
private readonly _subscribed;
|
|
23
|
+
private _sink?;
|
|
24
|
+
/**
|
|
25
|
+
* Subscribe to push notifications for a resource URI.
|
|
26
|
+
*
|
|
27
|
+
* @param uri - The resource URI to subscribe to
|
|
28
|
+
*/
|
|
29
|
+
subscribe(uri: string): void;
|
|
30
|
+
/**
|
|
31
|
+
* Unsubscribe from push notifications for a resource URI.
|
|
32
|
+
*
|
|
33
|
+
* @param uri - The resource URI to unsubscribe from
|
|
34
|
+
*/
|
|
35
|
+
unsubscribe(uri: string): void;
|
|
36
|
+
/**
|
|
37
|
+
* Check if a URI is currently subscribed.
|
|
38
|
+
*
|
|
39
|
+
* @param uri - The URI to check
|
|
40
|
+
*/
|
|
41
|
+
isSubscribed(uri: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Get all currently subscribed URIs.
|
|
44
|
+
*/
|
|
45
|
+
getSubscriptions(): ReadonlySet<string>;
|
|
46
|
+
/**
|
|
47
|
+
* Emit a `notifications/resources/updated` for a URI.
|
|
48
|
+
*
|
|
49
|
+
* Only emits if the URI is subscribed AND a sink is configured.
|
|
50
|
+
* Errors in the sink are swallowed (best-effort delivery).
|
|
51
|
+
*
|
|
52
|
+
* @param uri - The URI of the resource that changed
|
|
53
|
+
*/
|
|
54
|
+
notify(uri: string): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Set the notification sink.
|
|
57
|
+
*
|
|
58
|
+
* @param sink - Callback that emits the MCP notification
|
|
59
|
+
* @internal
|
|
60
|
+
*/
|
|
61
|
+
setSink(sink: ResourceNotificationSink): void;
|
|
62
|
+
/** Number of active subscriptions. */
|
|
63
|
+
get size(): number;
|
|
64
|
+
/** Remove all subscriptions. */
|
|
65
|
+
clear(): void;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=SubscriptionManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SubscriptionManager.d.ts","sourceRoot":"","sources":["../../src/resource/SubscriptionManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAI7E,qBAAa,mBAAmB;IAC5B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,KAAK,CAAC,CAA2B;IAEzC;;;;OAIG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI5B;;;;OAIG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI9B;;;;OAIG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIlC;;OAEG;IACH,gBAAgB,IAAI,WAAW,CAAC,MAAM,CAAC;IAIvC;;;;;;;OAOG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAaxC;;;;;OAKG;IACH,OAAO,CAAC,IAAI,EAAE,wBAAwB,GAAG,IAAI;IAI7C,sCAAsC;IACtC,IAAI,IAAI,IAAI,MAAM,CAAkC;IAEpD,gCAAgC;IAChC,KAAK,IAAI,IAAI;CAGhB"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SubscriptionManager — Push Notification Tracking
|
|
3
|
+
*
|
|
4
|
+
* Tracks which resource URIs are subscribed and routes
|
|
5
|
+
* `notifications/resources/updated` to the MCP transport layer.
|
|
6
|
+
*
|
|
7
|
+
* Designed to be embedded within {@link ResourceRegistry}.
|
|
8
|
+
* Supports both in-process usage (framework) and external
|
|
9
|
+
* delegation (runtime Redis bridge).
|
|
10
|
+
*
|
|
11
|
+
* @see {@link ResourceRegistry} for the public API
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
// ── Manager ──────────────────────────────────────────────
|
|
16
|
+
export class SubscriptionManager {
|
|
17
|
+
_subscribed = new Set();
|
|
18
|
+
_sink;
|
|
19
|
+
/**
|
|
20
|
+
* Subscribe to push notifications for a resource URI.
|
|
21
|
+
*
|
|
22
|
+
* @param uri - The resource URI to subscribe to
|
|
23
|
+
*/
|
|
24
|
+
subscribe(uri) {
|
|
25
|
+
this._subscribed.add(uri);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Unsubscribe from push notifications for a resource URI.
|
|
29
|
+
*
|
|
30
|
+
* @param uri - The resource URI to unsubscribe from
|
|
31
|
+
*/
|
|
32
|
+
unsubscribe(uri) {
|
|
33
|
+
this._subscribed.delete(uri);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Check if a URI is currently subscribed.
|
|
37
|
+
*
|
|
38
|
+
* @param uri - The URI to check
|
|
39
|
+
*/
|
|
40
|
+
isSubscribed(uri) {
|
|
41
|
+
return this._subscribed.has(uri);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get all currently subscribed URIs.
|
|
45
|
+
*/
|
|
46
|
+
getSubscriptions() {
|
|
47
|
+
return this._subscribed;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Emit a `notifications/resources/updated` for a URI.
|
|
51
|
+
*
|
|
52
|
+
* Only emits if the URI is subscribed AND a sink is configured.
|
|
53
|
+
* Errors in the sink are swallowed (best-effort delivery).
|
|
54
|
+
*
|
|
55
|
+
* @param uri - The URI of the resource that changed
|
|
56
|
+
*/
|
|
57
|
+
async notify(uri) {
|
|
58
|
+
if (!this._sink || !this._subscribed.has(uri))
|
|
59
|
+
return;
|
|
60
|
+
try {
|
|
61
|
+
const result = this._sink(uri);
|
|
62
|
+
if (result instanceof Promise) {
|
|
63
|
+
await result;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
/* best-effort — sink must not break the pipeline */
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Set the notification sink.
|
|
72
|
+
*
|
|
73
|
+
* @param sink - Callback that emits the MCP notification
|
|
74
|
+
* @internal
|
|
75
|
+
*/
|
|
76
|
+
setSink(sink) {
|
|
77
|
+
this._sink = sink;
|
|
78
|
+
}
|
|
79
|
+
/** Number of active subscriptions. */
|
|
80
|
+
get size() { return this._subscribed.size; }
|
|
81
|
+
/** Remove all subscriptions. */
|
|
82
|
+
clear() {
|
|
83
|
+
this._subscribed.clear();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=SubscriptionManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SubscriptionManager.js","sourceRoot":"","sources":["../../src/resource/SubscriptionManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAWH,4DAA4D;AAE5D,MAAM,OAAO,mBAAmB;IACX,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACzC,KAAK,CAA4B;IAEzC;;;;OAIG;IACH,SAAS,CAAC,GAAW;QACjB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,GAAW;QACnB,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACH,YAAY,CAAC,GAAW;QACpB,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,gBAAgB;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC5B,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,MAAM,CAAC,GAAW;QACpB,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO;QAEtD,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;gBAC5B,MAAM,MAAM,CAAC;YACjB,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACL,oDAAoD;QACxD,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACH,OAAO,CAAC,IAA8B;QAClC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,sCAAsC;IACtC,IAAI,IAAI,KAAa,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IAEpD,gCAAgC;IAChC,KAAK;QACD,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;CACJ"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource Module — Barrel Export
|
|
3
|
+
*
|
|
4
|
+
* Public API for MCP Resource Subscriptions.
|
|
5
|
+
* All exports are re-exported from bounded context modules.
|
|
6
|
+
*/
|
|
7
|
+
export { defineResource } from './ResourceBuilder.js';
|
|
8
|
+
export type { ResourceBuilder, ResourceConfig, ResourceContent, ResourceHandler, McpResourceDef, } from './ResourceBuilder.js';
|
|
9
|
+
export { ResourceRegistry } from './ResourceRegistry.js';
|
|
10
|
+
export type { ResourceListChangedSink } from './ResourceRegistry.js';
|
|
11
|
+
export { SubscriptionManager } from './SubscriptionManager.js';
|
|
12
|
+
export type { ResourceNotificationSink } from './SubscriptionManager.js';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resource/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EACR,eAAe,EACf,cAAc,EACd,eAAe,EACf,eAAe,EACf,cAAc,GACjB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,YAAY,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAGrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource Module — Barrel Export
|
|
3
|
+
*
|
|
4
|
+
* Public API for MCP Resource Subscriptions.
|
|
5
|
+
* All exports are re-exported from bounded context modules.
|
|
6
|
+
*/
|
|
7
|
+
// ── Builder ──────────────────────────────────────────────
|
|
8
|
+
export { defineResource } from './ResourceBuilder.js';
|
|
9
|
+
// ── Registry ─────────────────────────────────────────────
|
|
10
|
+
export { ResourceRegistry } from './ResourceRegistry.js';
|
|
11
|
+
// ── Subscription ─────────────────────────────────────────
|
|
12
|
+
export { SubscriptionManager } from './SubscriptionManager.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resource/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,4DAA4D;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAStD,4DAA4D;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,4DAA4D;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -9,6 +9,7 @@ import { type IntrospectionConfig } from '../introspection/types.js';
|
|
|
9
9
|
import { type ZeroTrustConfig } from '../introspection/CryptoAttestation.js';
|
|
10
10
|
import { type SelfHealingConfig } from '../introspection/ContractAwareSelfHealing.js';
|
|
11
11
|
import { type ToolExposition } from '../exposition/types.js';
|
|
12
|
+
import { type ResourceRegistry } from '../resource/ResourceRegistry.js';
|
|
12
13
|
import { type PromptRegistry } from '../prompt/PromptRegistry.js';
|
|
13
14
|
import { StateMachineGate, type FsmStateStore } from '../fsm/StateMachineGate.js';
|
|
14
15
|
import type { TelemetrySink } from '../observability/TelemetryEvent.js';
|
|
@@ -305,6 +306,31 @@ export interface AttachOptions<TContext> {
|
|
|
305
306
|
* ```
|
|
306
307
|
*/
|
|
307
308
|
fsmStore?: FsmStateStore;
|
|
309
|
+
/**
|
|
310
|
+
* Resource registry for live data feeds with push subscriptions.
|
|
311
|
+
*
|
|
312
|
+
* When provided, the framework registers `resources/list`, `resources/read`,
|
|
313
|
+
* `resources/subscribe`, and `resources/unsubscribe` handlers on the MCP
|
|
314
|
+
* server, enabling AI agents to subscribe to real-time data updates.
|
|
315
|
+
*
|
|
316
|
+
* Zero overhead when omitted — no resource code runs.
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* ```typescript
|
|
320
|
+
* const resourceRegistry = new ResourceRegistry<AppContext>();
|
|
321
|
+
* resourceRegistry.register(stockPrice);
|
|
322
|
+
* resourceRegistry.register(deployStatus);
|
|
323
|
+
*
|
|
324
|
+
* registry.attachToServer(server, {
|
|
325
|
+
* contextFactory: createContext,
|
|
326
|
+
* resources: resourceRegistry,
|
|
327
|
+
* });
|
|
328
|
+
* ```
|
|
329
|
+
*
|
|
330
|
+
* @see {@link ResourceRegistry} for resource registration
|
|
331
|
+
* @see {@link defineResource} for creating resources
|
|
332
|
+
*/
|
|
333
|
+
resources?: ResourceRegistry<TContext>;
|
|
308
334
|
}
|
|
309
335
|
/** Function to detach the registry from the server */
|
|
310
336
|
export type DetachFn = () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerAttachment.d.ts","sourceRoot":"","sources":["../../src/server/ServerAttachment.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ServerAttachment.d.ts","sourceRoot":"","sources":["../../src/server/ServerAttachment.ts"],"names":[],"mappings":"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"}
|