@defai.digital/ax-cli 3.14.18 → 3.15.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/README.md +24 -2
- package/dist/mcp/client-v2.d.ts +103 -2
- package/dist/mcp/client-v2.js +299 -7
- package/dist/mcp/client-v2.js.map +1 -1
- package/dist/mcp/content-length-transport.d.ts +2 -0
- package/dist/mcp/content-length-transport.js +4 -1
- package/dist/mcp/content-length-transport.js.map +1 -1
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.js +4 -0
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/schema-validator.d.ts +77 -0
- package/dist/mcp/schema-validator.js +125 -0
- package/dist/mcp/schema-validator.js.map +1 -0
- package/dist/mcp/subscriptions.d.ts +164 -0
- package/dist/mcp/subscriptions.js +242 -0
- package/dist/mcp/subscriptions.js.map +1 -0
- package/dist/mcp/transports.d.ts +3 -0
- package/dist/mcp/transports.js +11 -2
- package/dist/mcp/transports.js.map +1 -1
- package/dist/mcp/zai-templates.js +4 -0
- package/dist/mcp/zai-templates.js.map +1 -1
- package/dist/schemas/settings-schemas.js +7 -0
- package/dist/schemas/settings-schemas.js.map +1 -1
- package/package.json +1 -1
- package/.ax-cli/CUSTOM.md +0 -97
- package/.ax-cli/auto-accept-audit.json +0 -1302
- package/.ax-cli/index.json +0 -43
- package/.ax-cli/memory.json +0 -62
- package/.ax-cli/settings.json +0 -39
- package/ax.config.json +0 -304
- package/dist/analyzers/ast/tree-sitter-parser.d.ts +0 -134
- package/dist/analyzers/ast/tree-sitter-parser.js +0 -730
- package/dist/analyzers/ast/tree-sitter-parser.js.map +0 -1
- package/dist/mcp/config-detector-v2.d.ts +0 -83
- package/dist/mcp/config-detector-v2.js +0 -328
- package/dist/mcp/config-detector-v2.js.map +0 -1
- package/dist/mcp/config-migrator-v2.d.ts +0 -89
- package/dist/mcp/config-migrator-v2.js +0 -288
- package/dist/mcp/config-migrator-v2.js.map +0 -1
- package/dist/mcp/config-v2.d.ts +0 -111
- package/dist/mcp/config-v2.js +0 -443
- package/dist/mcp/config-v2.js.map +0 -1
- package/dist/mcp/transports-v2.d.ts +0 -152
- package/dist/mcp/transports-v2.js +0 -481
- package/dist/mcp/transports-v2.js.map +0 -1
- package/dist/utils/error-sanitizer.d.ts +0 -119
- package/dist/utils/error-sanitizer.js +0 -253
- package/dist/utils/error-sanitizer.js.map +0 -1
- package/dist/utils/errors.d.ts +0 -74
- package/dist/utils/errors.js +0 -139
- package/dist/utils/errors.js.map +0 -1
- package/dist/utils/incremental-analyzer.d.ts +0 -134
- package/dist/utils/incremental-analyzer.js +0 -377
- package/dist/utils/incremental-analyzer.js.map +0 -1
- package/dist/utils/math.d.ts +0 -1
- package/dist/utils/math.js +0 -4
- package/dist/utils/math.js.map +0 -1
- package/dist/utils/settings.d.ts +0 -1
- package/dist/utils/settings.js +0 -4
- package/dist/utils/settings.js.map +0 -1
- package/dist/utils/streaming-analyzer.d.ts +0 -160
- package/dist/utils/streaming-analyzer.js +0 -214
- package/dist/utils/streaming-analyzer.js.map +0 -1
|
@@ -45,8 +45,11 @@ export class ContentLengthStdioTransport extends EventEmitter {
|
|
|
45
45
|
this._started = true;
|
|
46
46
|
return new Promise((resolve, reject) => {
|
|
47
47
|
try {
|
|
48
|
+
// Use "pipe" for stderr in quiet mode to suppress INFO/DEBUG logs
|
|
49
|
+
// Use "inherit" otherwise to show all output (default behavior)
|
|
50
|
+
const stderrOption = this.config.quiet ? "pipe" : "inherit";
|
|
48
51
|
this.process = spawn(this.config.command, this.config.args || [], {
|
|
49
|
-
stdio: ["pipe", "pipe",
|
|
52
|
+
stdio: ["pipe", "pipe", stderrOption],
|
|
50
53
|
env: {
|
|
51
54
|
...process.env,
|
|
52
55
|
...this.config.env,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-length-transport.js","sourceRoot":"","sources":["../../src/mcp/content-length-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,KAAK,EAAgB,MAAM,eAAe,CAAC;AAEpD,OAAO,EAAkB,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"content-length-transport.js","sourceRoot":"","sources":["../../src/mcp/content-length-transport.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp/index.d.ts
CHANGED
|
@@ -33,5 +33,7 @@ export { Result, Ok, Err } from "./type-safety.js";
|
|
|
33
33
|
export { resolveMCPReferences, extractMCPReferences } from "./resources.js";
|
|
34
34
|
export { ProgressTracker, getProgressTracker, resetProgressTracker, formatProgress, formatElapsedTime, type ProgressUpdate, type ProgressCallback, } from "./progress.js";
|
|
35
35
|
export { CancellationManager, getCancellationManager, resetCancellationManager, isRequestCancelled, createCancellationError, CANCELLED_ERROR_CODE, type CancellableRequest, type CancellationResult, } from "./cancellation.js";
|
|
36
|
+
export { SubscriptionManager, getSubscriptionManager, resetSubscriptionManager, type ResourceSubscription, } from "./subscriptions.js";
|
|
37
|
+
export { ToolOutputValidator, getToolOutputValidator, resetToolOutputValidator, type SchemaValidationResult, type SchemaValidationStatus, } from "./schema-validator.js";
|
|
36
38
|
export { ZAI_SERVER_NAMES, ZAI_ENDPOINTS, ZAI_VISION_PACKAGE, ZAI_MCP_TEMPLATES, ZAI_QUOTA_LIMITS, generateZAIServerConfig, getAllZAIServerNames, isZAIServer, getZAITemplate, type ZAIServerName, type ZAIPlanTier, type ZAIMCPTemplate, } from "./zai-templates.js";
|
|
37
39
|
export { detectZAIServices, getEnabledZAIServers, validateZAIApiKey, getZAIApiKey, isZAIMCPConfigured, getRecommendedServers, isGLMModel, isZAIBaseURL, formatZAIStatus, type ZAIServiceStatus, } from "./zai-detector.js";
|
package/dist/mcp/index.js
CHANGED
|
@@ -40,6 +40,10 @@ export { resolveMCPReferences, extractMCPReferences } from "./resources.js";
|
|
|
40
40
|
export { ProgressTracker, getProgressTracker, resetProgressTracker, formatProgress, formatElapsedTime, } from "./progress.js";
|
|
41
41
|
// Cancellation support (MCP 2025-06-18)
|
|
42
42
|
export { CancellationManager, getCancellationManager, resetCancellationManager, isRequestCancelled, createCancellationError, CANCELLED_ERROR_CODE, } from "./cancellation.js";
|
|
43
|
+
// Resource subscriptions (MCP 2025-06-18)
|
|
44
|
+
export { SubscriptionManager, getSubscriptionManager, resetSubscriptionManager, } from "./subscriptions.js";
|
|
45
|
+
// Schema validation (MCP 2025-06-18)
|
|
46
|
+
export { ToolOutputValidator, getToolOutputValidator, resetToolOutputValidator, } from "./schema-validator.js";
|
|
43
47
|
// Z.AI MCP Integration
|
|
44
48
|
export { ZAI_SERVER_NAMES, ZAI_ENDPOINTS, ZAI_VISION_PACKAGE, ZAI_MCP_TEMPLATES, ZAI_QUOTA_LIMITS, generateZAIServerConfig, getAllZAIServerNames, isZAIServer, getZAITemplate, } from "./zai-templates.js";
|
|
45
49
|
export { detectZAIServices, getEnabledZAIServers, validateZAIApiKey, getZAIApiKey, isZAIMCPConfigured, getRecommendedServers, isGLMModel, isZAIBaseURL, formatZAIStatus, } from "./zai-detector.js";
|
package/dist/mcp/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,qDAAqD;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,uDAAuD;AACvD,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,cAAc,GAIf,MAAM,gBAAgB,CAAC;AAGxB,mBAAmB;AACnB,OAAO,EACL,kBAAkB,EAAE,6CAA6C;AACjE,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAEtB,gBAAgB;AAChB,OAAO,EACL,aAAa,EACb,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,WAAW,EACX,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AAGrB,aAAa;AACb,OAAO,EACL,eAAe,GAKhB,MAAM,iBAAiB,CAAC;AAEzB,iCAAiC;AACjC,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACtG,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAEtG,wBAAwB;AACxB,OAAO,EAAU,EAAE,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEnD,oBAAoB;AACpB,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE5E,qCAAqC;AACrC,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,GAGlB,MAAM,eAAe,CAAC;AAEvB,wCAAwC;AACxC,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,wBAAwB,EACxB,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,GAGrB,MAAM,mBAAmB,CAAC;AAE3B,uBAAuB;AACvB,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,EACpB,WAAW,EACX,cAAc,GAIf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,EAClB,qBAAqB,EACrB,UAAU,EACV,YAAY,EACZ,eAAe,GAEhB,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,qDAAqD;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,uDAAuD;AACvD,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,cAAc,GAIf,MAAM,gBAAgB,CAAC;AAGxB,mBAAmB;AACnB,OAAO,EACL,kBAAkB,EAAE,6CAA6C;AACjE,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAEtB,gBAAgB;AAChB,OAAO,EACL,aAAa,EACb,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,WAAW,EACX,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AAGrB,aAAa;AACb,OAAO,EACL,eAAe,GAKhB,MAAM,iBAAiB,CAAC;AAEzB,iCAAiC;AACjC,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACtG,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAEtG,wBAAwB;AACxB,OAAO,EAAU,EAAE,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEnD,oBAAoB;AACpB,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE5E,qCAAqC;AACrC,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,GAGlB,MAAM,eAAe,CAAC;AAEvB,wCAAwC;AACxC,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,wBAAwB,EACxB,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,GAGrB,MAAM,mBAAmB,CAAC;AAE3B,0CAA0C;AAC1C,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,wBAAwB,GAEzB,MAAM,oBAAoB,CAAC;AAE5B,qCAAqC;AACrC,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,wBAAwB,GAGzB,MAAM,uBAAuB,CAAC;AAE/B,uBAAuB;AACvB,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,EACpB,WAAW,EACX,cAAc,GAIf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,EAClB,qBAAqB,EACrB,UAAU,EACV,YAAY,EACZ,eAAe,GAEhB,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool Output Schema Validation
|
|
3
|
+
*
|
|
4
|
+
* Validates tool outputs against their declared JSON schemas using Ajv.
|
|
5
|
+
* Uses the MCP SDK's AjvJsonSchemaValidator for consistency.
|
|
6
|
+
*
|
|
7
|
+
* MCP Specification: Tool Output Schemas (2025-06-18)
|
|
8
|
+
*
|
|
9
|
+
* @module mcp/schema-validator
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Schema validation result status
|
|
13
|
+
*/
|
|
14
|
+
export type SchemaValidationStatus = 'valid' | 'invalid' | 'no-schema';
|
|
15
|
+
/**
|
|
16
|
+
* Schema validation result
|
|
17
|
+
*/
|
|
18
|
+
export interface SchemaValidationResult {
|
|
19
|
+
/** Validation status */
|
|
20
|
+
status: SchemaValidationStatus;
|
|
21
|
+
/** Validation errors (if status is 'invalid') */
|
|
22
|
+
errors?: string[];
|
|
23
|
+
/** The schema that was used for validation */
|
|
24
|
+
schema?: unknown;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Tool Output Schema Validator
|
|
28
|
+
*
|
|
29
|
+
* Validates MCP tool outputs against their declared JSON schemas.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const validator = new ToolOutputValidator();
|
|
34
|
+
*
|
|
35
|
+
* // Validate tool output
|
|
36
|
+
* const result = validator.validate(outputSchema, toolOutput);
|
|
37
|
+
*
|
|
38
|
+
* if (result.status === 'invalid') {
|
|
39
|
+
* console.warn('Tool output validation failed:', result.errors);
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare class ToolOutputValidator {
|
|
44
|
+
private validator;
|
|
45
|
+
constructor();
|
|
46
|
+
/**
|
|
47
|
+
* Validate tool output against schema
|
|
48
|
+
*
|
|
49
|
+
* @param schema - JSON schema to validate against (or undefined if no schema)
|
|
50
|
+
* @param output - Tool output to validate
|
|
51
|
+
* @returns Validation result
|
|
52
|
+
*/
|
|
53
|
+
validate(schema: unknown, output: unknown): SchemaValidationResult;
|
|
54
|
+
/**
|
|
55
|
+
* Validate tool output content array
|
|
56
|
+
*
|
|
57
|
+
* MCP tool results return an array of content items.
|
|
58
|
+
* This method validates the extracted content.
|
|
59
|
+
*
|
|
60
|
+
* @param schema - JSON schema
|
|
61
|
+
* @param content - MCP tool result content array
|
|
62
|
+
* @returns Validation result
|
|
63
|
+
*/
|
|
64
|
+
validateContent(schema: unknown, content: Array<{
|
|
65
|
+
type: string;
|
|
66
|
+
text?: string;
|
|
67
|
+
[key: string]: unknown;
|
|
68
|
+
}>): SchemaValidationResult;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get the singleton validator instance
|
|
72
|
+
*/
|
|
73
|
+
export declare function getToolOutputValidator(): ToolOutputValidator;
|
|
74
|
+
/**
|
|
75
|
+
* Reset the validator (for testing)
|
|
76
|
+
*/
|
|
77
|
+
export declare function resetToolOutputValidator(): void;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool Output Schema Validation
|
|
3
|
+
*
|
|
4
|
+
* Validates tool outputs against their declared JSON schemas using Ajv.
|
|
5
|
+
* Uses the MCP SDK's AjvJsonSchemaValidator for consistency.
|
|
6
|
+
*
|
|
7
|
+
* MCP Specification: Tool Output Schemas (2025-06-18)
|
|
8
|
+
*
|
|
9
|
+
* @module mcp/schema-validator
|
|
10
|
+
*/
|
|
11
|
+
import { AjvJsonSchemaValidator } from '@modelcontextprotocol/sdk/validation/ajv';
|
|
12
|
+
/**
|
|
13
|
+
* Tool Output Schema Validator
|
|
14
|
+
*
|
|
15
|
+
* Validates MCP tool outputs against their declared JSON schemas.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const validator = new ToolOutputValidator();
|
|
20
|
+
*
|
|
21
|
+
* // Validate tool output
|
|
22
|
+
* const result = validator.validate(outputSchema, toolOutput);
|
|
23
|
+
*
|
|
24
|
+
* if (result.status === 'invalid') {
|
|
25
|
+
* console.warn('Tool output validation failed:', result.errors);
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export class ToolOutputValidator {
|
|
30
|
+
validator;
|
|
31
|
+
constructor() {
|
|
32
|
+
this.validator = new AjvJsonSchemaValidator();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Validate tool output against schema
|
|
36
|
+
*
|
|
37
|
+
* @param schema - JSON schema to validate against (or undefined if no schema)
|
|
38
|
+
* @param output - Tool output to validate
|
|
39
|
+
* @returns Validation result
|
|
40
|
+
*/
|
|
41
|
+
validate(schema, output) {
|
|
42
|
+
// No schema defined
|
|
43
|
+
if (schema === undefined || schema === null) {
|
|
44
|
+
return { status: 'no-schema' };
|
|
45
|
+
}
|
|
46
|
+
// Empty schema (matches anything)
|
|
47
|
+
if (typeof schema === 'object' && Object.keys(schema).length === 0) {
|
|
48
|
+
return { status: 'valid', schema };
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
// Use the SDK's validator - getValidator returns a function
|
|
52
|
+
const validateFn = this.validator.getValidator(schema);
|
|
53
|
+
const result = validateFn(output);
|
|
54
|
+
if (result.valid) {
|
|
55
|
+
return { status: 'valid', schema };
|
|
56
|
+
}
|
|
57
|
+
// Extract error message
|
|
58
|
+
return {
|
|
59
|
+
status: 'invalid',
|
|
60
|
+
errors: result.errorMessage ? [result.errorMessage] : ['Validation failed'],
|
|
61
|
+
schema,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
// Schema compilation error
|
|
66
|
+
return {
|
|
67
|
+
status: 'invalid',
|
|
68
|
+
errors: [`Schema compilation error: ${error instanceof Error ? error.message : String(error)}`],
|
|
69
|
+
schema,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Validate tool output content array
|
|
75
|
+
*
|
|
76
|
+
* MCP tool results return an array of content items.
|
|
77
|
+
* This method validates the extracted content.
|
|
78
|
+
*
|
|
79
|
+
* @param schema - JSON schema
|
|
80
|
+
* @param content - MCP tool result content array
|
|
81
|
+
* @returns Validation result
|
|
82
|
+
*/
|
|
83
|
+
validateContent(schema, content) {
|
|
84
|
+
if (schema === undefined || schema === null) {
|
|
85
|
+
return { status: 'no-schema' };
|
|
86
|
+
}
|
|
87
|
+
// Extract text content and try to parse as JSON
|
|
88
|
+
const textContent = content
|
|
89
|
+
.filter((item) => item.type === 'text' && item.text)
|
|
90
|
+
.map((item) => item.text)
|
|
91
|
+
.join('');
|
|
92
|
+
if (!textContent) {
|
|
93
|
+
// No text content to validate
|
|
94
|
+
return { status: 'valid', schema };
|
|
95
|
+
}
|
|
96
|
+
// Try to parse as JSON
|
|
97
|
+
let parsedOutput;
|
|
98
|
+
try {
|
|
99
|
+
parsedOutput = JSON.parse(textContent);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// Not JSON - validate as string if schema allows
|
|
103
|
+
parsedOutput = textContent;
|
|
104
|
+
}
|
|
105
|
+
return this.validate(schema, parsedOutput);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Singleton instance
|
|
109
|
+
let validatorInstance = null;
|
|
110
|
+
/**
|
|
111
|
+
* Get the singleton validator instance
|
|
112
|
+
*/
|
|
113
|
+
export function getToolOutputValidator() {
|
|
114
|
+
if (!validatorInstance) {
|
|
115
|
+
validatorInstance = new ToolOutputValidator();
|
|
116
|
+
}
|
|
117
|
+
return validatorInstance;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Reset the validator (for testing)
|
|
121
|
+
*/
|
|
122
|
+
export function resetToolOutputValidator() {
|
|
123
|
+
validatorInstance = null;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=schema-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-validator.js","sourceRoot":"","sources":["../../src/mcp/schema-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Resource Subscriptions
|
|
3
|
+
*
|
|
4
|
+
* Enables clients to subscribe to resource changes and receive notifications
|
|
5
|
+
* when resources are updated.
|
|
6
|
+
*
|
|
7
|
+
* MCP Specification:
|
|
8
|
+
* - resources/subscribe - Subscribe to a resource
|
|
9
|
+
* - resources/unsubscribe - Unsubscribe from a resource
|
|
10
|
+
* - notifications/resources/updated - Resource update notification
|
|
11
|
+
* - notifications/resources/list_changed - Resource list change notification
|
|
12
|
+
*
|
|
13
|
+
* @module mcp/subscriptions
|
|
14
|
+
*/
|
|
15
|
+
import { EventEmitter } from 'events';
|
|
16
|
+
import type { ServerName } from './type-safety.js';
|
|
17
|
+
import { Result } from './type-safety.js';
|
|
18
|
+
/**
|
|
19
|
+
* Resource subscription information
|
|
20
|
+
*/
|
|
21
|
+
export interface ResourceSubscription {
|
|
22
|
+
/** Resource URI */
|
|
23
|
+
uri: string;
|
|
24
|
+
/** Server providing the resource */
|
|
25
|
+
serverName: ServerName;
|
|
26
|
+
/** When the subscription was created */
|
|
27
|
+
subscribedAt: Date;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Callback for sending subscription requests to server
|
|
31
|
+
*/
|
|
32
|
+
export type SendSubscriptionRequest = (serverName: ServerName, method: 'resources/subscribe' | 'resources/unsubscribe', uri: string) => Promise<Result<void, Error>>;
|
|
33
|
+
/**
|
|
34
|
+
* Callback for checking server capabilities
|
|
35
|
+
*/
|
|
36
|
+
export type CheckServerCapabilities = (serverName: ServerName) => Promise<{
|
|
37
|
+
supportsSubscriptions: boolean;
|
|
38
|
+
}>;
|
|
39
|
+
/**
|
|
40
|
+
* Subscription Manager
|
|
41
|
+
*
|
|
42
|
+
* Manages resource subscriptions across MCP servers.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const manager = new SubscriptionManager();
|
|
47
|
+
*
|
|
48
|
+
* // Subscribe to a resource
|
|
49
|
+
* await manager.subscribe('filesystem', 'file:///config.json');
|
|
50
|
+
*
|
|
51
|
+
* // Listen for updates
|
|
52
|
+
* manager.on('resource-updated', (uri, serverName) => {
|
|
53
|
+
* console.log(`Resource updated: ${uri} from ${serverName}`);
|
|
54
|
+
* });
|
|
55
|
+
*
|
|
56
|
+
* // Unsubscribe
|
|
57
|
+
* await manager.unsubscribe('filesystem', 'file:///config.json');
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare class SubscriptionManager extends EventEmitter {
|
|
61
|
+
private subscriptions;
|
|
62
|
+
private sendRequest;
|
|
63
|
+
private checkCapabilities;
|
|
64
|
+
/**
|
|
65
|
+
* Set the request sender function
|
|
66
|
+
* Called by MCPManagerV2 to wire up the request mechanism
|
|
67
|
+
*/
|
|
68
|
+
setSendRequest(fn: SendSubscriptionRequest): void;
|
|
69
|
+
/**
|
|
70
|
+
* Set the capabilities checker function
|
|
71
|
+
* Called by MCPManagerV2 to wire up capability checking
|
|
72
|
+
*/
|
|
73
|
+
setCheckCapabilities(fn: CheckServerCapabilities): void;
|
|
74
|
+
/**
|
|
75
|
+
* Get subscription key for internal storage
|
|
76
|
+
*/
|
|
77
|
+
private getKey;
|
|
78
|
+
/**
|
|
79
|
+
* Subscribe to a resource
|
|
80
|
+
*
|
|
81
|
+
* @param serverName - Server providing the resource
|
|
82
|
+
* @param uri - Resource URI to subscribe to
|
|
83
|
+
* @returns Result indicating success or error
|
|
84
|
+
*/
|
|
85
|
+
subscribe(serverName: ServerName, uri: string): Promise<Result<void, Error>>;
|
|
86
|
+
/**
|
|
87
|
+
* Unsubscribe from a resource
|
|
88
|
+
*
|
|
89
|
+
* @param serverName - Server providing the resource
|
|
90
|
+
* @param uri - Resource URI to unsubscribe from
|
|
91
|
+
* @returns Result indicating success or error
|
|
92
|
+
*/
|
|
93
|
+
unsubscribe(serverName: ServerName, uri: string): Promise<Result<void, Error>>;
|
|
94
|
+
/**
|
|
95
|
+
* Handle resource update notification from server
|
|
96
|
+
*
|
|
97
|
+
* @param serverName - Server that sent the notification
|
|
98
|
+
* @param uri - Updated resource URI
|
|
99
|
+
*/
|
|
100
|
+
handleResourceUpdated(serverName: ServerName, uri: string): void;
|
|
101
|
+
/**
|
|
102
|
+
* Handle resource list change notification from server
|
|
103
|
+
*
|
|
104
|
+
* @param serverName - Server that sent the notification
|
|
105
|
+
*/
|
|
106
|
+
handleResourceListChanged(serverName: ServerName): void;
|
|
107
|
+
/**
|
|
108
|
+
* Get all active subscriptions
|
|
109
|
+
*
|
|
110
|
+
* @returns Array of active subscriptions
|
|
111
|
+
*/
|
|
112
|
+
getActiveSubscriptions(): ResourceSubscription[];
|
|
113
|
+
/**
|
|
114
|
+
* Get subscriptions for a specific server
|
|
115
|
+
*
|
|
116
|
+
* @param serverName - Server to get subscriptions for
|
|
117
|
+
* @returns Array of subscriptions for the server
|
|
118
|
+
*/
|
|
119
|
+
getSubscriptionsForServer(serverName: ServerName): ResourceSubscription[];
|
|
120
|
+
/**
|
|
121
|
+
* Check if subscribed to a resource
|
|
122
|
+
*
|
|
123
|
+
* @param serverName - Server providing the resource
|
|
124
|
+
* @param uri - Resource URI
|
|
125
|
+
* @returns true if subscribed
|
|
126
|
+
*/
|
|
127
|
+
isSubscribed(serverName: ServerName, uri: string): boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Get the number of active subscriptions
|
|
130
|
+
*
|
|
131
|
+
* @returns Number of active subscriptions
|
|
132
|
+
*/
|
|
133
|
+
getSubscriptionCount(): number;
|
|
134
|
+
/**
|
|
135
|
+
* Resubscribe all subscriptions for a server
|
|
136
|
+
* Called after server reconnection
|
|
137
|
+
*
|
|
138
|
+
* @param serverName - Server to resubscribe for
|
|
139
|
+
* @returns Results of resubscription attempts
|
|
140
|
+
*/
|
|
141
|
+
resubscribeForServer(serverName: ServerName): Promise<Array<{
|
|
142
|
+
uri: string;
|
|
143
|
+
result: Result<void, Error>;
|
|
144
|
+
}>>;
|
|
145
|
+
/**
|
|
146
|
+
* Unsubscribe from all resources on a server
|
|
147
|
+
* Called during server disconnection
|
|
148
|
+
*
|
|
149
|
+
* @param serverName - Server to unsubscribe from
|
|
150
|
+
*/
|
|
151
|
+
unsubscribeAllForServer(serverName: ServerName): void;
|
|
152
|
+
/**
|
|
153
|
+
* Cleanup all subscriptions
|
|
154
|
+
*/
|
|
155
|
+
cleanupAll(): void;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get the singleton subscription manager instance
|
|
159
|
+
*/
|
|
160
|
+
export declare function getSubscriptionManager(): SubscriptionManager;
|
|
161
|
+
/**
|
|
162
|
+
* Reset the subscription manager (for testing)
|
|
163
|
+
*/
|
|
164
|
+
export declare function resetSubscriptionManager(): void;
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Resource Subscriptions
|
|
3
|
+
*
|
|
4
|
+
* Enables clients to subscribe to resource changes and receive notifications
|
|
5
|
+
* when resources are updated.
|
|
6
|
+
*
|
|
7
|
+
* MCP Specification:
|
|
8
|
+
* - resources/subscribe - Subscribe to a resource
|
|
9
|
+
* - resources/unsubscribe - Unsubscribe from a resource
|
|
10
|
+
* - notifications/resources/updated - Resource update notification
|
|
11
|
+
* - notifications/resources/list_changed - Resource list change notification
|
|
12
|
+
*
|
|
13
|
+
* @module mcp/subscriptions
|
|
14
|
+
*/
|
|
15
|
+
import { EventEmitter } from 'events';
|
|
16
|
+
import { Ok, Err } from './type-safety.js';
|
|
17
|
+
/**
|
|
18
|
+
* Subscription Manager
|
|
19
|
+
*
|
|
20
|
+
* Manages resource subscriptions across MCP servers.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const manager = new SubscriptionManager();
|
|
25
|
+
*
|
|
26
|
+
* // Subscribe to a resource
|
|
27
|
+
* await manager.subscribe('filesystem', 'file:///config.json');
|
|
28
|
+
*
|
|
29
|
+
* // Listen for updates
|
|
30
|
+
* manager.on('resource-updated', (uri, serverName) => {
|
|
31
|
+
* console.log(`Resource updated: ${uri} from ${serverName}`);
|
|
32
|
+
* });
|
|
33
|
+
*
|
|
34
|
+
* // Unsubscribe
|
|
35
|
+
* await manager.unsubscribe('filesystem', 'file:///config.json');
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export class SubscriptionManager extends EventEmitter {
|
|
39
|
+
subscriptions = new Map();
|
|
40
|
+
sendRequest = null;
|
|
41
|
+
checkCapabilities = null;
|
|
42
|
+
/**
|
|
43
|
+
* Set the request sender function
|
|
44
|
+
* Called by MCPManagerV2 to wire up the request mechanism
|
|
45
|
+
*/
|
|
46
|
+
setSendRequest(fn) {
|
|
47
|
+
this.sendRequest = fn;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Set the capabilities checker function
|
|
51
|
+
* Called by MCPManagerV2 to wire up capability checking
|
|
52
|
+
*/
|
|
53
|
+
setCheckCapabilities(fn) {
|
|
54
|
+
this.checkCapabilities = fn;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get subscription key for internal storage
|
|
58
|
+
*/
|
|
59
|
+
getKey(serverName, uri) {
|
|
60
|
+
return `${serverName}:${uri}`;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Subscribe to a resource
|
|
64
|
+
*
|
|
65
|
+
* @param serverName - Server providing the resource
|
|
66
|
+
* @param uri - Resource URI to subscribe to
|
|
67
|
+
* @returns Result indicating success or error
|
|
68
|
+
*/
|
|
69
|
+
async subscribe(serverName, uri) {
|
|
70
|
+
// Check if already subscribed
|
|
71
|
+
const key = this.getKey(serverName, uri);
|
|
72
|
+
if (this.subscriptions.has(key)) {
|
|
73
|
+
return Ok(undefined); // Already subscribed
|
|
74
|
+
}
|
|
75
|
+
// Check server capabilities
|
|
76
|
+
if (this.checkCapabilities) {
|
|
77
|
+
const caps = await this.checkCapabilities(serverName);
|
|
78
|
+
if (!caps.supportsSubscriptions) {
|
|
79
|
+
return Err(new Error(`Server ${serverName} does not support resource subscriptions`));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Send subscription request
|
|
83
|
+
if (!this.sendRequest) {
|
|
84
|
+
return Err(new Error('Subscription manager not initialized'));
|
|
85
|
+
}
|
|
86
|
+
const result = await this.sendRequest(serverName, 'resources/subscribe', uri);
|
|
87
|
+
if (!result.success) {
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
// Track the subscription
|
|
91
|
+
this.subscriptions.set(key, {
|
|
92
|
+
uri,
|
|
93
|
+
serverName,
|
|
94
|
+
subscribedAt: new Date(),
|
|
95
|
+
});
|
|
96
|
+
this.emit('subscribed', uri, serverName);
|
|
97
|
+
return Ok(undefined);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Unsubscribe from a resource
|
|
101
|
+
*
|
|
102
|
+
* @param serverName - Server providing the resource
|
|
103
|
+
* @param uri - Resource URI to unsubscribe from
|
|
104
|
+
* @returns Result indicating success or error
|
|
105
|
+
*/
|
|
106
|
+
async unsubscribe(serverName, uri) {
|
|
107
|
+
const key = this.getKey(serverName, uri);
|
|
108
|
+
if (!this.subscriptions.has(key)) {
|
|
109
|
+
return Ok(undefined); // Not subscribed
|
|
110
|
+
}
|
|
111
|
+
// Send unsubscription request
|
|
112
|
+
if (this.sendRequest) {
|
|
113
|
+
const result = await this.sendRequest(serverName, 'resources/unsubscribe', uri);
|
|
114
|
+
if (!result.success) {
|
|
115
|
+
// Log but don't fail - we'll still clean up locally
|
|
116
|
+
console.warn(`Failed to unsubscribe from ${uri}: ${result.error.message}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Remove from tracking
|
|
120
|
+
this.subscriptions.delete(key);
|
|
121
|
+
this.emit('unsubscribed', uri, serverName);
|
|
122
|
+
return Ok(undefined);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Handle resource update notification from server
|
|
126
|
+
*
|
|
127
|
+
* @param serverName - Server that sent the notification
|
|
128
|
+
* @param uri - Updated resource URI
|
|
129
|
+
*/
|
|
130
|
+
handleResourceUpdated(serverName, uri) {
|
|
131
|
+
const key = this.getKey(serverName, uri);
|
|
132
|
+
if (this.subscriptions.has(key)) {
|
|
133
|
+
this.emit('resource-updated', uri, serverName);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Handle resource list change notification from server
|
|
138
|
+
*
|
|
139
|
+
* @param serverName - Server that sent the notification
|
|
140
|
+
*/
|
|
141
|
+
handleResourceListChanged(serverName) {
|
|
142
|
+
this.emit('resource-list-changed', serverName);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get all active subscriptions
|
|
146
|
+
*
|
|
147
|
+
* @returns Array of active subscriptions
|
|
148
|
+
*/
|
|
149
|
+
getActiveSubscriptions() {
|
|
150
|
+
return Array.from(this.subscriptions.values());
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Get subscriptions for a specific server
|
|
154
|
+
*
|
|
155
|
+
* @param serverName - Server to get subscriptions for
|
|
156
|
+
* @returns Array of subscriptions for the server
|
|
157
|
+
*/
|
|
158
|
+
getSubscriptionsForServer(serverName) {
|
|
159
|
+
return this.getActiveSubscriptions().filter(sub => sub.serverName === serverName);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Check if subscribed to a resource
|
|
163
|
+
*
|
|
164
|
+
* @param serverName - Server providing the resource
|
|
165
|
+
* @param uri - Resource URI
|
|
166
|
+
* @returns true if subscribed
|
|
167
|
+
*/
|
|
168
|
+
isSubscribed(serverName, uri) {
|
|
169
|
+
return this.subscriptions.has(this.getKey(serverName, uri));
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get the number of active subscriptions
|
|
173
|
+
*
|
|
174
|
+
* @returns Number of active subscriptions
|
|
175
|
+
*/
|
|
176
|
+
getSubscriptionCount() {
|
|
177
|
+
return this.subscriptions.size;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Resubscribe all subscriptions for a server
|
|
181
|
+
* Called after server reconnection
|
|
182
|
+
*
|
|
183
|
+
* @param serverName - Server to resubscribe for
|
|
184
|
+
* @returns Results of resubscription attempts
|
|
185
|
+
*/
|
|
186
|
+
async resubscribeForServer(serverName) {
|
|
187
|
+
const subs = this.getSubscriptionsForServer(serverName);
|
|
188
|
+
const results = [];
|
|
189
|
+
for (const sub of subs) {
|
|
190
|
+
// Remove existing subscription first
|
|
191
|
+
this.subscriptions.delete(this.getKey(serverName, sub.uri));
|
|
192
|
+
// Resubscribe
|
|
193
|
+
const result = await this.subscribe(serverName, sub.uri);
|
|
194
|
+
results.push({ uri: sub.uri, result });
|
|
195
|
+
}
|
|
196
|
+
return results;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Unsubscribe from all resources on a server
|
|
200
|
+
* Called during server disconnection
|
|
201
|
+
*
|
|
202
|
+
* @param serverName - Server to unsubscribe from
|
|
203
|
+
*/
|
|
204
|
+
unsubscribeAllForServer(serverName) {
|
|
205
|
+
const subs = this.getSubscriptionsForServer(serverName);
|
|
206
|
+
for (const sub of subs) {
|
|
207
|
+
this.subscriptions.delete(this.getKey(serverName, sub.uri));
|
|
208
|
+
this.emit('unsubscribed', sub.uri, serverName);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Cleanup all subscriptions
|
|
213
|
+
*/
|
|
214
|
+
cleanupAll() {
|
|
215
|
+
for (const [key, sub] of this.subscriptions.entries()) {
|
|
216
|
+
this.subscriptions.delete(key);
|
|
217
|
+
this.emit('unsubscribed', sub.uri, sub.serverName);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
// Singleton instance
|
|
222
|
+
let subscriptionManager = null;
|
|
223
|
+
/**
|
|
224
|
+
* Get the singleton subscription manager instance
|
|
225
|
+
*/
|
|
226
|
+
export function getSubscriptionManager() {
|
|
227
|
+
if (!subscriptionManager) {
|
|
228
|
+
subscriptionManager = new SubscriptionManager();
|
|
229
|
+
}
|
|
230
|
+
return subscriptionManager;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Reset the subscription manager (for testing)
|
|
234
|
+
*/
|
|
235
|
+
export function resetSubscriptionManager() {
|
|
236
|
+
if (subscriptionManager) {
|
|
237
|
+
subscriptionManager.cleanupAll();
|
|
238
|
+
subscriptionManager.removeAllListeners();
|
|
239
|
+
}
|
|
240
|
+
subscriptionManager = null;
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=subscriptions.js.map
|