@claude-flow/mcp 3.0.0-alpha.1
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/.agentic-flow/intelligence.json +16 -0
- package/README.md +428 -0
- package/__tests__/integration.test.ts +449 -0
- package/__tests__/mcp.test.ts +641 -0
- package/dist/connection-pool.d.ts +36 -0
- package/dist/connection-pool.d.ts.map +1 -0
- package/dist/connection-pool.js +273 -0
- package/dist/connection-pool.js.map +1 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +85 -0
- package/dist/index.js.map +1 -0
- package/dist/oauth.d.ts +146 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +318 -0
- package/dist/oauth.js.map +1 -0
- package/dist/prompt-registry.d.ts +90 -0
- package/dist/prompt-registry.d.ts.map +1 -0
- package/dist/prompt-registry.js +209 -0
- package/dist/prompt-registry.js.map +1 -0
- package/dist/rate-limiter.d.ts +86 -0
- package/dist/rate-limiter.d.ts.map +1 -0
- package/dist/rate-limiter.js +197 -0
- package/dist/rate-limiter.js.map +1 -0
- package/dist/resource-registry.d.ts +144 -0
- package/dist/resource-registry.d.ts.map +1 -0
- package/dist/resource-registry.js +405 -0
- package/dist/resource-registry.js.map +1 -0
- package/dist/sampling.d.ts +102 -0
- package/dist/sampling.d.ts.map +1 -0
- package/dist/sampling.js +268 -0
- package/dist/sampling.js.map +1 -0
- package/dist/schema-validator.d.ts +30 -0
- package/dist/schema-validator.d.ts.map +1 -0
- package/dist/schema-validator.js +182 -0
- package/dist/schema-validator.js.map +1 -0
- package/dist/server.d.ts +122 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +829 -0
- package/dist/server.js.map +1 -0
- package/dist/session-manager.d.ts +55 -0
- package/dist/session-manager.d.ts.map +1 -0
- package/dist/session-manager.js +252 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/task-manager.d.ts +81 -0
- package/dist/task-manager.d.ts.map +1 -0
- package/dist/task-manager.js +337 -0
- package/dist/task-manager.js.map +1 -0
- package/dist/tool-registry.d.ts +88 -0
- package/dist/tool-registry.d.ts.map +1 -0
- package/dist/tool-registry.js +353 -0
- package/dist/tool-registry.js.map +1 -0
- package/dist/transport/http.d.ts +55 -0
- package/dist/transport/http.d.ts.map +1 -0
- package/dist/transport/http.js +446 -0
- package/dist/transport/http.js.map +1 -0
- package/dist/transport/index.d.ts +50 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +181 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/stdio.d.ts +43 -0
- package/dist/transport/stdio.d.ts.map +1 -0
- package/dist/transport/stdio.js +194 -0
- package/dist/transport/stdio.js.map +1 -0
- package/dist/transport/websocket.d.ts +65 -0
- package/dist/transport/websocket.d.ts.map +1 -0
- package/dist/transport/websocket.js +314 -0
- package/dist/transport/websocket.js.map +1 -0
- package/dist/types.d.ts +473 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +40 -0
- package/dist/types.js.map +1 -0
- package/package.json +42 -0
- package/src/connection-pool.ts +344 -0
- package/src/index.ts +253 -0
- package/src/oauth.ts +447 -0
- package/src/prompt-registry.ts +296 -0
- package/src/rate-limiter.ts +266 -0
- package/src/resource-registry.ts +530 -0
- package/src/sampling.ts +363 -0
- package/src/schema-validator.ts +213 -0
- package/src/server.ts +1134 -0
- package/src/session-manager.ts +339 -0
- package/src/task-manager.ts +427 -0
- package/src/tool-registry.ts +475 -0
- package/src/transport/http.ts +532 -0
- package/src/transport/index.ts +233 -0
- package/src/transport/stdio.ts +252 -0
- package/src/transport/websocket.ts +396 -0
- package/src/types.ts +664 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +13 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @claude-flow/mcp - Rate Limiter
|
|
3
|
+
*
|
|
4
|
+
* Token bucket rate limiting for DoS protection
|
|
5
|
+
*/
|
|
6
|
+
import { EventEmitter } from 'events';
|
|
7
|
+
import type { ILogger } from './types.js';
|
|
8
|
+
export interface RateLimitConfig {
|
|
9
|
+
/** Requests per second */
|
|
10
|
+
requestsPerSecond: number;
|
|
11
|
+
/** Burst size (max tokens) */
|
|
12
|
+
burstSize: number;
|
|
13
|
+
/** Per-session limits (if different from global) */
|
|
14
|
+
perSessionLimit?: number;
|
|
15
|
+
/** Cleanup interval for expired sessions */
|
|
16
|
+
cleanupInterval?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface RateLimitResult {
|
|
19
|
+
allowed: boolean;
|
|
20
|
+
remaining: number;
|
|
21
|
+
resetIn: number;
|
|
22
|
+
retryAfter?: number;
|
|
23
|
+
}
|
|
24
|
+
export declare class RateLimiter extends EventEmitter {
|
|
25
|
+
private readonly logger;
|
|
26
|
+
private readonly config;
|
|
27
|
+
private globalBucket;
|
|
28
|
+
private sessionBuckets;
|
|
29
|
+
private cleanupTimer?;
|
|
30
|
+
constructor(logger: ILogger, config?: Partial<RateLimitConfig>);
|
|
31
|
+
/**
|
|
32
|
+
* Check if request is allowed (global limit)
|
|
33
|
+
*/
|
|
34
|
+
checkGlobal(): RateLimitResult;
|
|
35
|
+
/**
|
|
36
|
+
* Check if request is allowed (per-session limit)
|
|
37
|
+
*/
|
|
38
|
+
checkSession(sessionId: string): RateLimitResult;
|
|
39
|
+
/**
|
|
40
|
+
* Check both global and session limits
|
|
41
|
+
*/
|
|
42
|
+
check(sessionId?: string): RateLimitResult;
|
|
43
|
+
/**
|
|
44
|
+
* Consume a token (call after request is processed)
|
|
45
|
+
*/
|
|
46
|
+
consume(sessionId?: string): void;
|
|
47
|
+
/**
|
|
48
|
+
* Reset session bucket
|
|
49
|
+
*/
|
|
50
|
+
resetSession(sessionId: string): void;
|
|
51
|
+
/**
|
|
52
|
+
* Get current stats
|
|
53
|
+
*/
|
|
54
|
+
getStats(): {
|
|
55
|
+
globalTokens: number;
|
|
56
|
+
globalBurstSize: number;
|
|
57
|
+
sessionCount: number;
|
|
58
|
+
config: RateLimitConfig;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Destroy the rate limiter
|
|
62
|
+
*/
|
|
63
|
+
destroy(): void;
|
|
64
|
+
/**
|
|
65
|
+
* Check bucket and refill tokens
|
|
66
|
+
*/
|
|
67
|
+
private checkBucket;
|
|
68
|
+
/**
|
|
69
|
+
* Refill tokens based on elapsed time
|
|
70
|
+
*/
|
|
71
|
+
private refillBucket;
|
|
72
|
+
/**
|
|
73
|
+
* Consume a token from bucket
|
|
74
|
+
*/
|
|
75
|
+
private consumeFromBucket;
|
|
76
|
+
/**
|
|
77
|
+
* Start cleanup timer for expired sessions
|
|
78
|
+
*/
|
|
79
|
+
private startCleanup;
|
|
80
|
+
}
|
|
81
|
+
export declare function createRateLimiter(logger: ILogger, config?: Partial<RateLimitConfig>): RateLimiter;
|
|
82
|
+
/**
|
|
83
|
+
* Express/Connect middleware for rate limiting
|
|
84
|
+
*/
|
|
85
|
+
export declare function rateLimitMiddleware(rateLimiter: RateLimiter): (req: any, res: any, next: () => void) => void;
|
|
86
|
+
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,eAAe;IAC9B,0BAA0B;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4CAA4C;IAC5C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAcD,qBAAa,WAAY,SAAQ,YAAY;IAOzC,OAAO,CAAC,QAAQ,CAAC,MAAM;IANzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IACnD,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,cAAc,CAAuC;IAC7D,OAAO,CAAC,YAAY,CAAC,CAAiB;gBAGnB,MAAM,EAAE,OAAO,EAChC,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM;IAcvC;;OAEG;IACH,WAAW,IAAI,eAAe;IAI9B;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe;IAiBhD;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe;IAmB1C;;OAEG;IACH,OAAO,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAUjC;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAKrC;;OAEG;IACH,QAAQ,IAAI;QACV,YAAY,EAAE,MAAM,CAAC;QACrB,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,MAAM,EAAE,eAAe,CAAC;KACzB;IAUD;;OAEG;IACH,OAAO,IAAI,IAAI;IASf;;OAEG;IACH,OAAO,CAAC,WAAW;IA2BnB;;OAEG;IACH,OAAO,CAAC,YAAY;IASpB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAMzB;;OAEG;IACH,OAAO,CAAC,YAAY;CAarB;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,OAAO,EACf,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAChC,WAAW,CAEb;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,WAAW,IAClD,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,IAAI,UAwB7C"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @claude-flow/mcp - Rate Limiter
|
|
3
|
+
*
|
|
4
|
+
* Token bucket rate limiting for DoS protection
|
|
5
|
+
*/
|
|
6
|
+
import { EventEmitter } from 'events';
|
|
7
|
+
const DEFAULT_CONFIG = {
|
|
8
|
+
requestsPerSecond: 100,
|
|
9
|
+
burstSize: 200,
|
|
10
|
+
perSessionLimit: 50,
|
|
11
|
+
cleanupInterval: 60000, // 1 minute
|
|
12
|
+
};
|
|
13
|
+
export class RateLimiter extends EventEmitter {
|
|
14
|
+
logger;
|
|
15
|
+
config;
|
|
16
|
+
globalBucket;
|
|
17
|
+
sessionBuckets = new Map();
|
|
18
|
+
cleanupTimer;
|
|
19
|
+
constructor(logger, config = {}) {
|
|
20
|
+
super();
|
|
21
|
+
this.logger = logger;
|
|
22
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
23
|
+
// Initialize global bucket
|
|
24
|
+
this.globalBucket = {
|
|
25
|
+
tokens: this.config.burstSize,
|
|
26
|
+
lastRefill: Date.now(),
|
|
27
|
+
};
|
|
28
|
+
this.startCleanup();
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Check if request is allowed (global limit)
|
|
32
|
+
*/
|
|
33
|
+
checkGlobal() {
|
|
34
|
+
return this.checkBucket(this.globalBucket, this.config.requestsPerSecond, this.config.burstSize);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Check if request is allowed (per-session limit)
|
|
38
|
+
*/
|
|
39
|
+
checkSession(sessionId) {
|
|
40
|
+
let bucket = this.sessionBuckets.get(sessionId);
|
|
41
|
+
if (!bucket) {
|
|
42
|
+
bucket = {
|
|
43
|
+
tokens: this.config.perSessionLimit,
|
|
44
|
+
lastRefill: Date.now(),
|
|
45
|
+
};
|
|
46
|
+
this.sessionBuckets.set(sessionId, bucket);
|
|
47
|
+
}
|
|
48
|
+
return this.checkBucket(bucket, this.config.perSessionLimit / 10, // Refill rate (10 seconds to full)
|
|
49
|
+
this.config.perSessionLimit);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Check both global and session limits
|
|
53
|
+
*/
|
|
54
|
+
check(sessionId) {
|
|
55
|
+
const globalResult = this.checkGlobal();
|
|
56
|
+
if (!globalResult.allowed) {
|
|
57
|
+
this.emit('rate-limit:global', { remaining: globalResult.remaining });
|
|
58
|
+
return globalResult;
|
|
59
|
+
}
|
|
60
|
+
if (sessionId) {
|
|
61
|
+
const sessionResult = this.checkSession(sessionId);
|
|
62
|
+
if (!sessionResult.allowed) {
|
|
63
|
+
this.emit('rate-limit:session', { sessionId, remaining: sessionResult.remaining });
|
|
64
|
+
return sessionResult;
|
|
65
|
+
}
|
|
66
|
+
return sessionResult;
|
|
67
|
+
}
|
|
68
|
+
return globalResult;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Consume a token (call after request is processed)
|
|
72
|
+
*/
|
|
73
|
+
consume(sessionId) {
|
|
74
|
+
this.consumeFromBucket(this.globalBucket);
|
|
75
|
+
if (sessionId) {
|
|
76
|
+
const bucket = this.sessionBuckets.get(sessionId);
|
|
77
|
+
if (bucket) {
|
|
78
|
+
this.consumeFromBucket(bucket);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Reset session bucket
|
|
84
|
+
*/
|
|
85
|
+
resetSession(sessionId) {
|
|
86
|
+
this.sessionBuckets.delete(sessionId);
|
|
87
|
+
this.logger.debug('Rate limit session reset', { sessionId });
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get current stats
|
|
91
|
+
*/
|
|
92
|
+
getStats() {
|
|
93
|
+
this.refillBucket(this.globalBucket, this.config.requestsPerSecond, this.config.burstSize);
|
|
94
|
+
return {
|
|
95
|
+
globalTokens: Math.floor(this.globalBucket.tokens),
|
|
96
|
+
globalBurstSize: this.config.burstSize,
|
|
97
|
+
sessionCount: this.sessionBuckets.size,
|
|
98
|
+
config: this.config,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Destroy the rate limiter
|
|
103
|
+
*/
|
|
104
|
+
destroy() {
|
|
105
|
+
if (this.cleanupTimer) {
|
|
106
|
+
clearInterval(this.cleanupTimer);
|
|
107
|
+
this.cleanupTimer = undefined;
|
|
108
|
+
}
|
|
109
|
+
this.sessionBuckets.clear();
|
|
110
|
+
this.removeAllListeners();
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Check bucket and refill tokens
|
|
114
|
+
*/
|
|
115
|
+
checkBucket(bucket, refillRate, maxTokens) {
|
|
116
|
+
this.refillBucket(bucket, refillRate, maxTokens);
|
|
117
|
+
if (bucket.tokens >= 1) {
|
|
118
|
+
return {
|
|
119
|
+
allowed: true,
|
|
120
|
+
remaining: Math.floor(bucket.tokens) - 1,
|
|
121
|
+
resetIn: Math.ceil((maxTokens - bucket.tokens) / refillRate * 1000),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
// Calculate when bucket will have 1 token
|
|
125
|
+
const tokensNeeded = 1 - bucket.tokens;
|
|
126
|
+
const retryAfter = Math.ceil(tokensNeeded / refillRate);
|
|
127
|
+
return {
|
|
128
|
+
allowed: false,
|
|
129
|
+
remaining: 0,
|
|
130
|
+
resetIn: retryAfter * 1000,
|
|
131
|
+
retryAfter,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Refill tokens based on elapsed time
|
|
136
|
+
*/
|
|
137
|
+
refillBucket(bucket, refillRate, maxTokens) {
|
|
138
|
+
const now = Date.now();
|
|
139
|
+
const elapsed = (now - bucket.lastRefill) / 1000; // seconds
|
|
140
|
+
const tokensToAdd = elapsed * refillRate;
|
|
141
|
+
bucket.tokens = Math.min(maxTokens, bucket.tokens + tokensToAdd);
|
|
142
|
+
bucket.lastRefill = now;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Consume a token from bucket
|
|
146
|
+
*/
|
|
147
|
+
consumeFromBucket(bucket) {
|
|
148
|
+
if (bucket.tokens >= 1) {
|
|
149
|
+
bucket.tokens -= 1;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Start cleanup timer for expired sessions
|
|
154
|
+
*/
|
|
155
|
+
startCleanup() {
|
|
156
|
+
this.cleanupTimer = setInterval(() => {
|
|
157
|
+
const now = Date.now();
|
|
158
|
+
const expireTime = this.config.cleanupInterval * 2;
|
|
159
|
+
for (const [sessionId, bucket] of this.sessionBuckets) {
|
|
160
|
+
if (now - bucket.lastRefill > expireTime) {
|
|
161
|
+
this.sessionBuckets.delete(sessionId);
|
|
162
|
+
this.logger.debug('Rate limit session expired', { sessionId });
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}, this.config.cleanupInterval);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
export function createRateLimiter(logger, config) {
|
|
169
|
+
return new RateLimiter(logger, config);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Express/Connect middleware for rate limiting
|
|
173
|
+
*/
|
|
174
|
+
export function rateLimitMiddleware(rateLimiter) {
|
|
175
|
+
return (req, res, next) => {
|
|
176
|
+
const sessionId = req.headers['x-session-id'] || req.ip;
|
|
177
|
+
const result = rateLimiter.check(sessionId);
|
|
178
|
+
res.setHeader('X-RateLimit-Remaining', result.remaining);
|
|
179
|
+
res.setHeader('X-RateLimit-Reset', Math.ceil(Date.now() / 1000) + Math.ceil(result.resetIn / 1000));
|
|
180
|
+
if (!result.allowed) {
|
|
181
|
+
res.setHeader('Retry-After', result.retryAfter);
|
|
182
|
+
res.status(429).json({
|
|
183
|
+
jsonrpc: '2.0',
|
|
184
|
+
id: null,
|
|
185
|
+
error: {
|
|
186
|
+
code: -32000,
|
|
187
|
+
message: 'Rate limit exceeded',
|
|
188
|
+
data: { retryAfter: result.retryAfter },
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
rateLimiter.consume(sessionId);
|
|
194
|
+
next();
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @claude-flow/mcp - Resource Registry
|
|
3
|
+
*
|
|
4
|
+
* MCP 2025-11-25 compliant resource management
|
|
5
|
+
* Supports: list, read, subscribe, templates, pagination
|
|
6
|
+
*/
|
|
7
|
+
import { EventEmitter } from 'events';
|
|
8
|
+
import type { MCPResource, ResourceContent, ResourceTemplate, ResourceListResult, ResourceReadResult, ILogger, ContentAnnotations } from './types.js';
|
|
9
|
+
export type ResourceHandler = (uri: string) => Promise<ResourceContent[]>;
|
|
10
|
+
export type SubscriptionCallback = (uri: string, content: ResourceContent[]) => void;
|
|
11
|
+
export interface ResourceRegistryOptions {
|
|
12
|
+
enableSubscriptions?: boolean;
|
|
13
|
+
maxSubscriptionsPerResource?: number;
|
|
14
|
+
cacheEnabled?: boolean;
|
|
15
|
+
cacheTTL?: number;
|
|
16
|
+
maxCacheSize?: number;
|
|
17
|
+
}
|
|
18
|
+
export declare class ResourceRegistry extends EventEmitter {
|
|
19
|
+
private readonly logger;
|
|
20
|
+
private resources;
|
|
21
|
+
private templates;
|
|
22
|
+
private handlers;
|
|
23
|
+
private subscriptions;
|
|
24
|
+
private cache;
|
|
25
|
+
private subscriptionCounter;
|
|
26
|
+
private readonly options;
|
|
27
|
+
constructor(logger: ILogger, options?: ResourceRegistryOptions);
|
|
28
|
+
/**
|
|
29
|
+
* Register a static resource
|
|
30
|
+
*/
|
|
31
|
+
registerResource(resource: MCPResource, handler: ResourceHandler): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Register a resource template (dynamic URIs)
|
|
34
|
+
*/
|
|
35
|
+
registerTemplate(template: ResourceTemplate, handler: ResourceHandler): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Unregister a resource
|
|
38
|
+
*/
|
|
39
|
+
unregisterResource(uri: string): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* List resources with pagination
|
|
42
|
+
*/
|
|
43
|
+
list(cursor?: string, pageSize?: number): ResourceListResult;
|
|
44
|
+
/**
|
|
45
|
+
* Read resource content
|
|
46
|
+
*/
|
|
47
|
+
read(uri: string): Promise<ResourceReadResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Subscribe to resource updates
|
|
50
|
+
*/
|
|
51
|
+
subscribe(uri: string, callback: SubscriptionCallback): string;
|
|
52
|
+
/**
|
|
53
|
+
* Unsubscribe from resource updates
|
|
54
|
+
*/
|
|
55
|
+
unsubscribe(subscriptionId: string): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Notify subscribers of resource update
|
|
58
|
+
*/
|
|
59
|
+
notifyUpdate(uri: string): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Get resource by URI
|
|
62
|
+
*/
|
|
63
|
+
getResource(uri: string): MCPResource | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Check if resource exists
|
|
66
|
+
*/
|
|
67
|
+
hasResource(uri: string): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Get resource count
|
|
70
|
+
*/
|
|
71
|
+
getResourceCount(): number;
|
|
72
|
+
/**
|
|
73
|
+
* Get all templates
|
|
74
|
+
*/
|
|
75
|
+
getTemplates(): ResourceTemplate[];
|
|
76
|
+
/**
|
|
77
|
+
* Get subscription count for a resource
|
|
78
|
+
*/
|
|
79
|
+
getSubscriptionCount(uri: string): number;
|
|
80
|
+
/**
|
|
81
|
+
* Get stats
|
|
82
|
+
*/
|
|
83
|
+
getStats(): {
|
|
84
|
+
totalResources: number;
|
|
85
|
+
totalTemplates: number;
|
|
86
|
+
totalSubscriptions: number;
|
|
87
|
+
cacheSize: number;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Clear cache
|
|
91
|
+
*/
|
|
92
|
+
clearCache(): void;
|
|
93
|
+
/**
|
|
94
|
+
* Find handler for template URI
|
|
95
|
+
*/
|
|
96
|
+
private findTemplateHandler;
|
|
97
|
+
/**
|
|
98
|
+
* Escape regex metacharacters to prevent ReDoS attacks
|
|
99
|
+
* SECURITY: Critical for preventing regex denial of service
|
|
100
|
+
*/
|
|
101
|
+
private escapeRegex;
|
|
102
|
+
/**
|
|
103
|
+
* Check if URI matches any template
|
|
104
|
+
* SECURITY: Uses escaped regex to prevent ReDoS
|
|
105
|
+
*/
|
|
106
|
+
private matchesTemplate;
|
|
107
|
+
/**
|
|
108
|
+
* Encode cursor for pagination
|
|
109
|
+
*/
|
|
110
|
+
private encodeCursor;
|
|
111
|
+
/**
|
|
112
|
+
* Decode cursor for pagination
|
|
113
|
+
*/
|
|
114
|
+
private decodeCursor;
|
|
115
|
+
/**
|
|
116
|
+
* Emit listChanged notification
|
|
117
|
+
*/
|
|
118
|
+
private emitListChanged;
|
|
119
|
+
}
|
|
120
|
+
export declare function createResourceRegistry(logger: ILogger, options?: ResourceRegistryOptions): ResourceRegistry;
|
|
121
|
+
/**
|
|
122
|
+
* Helper to create a static text resource
|
|
123
|
+
*/
|
|
124
|
+
export declare function createTextResource(uri: string, name: string, text: string, options?: {
|
|
125
|
+
description?: string;
|
|
126
|
+
mimeType?: string;
|
|
127
|
+
annotations?: ContentAnnotations;
|
|
128
|
+
}): {
|
|
129
|
+
resource: MCPResource;
|
|
130
|
+
handler: ResourceHandler;
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Helper to create a file resource
|
|
134
|
+
* SECURITY: Validates path to prevent path traversal attacks
|
|
135
|
+
*/
|
|
136
|
+
export declare function createFileResource(uri: string, name: string, filePath: string, options?: {
|
|
137
|
+
description?: string;
|
|
138
|
+
mimeType?: string;
|
|
139
|
+
allowedBasePaths?: string[];
|
|
140
|
+
}): {
|
|
141
|
+
resource: MCPResource;
|
|
142
|
+
handler: ResourceHandler;
|
|
143
|
+
};
|
|
144
|
+
//# sourceMappingURL=resource-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-registry.d.ts","sourceRoot":"","sources":["../src/resource-registry.ts"],"names":[],"mappings":"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"}
|