sub-agents-mcp 0.14.1 → 0.14.2
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/dist/agents/AgentManager.d.ts +16 -0
- package/dist/agents/AgentManager.d.ts.map +1 -1
- package/dist/agents/AgentManager.js +68 -43
- package/dist/agents/AgentManager.js.map +1 -1
- package/dist/agents/AgentName.d.ts +15 -0
- package/dist/agents/AgentName.d.ts.map +1 -0
- package/dist/agents/AgentName.js +40 -0
- package/dist/agents/AgentName.js.map +1 -0
- package/dist/config/ServerConfig.d.ts.map +1 -1
- package/dist/config/ServerConfig.js +101 -70
- package/dist/config/ServerConfig.js.map +1 -1
- package/dist/execution/AgentExecutor.d.ts +27 -3
- package/dist/execution/AgentExecutor.d.ts.map +1 -1
- package/dist/execution/AgentExecutor.js +328 -196
- package/dist/execution/AgentExecutor.js.map +1 -1
- package/dist/execution/StreamProcessor.d.ts.map +1 -1
- package/dist/execution/StreamProcessor.js +17 -16
- package/dist/execution/StreamProcessor.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/resources/AgentResources.d.ts.map +1 -1
- package/dist/resources/AgentResources.js +2 -8
- package/dist/resources/AgentResources.js.map +1 -1
- package/dist/server/McpServer.d.ts.map +1 -1
- package/dist/server/McpServer.js +40 -21
- package/dist/server/McpServer.js.map +1 -1
- package/dist/session/SessionManager.d.ts +11 -1
- package/dist/session/SessionManager.d.ts.map +1 -1
- package/dist/session/SessionManager.js +118 -28
- package/dist/session/SessionManager.js.map +1 -1
- package/dist/tools/RunAgentTool.d.ts +32 -9
- package/dist/tools/RunAgentTool.d.ts.map +1 -1
- package/dist/tools/RunAgentTool.js +281 -190
- package/dist/tools/RunAgentTool.js.map +1 -1
- package/dist/types/ExecutionParams.d.ts +0 -1
- package/dist/types/ExecutionParams.d.ts.map +1 -1
- package/dist/types/SessionData.d.ts +6 -1
- package/dist/types/SessionData.d.ts.map +1 -1
- package/dist/utils/ErrorHandler.d.ts +14 -2
- package/dist/utils/ErrorHandler.d.ts.map +1 -1
- package/dist/utils/ErrorHandler.js +40 -9
- package/dist/utils/ErrorHandler.js.map +1 -1
- package/dist/utils/Logger.d.ts.map +1 -1
- package/dist/utils/Logger.js +3 -2
- package/dist/utils/Logger.js.map +1 -1
- package/package.json +10 -14
|
@@ -4,9 +4,25 @@ export declare class AgentManager {
|
|
|
4
4
|
private config;
|
|
5
5
|
private logger;
|
|
6
6
|
constructor(config: ServerConfig);
|
|
7
|
+
/** Definition files found on disk but unusable, keyed by file name. */
|
|
8
|
+
private readonly skippedDefinitions;
|
|
9
|
+
/**
|
|
10
|
+
* Definition files that were discovered but cannot be exposed, with the reason.
|
|
11
|
+
* Surfaced to the caller so "the file is there but the agent is missing" is
|
|
12
|
+
* explainable without reading the server log.
|
|
13
|
+
*/
|
|
14
|
+
getSkippedDefinitions(): {
|
|
15
|
+
file: string;
|
|
16
|
+
reason: string;
|
|
17
|
+
}[];
|
|
7
18
|
getAgent(name: string): Promise<AgentDefinition | undefined>;
|
|
8
19
|
listAgents(): Promise<AgentDefinition[]>;
|
|
9
20
|
refreshAgents(): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Resolves an agent file to its real path, returning undefined when the file
|
|
23
|
+
* cannot be resolved. Throws when the resolved path escapes the agents directory.
|
|
24
|
+
*/
|
|
25
|
+
private resolveAgentFilePath;
|
|
10
26
|
private loadAgentsFromDirectory;
|
|
11
27
|
private loadAgentFromFile;
|
|
12
28
|
private isWithinDirectory;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentManager.d.ts","sourceRoot":"","sources":["../../src/agents/AgentManager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"AgentManager.d.ts","sourceRoot":"","sources":["../../src/agents/AgentManager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAqBlE,qBAAa,YAAY;IAGX,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,MAAM,CAAQ;gBAEF,MAAM,EAAE,YAAY;IAIxC,uEAAuE;IACvE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA4B;IAE/D;;;;OAIG;IACH,qBAAqB,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE;IAIrD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IAU5D,UAAU,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAKxC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAIpC;;;OAGG;YACW,oBAAoB;YAwBpB,uBAAuB;YAoFvB,iBAAiB;IAsC/B,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,kBAAkB;CAe3B"}
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { Logger as LoggerClass } from '../utils/Logger.js';
|
|
4
|
+
import { agentNameProblem, suggestAgentName } from './AgentName.js';
|
|
5
|
+
/** Sorts agent definition files by name, preferring `.md` over `.txt` on ties. */
|
|
6
|
+
function compareAgentFiles(left, right) {
|
|
7
|
+
const leftName = left.replace(/\.(md|txt)$/, '');
|
|
8
|
+
const rightName = right.replace(/\.(md|txt)$/, '');
|
|
9
|
+
const nameOrder = leftName.localeCompare(rightName);
|
|
10
|
+
if (nameOrder !== 0) {
|
|
11
|
+
return nameOrder;
|
|
12
|
+
}
|
|
13
|
+
if (left.endsWith('.md') && right.endsWith('.txt')) {
|
|
14
|
+
return -1;
|
|
15
|
+
}
|
|
16
|
+
if (left.endsWith('.txt') && right.endsWith('.md')) {
|
|
17
|
+
return 1;
|
|
18
|
+
}
|
|
19
|
+
return left.localeCompare(right);
|
|
20
|
+
}
|
|
4
21
|
export class AgentManager {
|
|
5
22
|
config;
|
|
6
23
|
logger;
|
|
@@ -8,28 +25,20 @@ export class AgentManager {
|
|
|
8
25
|
this.config = config;
|
|
9
26
|
this.logger = new LoggerClass(config.logLevel);
|
|
10
27
|
}
|
|
28
|
+
/** Definition files found on disk but unusable, keyed by file name. */
|
|
29
|
+
skippedDefinitions = new Map();
|
|
30
|
+
/**
|
|
31
|
+
* Definition files that were discovered but cannot be exposed, with the reason.
|
|
32
|
+
* Surfaced to the caller so "the file is there but the agent is missing" is
|
|
33
|
+
* explainable without reading the server log.
|
|
34
|
+
*/
|
|
35
|
+
getSkippedDefinitions() {
|
|
36
|
+
return Array.from(this.skippedDefinitions, ([file, reason]) => ({ file, reason }));
|
|
37
|
+
}
|
|
11
38
|
async getAgent(name) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (name.trim().length === 0) {
|
|
16
|
-
throw new Error('Invalid agent name: empty agent name not allowed');
|
|
17
|
-
}
|
|
18
|
-
if (name.length > 255) {
|
|
19
|
-
throw new Error('Invalid agent name: too long agent name');
|
|
20
|
-
}
|
|
21
|
-
const invalidChars = /[<>:"/\\|?*;`$()&|\s]/;
|
|
22
|
-
if (invalidChars.test(name)) {
|
|
23
|
-
throw new Error('Invalid agent name: forbidden characters detected');
|
|
24
|
-
}
|
|
25
|
-
for (let i = 0; i < name.length; i++) {
|
|
26
|
-
const charCode = name.charCodeAt(i);
|
|
27
|
-
if ((charCode >= 0 && charCode <= 31) || charCode === 127) {
|
|
28
|
-
throw new Error('Invalid agent name: forbidden characters detected');
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
if (name.includes('..') || name.includes('./') || name.includes('.\\')) {
|
|
32
|
-
throw new Error('Invalid agent name: path traversal attempt detected');
|
|
39
|
+
const problem = agentNameProblem(name);
|
|
40
|
+
if (problem) {
|
|
41
|
+
throw new Error(`Invalid agent name: ${problem}`);
|
|
33
42
|
}
|
|
34
43
|
const agents = await this.loadAgentsFromDirectory();
|
|
35
44
|
return agents.get(name);
|
|
@@ -41,6 +50,24 @@ export class AgentManager {
|
|
|
41
50
|
async refreshAgents() {
|
|
42
51
|
await this.loadAgentsFromDirectory();
|
|
43
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Resolves an agent file to its real path, returning undefined when the file
|
|
55
|
+
* cannot be resolved. Throws when the resolved path escapes the agents directory.
|
|
56
|
+
*/
|
|
57
|
+
async resolveAgentFilePath(agentsDir, filePath, file) {
|
|
58
|
+
let resolvedFilePath;
|
|
59
|
+
try {
|
|
60
|
+
resolvedFilePath = await fs.promises.realpath(filePath);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
this.logger.error('Failed to resolve agent definition file', error instanceof Error ? error : undefined, { filePath });
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
if (!this.isWithinDirectory(agentsDir, resolvedFilePath)) {
|
|
67
|
+
throw new Error(`Agent definition resolves outside the configured agents directory: ${file}`);
|
|
68
|
+
}
|
|
69
|
+
return resolvedFilePath;
|
|
70
|
+
}
|
|
44
71
|
async loadAgentsFromDirectory() {
|
|
45
72
|
try {
|
|
46
73
|
const agentsDir = await fs.promises.realpath(path.resolve(this.config.agentsDir));
|
|
@@ -48,27 +75,30 @@ export class AgentManager {
|
|
|
48
75
|
const files = await fs.promises.readdir(agentsDir);
|
|
49
76
|
const agentFiles = files
|
|
50
77
|
.filter((file) => file.endsWith('.md') || file.endsWith('.txt'))
|
|
51
|
-
.sort(
|
|
52
|
-
const leftName = left.replace(/\.(md|txt)$/, '');
|
|
53
|
-
const rightName = right.replace(/\.(md|txt)$/, '');
|
|
54
|
-
const nameOrder = leftName.localeCompare(rightName);
|
|
55
|
-
if (nameOrder !== 0)
|
|
56
|
-
return nameOrder;
|
|
57
|
-
if (left.endsWith('.md') && right.endsWith('.txt'))
|
|
58
|
-
return -1;
|
|
59
|
-
if (left.endsWith('.txt') && right.endsWith('.md'))
|
|
60
|
-
return 1;
|
|
61
|
-
return left.localeCompare(right);
|
|
62
|
-
});
|
|
78
|
+
.sort(compareAgentFiles);
|
|
63
79
|
this.logger.info('Agent definition files discovered', {
|
|
64
80
|
totalFiles: files.length,
|
|
65
81
|
agentFiles: agentFiles.length,
|
|
66
82
|
files: agentFiles,
|
|
67
83
|
});
|
|
68
84
|
const agents = new Map();
|
|
85
|
+
this.skippedDefinitions.clear();
|
|
69
86
|
for (const file of agentFiles) {
|
|
70
87
|
const filePath = path.join(agentsDir, file);
|
|
71
88
|
const agentName = file.replace(/\.(md|txt)$/, '');
|
|
89
|
+
// Applying the run_agent naming rule here is what stops a definition from
|
|
90
|
+
// being listed under a name that would then be rejected on execution.
|
|
91
|
+
const nameProblem = agentNameProblem(agentName);
|
|
92
|
+
if (nameProblem) {
|
|
93
|
+
const extension = file.slice(agentName.length);
|
|
94
|
+
this.skippedDefinitions.set(file, nameProblem);
|
|
95
|
+
this.logger.warn('Agent definition skipped: unusable name', {
|
|
96
|
+
file,
|
|
97
|
+
reason: nameProblem,
|
|
98
|
+
suggestedFileName: `${suggestAgentName(agentName)}${extension}`,
|
|
99
|
+
});
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
72
102
|
if (agents.has(agentName)) {
|
|
73
103
|
this.logger.warn('Duplicate agent definition ignored', {
|
|
74
104
|
name: agentName,
|
|
@@ -77,17 +107,10 @@ export class AgentManager {
|
|
|
77
107
|
});
|
|
78
108
|
continue;
|
|
79
109
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
resolvedFilePath = await fs.promises.realpath(filePath);
|
|
83
|
-
}
|
|
84
|
-
catch (error) {
|
|
85
|
-
this.logger.error('Failed to resolve agent definition file', error instanceof Error ? error : undefined, { filePath });
|
|
110
|
+
const resolvedFilePath = await this.resolveAgentFilePath(agentsDir, filePath, file);
|
|
111
|
+
if (!resolvedFilePath) {
|
|
86
112
|
continue;
|
|
87
113
|
}
|
|
88
|
-
if (!this.isWithinDirectory(agentsDir, resolvedFilePath)) {
|
|
89
|
-
throw new Error(`Agent definition resolves outside the configured agents directory: ${file}`);
|
|
90
|
-
}
|
|
91
114
|
const agent = await this.loadAgentFromFile(resolvedFilePath, agentName);
|
|
92
115
|
if (agent) {
|
|
93
116
|
agents.set(agentName, agent);
|
|
@@ -109,7 +132,9 @@ export class AgentManager {
|
|
|
109
132
|
if (error instanceof Error && error.message.startsWith('Agent definition resolves outside')) {
|
|
110
133
|
throw error;
|
|
111
134
|
}
|
|
112
|
-
throw new Error(`Failed to load agents from directory: ${this.config.agentsDir}
|
|
135
|
+
throw new Error(`Failed to load agents from directory: ${this.config.agentsDir}`, {
|
|
136
|
+
cause: error,
|
|
137
|
+
});
|
|
113
138
|
}
|
|
114
139
|
}
|
|
115
140
|
async loadAgentFromFile(resolvedFilePath, agentName) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentManager.js","sourceRoot":"","sources":["../../src/agents/AgentManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAG5B,OAAO,EAAe,MAAM,IAAI,WAAW,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"AgentManager.js","sourceRoot":"","sources":["../../src/agents/AgentManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one naming rule shared by agent discovery, `getAgent`, the `run_agent`
|
|
3
|
+
* tool input, and resource URIs. Keeping a single definition is what prevents an
|
|
4
|
+
* agent from being listed under a name that cannot then be executed.
|
|
5
|
+
*/
|
|
6
|
+
export declare const AGENT_NAME_PATTERN: RegExp;
|
|
7
|
+
/**
|
|
8
|
+
* Returns why `name` is unusable as an agent name, or undefined when it is
|
|
9
|
+
* valid. The text is written to be shown to the user verbatim.
|
|
10
|
+
*/
|
|
11
|
+
export declare function agentNameProblem(name: unknown): string | undefined;
|
|
12
|
+
export declare function isValidAgentName(name: unknown): name is string;
|
|
13
|
+
/** Best-effort rename suggestion shown alongside a skipped definition file. */
|
|
14
|
+
export declare function suggestAgentName(name: string): string;
|
|
15
|
+
//# sourceMappingURL=AgentName.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentName.d.ts","sourceRoot":"","sources":["../../src/agents/AgentName.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,QAAqB,CAAA;AAIpD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAclE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,MAAM,CAE9D;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQrD"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one naming rule shared by agent discovery, `getAgent`, the `run_agent`
|
|
3
|
+
* tool input, and resource URIs. Keeping a single definition is what prevents an
|
|
4
|
+
* agent from being listed under a name that cannot then be executed.
|
|
5
|
+
*/
|
|
6
|
+
export const AGENT_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
7
|
+
const MAX_AGENT_NAME_LENGTH = 100;
|
|
8
|
+
/**
|
|
9
|
+
* Returns why `name` is unusable as an agent name, or undefined when it is
|
|
10
|
+
* valid. The text is written to be shown to the user verbatim.
|
|
11
|
+
*/
|
|
12
|
+
export function agentNameProblem(name) {
|
|
13
|
+
if (typeof name !== 'string' || name.length === 0) {
|
|
14
|
+
return 'an agent name is required';
|
|
15
|
+
}
|
|
16
|
+
if (name.trim().length === 0) {
|
|
17
|
+
return 'an agent name cannot be blank';
|
|
18
|
+
}
|
|
19
|
+
if (name.length > MAX_AGENT_NAME_LENGTH) {
|
|
20
|
+
return `an agent name may be at most ${MAX_AGENT_NAME_LENGTH} characters (got ${name.length})`;
|
|
21
|
+
}
|
|
22
|
+
if (!AGENT_NAME_PATTERN.test(name)) {
|
|
23
|
+
return 'an agent name may only contain letters, digits, hyphens and underscores';
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
export function isValidAgentName(name) {
|
|
28
|
+
return agentNameProblem(name) === undefined;
|
|
29
|
+
}
|
|
30
|
+
/** Best-effort rename suggestion shown alongside a skipped definition file. */
|
|
31
|
+
export function suggestAgentName(name) {
|
|
32
|
+
const suggestion = name
|
|
33
|
+
.normalize('NFKD')
|
|
34
|
+
.replace(/[^a-zA-Z0-9_-]+/g, '-')
|
|
35
|
+
.replace(/-{2,}/g, '-')
|
|
36
|
+
.replace(/^-+|-+$/g, '')
|
|
37
|
+
.slice(0, MAX_AGENT_NAME_LENGTH);
|
|
38
|
+
return suggestion.length > 0 ? suggestion : 'agent';
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=AgentName.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentName.js","sourceRoot":"","sources":["../../src/agents/AgentName.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,kBAAkB,CAAA;AAEpD,MAAM,qBAAqB,GAAG,GAAG,CAAA;AAEjC;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,OAAO,2BAA2B,CAAA;IACpC,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,+BAA+B,CAAA;IACxC,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,GAAG,qBAAqB,EAAE,CAAC;QACxC,OAAO,gCAAgC,qBAAqB,oBAAoB,IAAI,CAAC,MAAM,GAAG,CAAA;IAChG,CAAC;IACD,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,OAAO,yEAAyE,CAAA;IAClF,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,OAAO,gBAAgB,CAAC,IAAI,CAAC,KAAK,SAAS,CAAA;AAC7C,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,UAAU,GAAG,IAAI;SACpB,SAAS,CAAC,MAAM,CAAC;SACjB,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC;SAChC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAA;IAClC,OAAO,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAA;AACrD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerConfig.d.ts","sourceRoot":"","sources":["../../src/config/ServerConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,SAAS,EAKf,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAA0B,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"ServerConfig.d.ts","sourceRoot":"","sources":["../../src/config/ServerConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,SAAS,EAKf,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAA0B,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAmH1E,qBAAa,YAAY;IACvB,SAAgB,UAAU,EAAE,MAAM,CAAA;IAElC,SAAgB,aAAa,EAAE,MAAM,CAAA;IAErC,SAAgB,SAAS,EAAE,MAAM,CAAA;IAEjC,SAAgB,SAAS,EAAE,SAAS,CAAA;IAEpC,SAAgB,eAAe,EAAE,eAAe,CAAA;IAEhD,SAAgB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IAE9C,SAAgB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;IAE/C,SAAgB,QAAQ,EAAE,QAAQ,CAAA;IAElC,SAAgB,kBAAkB,EAAE,MAAM,CAAA;IAE1C,SAAgB,cAAc,EAAE,OAAO,CAAA;IAEvC,SAAgB,UAAU,EAAE,MAAM,CAAA;IAElC,SAAgB,oBAAoB,EAAE,MAAM,CAAA;IAE5C,SAAgB,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAA;IAEtD,SAAgB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;IAEhD,SAAgB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAE7C,SAAgB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;;CA0B/C"}
|
|
@@ -1,5 +1,98 @@
|
|
|
1
1
|
import { AGENT_EFFORT_SUPPORTED_TYPES, AGENT_PERMISSIONS, AGENT_TYPES, DEFAULT_AGENT_PERMISSION, isAgentPermission, isAgentType, supportsAgentEffort, } from '../execution/AgentExecutor.js';
|
|
2
2
|
import { isLogLevel, LOG_LEVELS } from '../utils/Logger.js';
|
|
3
|
+
const DEFAULT_EXECUTION_TIMEOUT_MS = 300000;
|
|
4
|
+
const DEFAULT_SESSION_RETENTION_DAYS = 1;
|
|
5
|
+
const MISSING_AGENTS_DIR_ERROR = 'AGENTS_DIR environment variable is required.\n' +
|
|
6
|
+
'Please set it to an absolute path in your MCP configuration.\n' +
|
|
7
|
+
'Example for Cursor IDE (~/.cursor/mcp.json):\n' +
|
|
8
|
+
' "env": {\n' +
|
|
9
|
+
' "AGENTS_DIR": "/Users/username/projects/my-app/agents"\n' +
|
|
10
|
+
' }\n' +
|
|
11
|
+
'Example for Claude Desktop:\n' +
|
|
12
|
+
' "env": {\n' +
|
|
13
|
+
' "AGENTS_DIR": "/Users/username/claude-agents"\n' +
|
|
14
|
+
' }';
|
|
15
|
+
function readEnv(name) {
|
|
16
|
+
const value = process.env[name]?.trim();
|
|
17
|
+
return value ? value : undefined;
|
|
18
|
+
}
|
|
19
|
+
function resolveAgentsDir() {
|
|
20
|
+
const agentsDir = process.env['AGENTS_DIR'];
|
|
21
|
+
if (!agentsDir) {
|
|
22
|
+
throw new Error(MISSING_AGENTS_DIR_ERROR);
|
|
23
|
+
}
|
|
24
|
+
return agentsDir;
|
|
25
|
+
}
|
|
26
|
+
function resolveAgentType() {
|
|
27
|
+
const value = readEnv('AGENT_TYPE');
|
|
28
|
+
if (!value) {
|
|
29
|
+
throw new Error('AGENT_TYPE environment variable is required. ' +
|
|
30
|
+
`Set it to one of: ${AGENT_TYPES.join(', ')} in your MCP configuration, ` +
|
|
31
|
+
'then restart or reconnect the MCP server.');
|
|
32
|
+
}
|
|
33
|
+
if (!isAgentType(value)) {
|
|
34
|
+
throw new Error(`Invalid AGENT_TYPE: "${value}". Must be one of: ${AGENT_TYPES.join(', ')}.`);
|
|
35
|
+
}
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
function resolveAgentPermission() {
|
|
39
|
+
const value = readEnv('AGENT_PERMISSION');
|
|
40
|
+
if (!value) {
|
|
41
|
+
return DEFAULT_AGENT_PERMISSION;
|
|
42
|
+
}
|
|
43
|
+
if (!isAgentPermission(value)) {
|
|
44
|
+
throw new Error(`Invalid AGENT_PERMISSION: "${value}". Must be one of: ${AGENT_PERMISSIONS.join(', ')}.`);
|
|
45
|
+
}
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
function resolveAgentEffort(agentType) {
|
|
49
|
+
const value = readEnv('AGENT_EFFORT');
|
|
50
|
+
if (value && !supportsAgentEffort(agentType)) {
|
|
51
|
+
throw new Error(`AGENT_EFFORT is not supported for AGENT_TYPE="${agentType}". ` +
|
|
52
|
+
`Supported types: ${AGENT_EFFORT_SUPPORTED_TYPES.join(', ')}.`);
|
|
53
|
+
}
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
function resolveLogLevel() {
|
|
57
|
+
const value = readEnv('LOG_LEVEL');
|
|
58
|
+
if (!value) {
|
|
59
|
+
return 'info';
|
|
60
|
+
}
|
|
61
|
+
if (!isLogLevel(value)) {
|
|
62
|
+
throw new Error(`Invalid LOG_LEVEL: "${value}". Must be one of: ${LOG_LEVELS.join(', ')}.`);
|
|
63
|
+
}
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Parses a duration in milliseconds. `Number.parseInt` alone would read "5min"
|
|
68
|
+
* as 5, silently turning every execution into an instant timeout, so the whole
|
|
69
|
+
* value has to be a positive integer.
|
|
70
|
+
*/
|
|
71
|
+
function resolveExecutionTimeoutMs() {
|
|
72
|
+
const value = readEnv('EXECUTION_TIMEOUT_MS');
|
|
73
|
+
if (!value) {
|
|
74
|
+
return DEFAULT_EXECUTION_TIMEOUT_MS;
|
|
75
|
+
}
|
|
76
|
+
// Restricted to plain decimal digits: "1e6" and "0x10" are valid to Number()
|
|
77
|
+
// but are not what anyone means to write in a millisecond setting.
|
|
78
|
+
const parsed = /^\d+$/.test(value) ? Number(value) : Number.NaN;
|
|
79
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
80
|
+
throw new Error(`Invalid EXECUTION_TIMEOUT_MS: "${value}". ` +
|
|
81
|
+
'Expected a positive whole number of milliseconds. ' +
|
|
82
|
+
`"${value}" is not one, and a value like "5min" would be read as 5 milliseconds. ` +
|
|
83
|
+
`Use ${DEFAULT_EXECUTION_TIMEOUT_MS} for 5 minutes. ` +
|
|
84
|
+
'Update "env" in your MCP configuration and restart the server.');
|
|
85
|
+
}
|
|
86
|
+
return parsed;
|
|
87
|
+
}
|
|
88
|
+
function resolveSessionRetentionDays() {
|
|
89
|
+
const value = readEnv('SESSION_RETENTION_DAYS');
|
|
90
|
+
if (!value) {
|
|
91
|
+
return DEFAULT_SESSION_RETENTION_DAYS;
|
|
92
|
+
}
|
|
93
|
+
const parsed = Number.parseInt(value, 10);
|
|
94
|
+
return Number.isNaN(parsed) || parsed <= 0 ? DEFAULT_SESSION_RETENTION_DAYS : parsed;
|
|
95
|
+
}
|
|
3
96
|
export class ServerConfig {
|
|
4
97
|
serverName;
|
|
5
98
|
serverVersion;
|
|
@@ -20,78 +113,16 @@ export class ServerConfig {
|
|
|
20
113
|
constructor() {
|
|
21
114
|
this.serverName = process.env['SERVER_NAME'] || 'sub-agents-mcp';
|
|
22
115
|
this.serverVersion = process.env['SERVER_VERSION'] || '0.1.0';
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
' }\n' +
|
|
31
|
-
'Example for Claude Desktop:\n' +
|
|
32
|
-
' "env": {\n' +
|
|
33
|
-
' "AGENTS_DIR": "/Users/username/claude-agents"\n' +
|
|
34
|
-
' }');
|
|
35
|
-
}
|
|
36
|
-
this.agentsDir = agentsDir;
|
|
37
|
-
const agentTypeEnv = process.env['AGENT_TYPE']?.trim();
|
|
38
|
-
if (!agentTypeEnv) {
|
|
39
|
-
throw new Error('AGENT_TYPE environment variable is required. ' +
|
|
40
|
-
`Set it to one of: ${AGENT_TYPES.join(', ')} in your MCP configuration, ` +
|
|
41
|
-
'then restart or reconnect the MCP server.');
|
|
42
|
-
}
|
|
43
|
-
else if (isAgentType(agentTypeEnv)) {
|
|
44
|
-
this.agentType = agentTypeEnv;
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
throw new Error(`Invalid AGENT_TYPE: "${agentTypeEnv}". Must be one of: ${AGENT_TYPES.join(', ')}.`);
|
|
48
|
-
}
|
|
49
|
-
const agentPermissionEnv = process.env['AGENT_PERMISSION']?.trim();
|
|
50
|
-
if (!agentPermissionEnv) {
|
|
51
|
-
this.agentPermission = DEFAULT_AGENT_PERMISSION;
|
|
52
|
-
}
|
|
53
|
-
else if (isAgentPermission(agentPermissionEnv)) {
|
|
54
|
-
this.agentPermission = agentPermissionEnv;
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
throw new Error(`Invalid AGENT_PERMISSION: "${agentPermissionEnv}". Must be one of: ${AGENT_PERMISSIONS.join(', ')}.`);
|
|
58
|
-
}
|
|
59
|
-
const agentModelEnv = process.env['AGENT_MODEL']?.trim();
|
|
60
|
-
this.agentModel = agentModelEnv || undefined;
|
|
61
|
-
const agentEffortEnv = process.env['AGENT_EFFORT']?.trim();
|
|
62
|
-
this.agentEffort = agentEffortEnv || undefined;
|
|
63
|
-
if (this.agentEffort && !supportsAgentEffort(this.agentType)) {
|
|
64
|
-
throw new Error(`AGENT_EFFORT is not supported for AGENT_TYPE="${this.agentType}". ` +
|
|
65
|
-
`Supported types: ${AGENT_EFFORT_SUPPORTED_TYPES.join(', ')}.`);
|
|
66
|
-
}
|
|
67
|
-
const logLevelEnv = process.env['LOG_LEVEL']?.trim();
|
|
68
|
-
if (!logLevelEnv) {
|
|
69
|
-
this.logLevel = 'info';
|
|
70
|
-
}
|
|
71
|
-
else if (isLogLevel(logLevelEnv)) {
|
|
72
|
-
this.logLevel = logLevelEnv;
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
throw new Error(`Invalid LOG_LEVEL: "${logLevelEnv}". Must be one of: ${LOG_LEVELS.join(', ')}.`);
|
|
76
|
-
}
|
|
77
|
-
const timeoutEnv = process.env['EXECUTION_TIMEOUT_MS'];
|
|
78
|
-
if (timeoutEnv?.trim()) {
|
|
79
|
-
const parsedTimeout = Number.parseInt(timeoutEnv, 10);
|
|
80
|
-
this.executionTimeoutMs = Number.isNaN(parsedTimeout) ? 300000 : parsedTimeout;
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
this.executionTimeoutMs = 300000;
|
|
84
|
-
}
|
|
116
|
+
this.agentsDir = resolveAgentsDir();
|
|
117
|
+
this.agentType = resolveAgentType();
|
|
118
|
+
this.agentPermission = resolveAgentPermission();
|
|
119
|
+
this.agentModel = readEnv('AGENT_MODEL');
|
|
120
|
+
this.agentEffort = resolveAgentEffort(this.agentType);
|
|
121
|
+
this.logLevel = resolveLogLevel();
|
|
122
|
+
this.executionTimeoutMs = resolveExecutionTimeoutMs();
|
|
85
123
|
this.sessionEnabled = process.env['SESSION_ENABLED'] === 'true';
|
|
86
124
|
this.sessionDir = process.env['SESSION_DIR'] || '.mcp-sessions';
|
|
87
|
-
|
|
88
|
-
if (retentionDaysEnv?.trim()) {
|
|
89
|
-
const parsedDays = Number.parseInt(retentionDaysEnv, 10);
|
|
90
|
-
this.sessionRetentionDays = Number.isNaN(parsedDays) || parsedDays <= 0 ? 1 : parsedDays;
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
this.sessionRetentionDays = 1;
|
|
94
|
-
}
|
|
125
|
+
this.sessionRetentionDays = resolveSessionRetentionDays();
|
|
95
126
|
this.agentsSettingsPath = process.env['AGENTS_SETTINGS_PATH'] || undefined;
|
|
96
127
|
// Cursor API key: prefer CURSOR_API_KEY, fall back to CLI_API_KEY for backward compatibility
|
|
97
128
|
const cursorApiKeyEnv = process.env['CURSOR_API_KEY'] || process.env['CLI_API_KEY'];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerConfig.js","sourceRoot":"","sources":["../../src/config/ServerConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,iBAAiB,EACjB,WAAW,EAGX,wBAAwB,EACxB,iBAAiB,EACjB,WAAW,EACX,mBAAmB,GACpB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAiB,MAAM,oBAAoB,CAAA;AAE1E,MAAM,
|
|
1
|
+
{"version":3,"file":"ServerConfig.js","sourceRoot":"","sources":["../../src/config/ServerConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { ExecutionParams } from '../types/ExecutionParams.js';
|
|
2
2
|
import { Logger } from '../utils/Logger.js';
|
|
3
|
+
/**
|
|
4
|
+
* A machine-readable reason for failures whose remedy is not obvious from the
|
|
5
|
+
* exit code alone, so callers can give the user an actionable next step.
|
|
6
|
+
*/
|
|
7
|
+
type ExecutionFailureReason = 'argv_too_long';
|
|
3
8
|
export interface AgentExecutionResult {
|
|
4
9
|
stdout: string;
|
|
5
10
|
stderr: string;
|
|
@@ -7,6 +12,7 @@ export interface AgentExecutionResult {
|
|
|
7
12
|
executionTime: number;
|
|
8
13
|
hasResult?: boolean;
|
|
9
14
|
resultJson?: unknown;
|
|
15
|
+
failureReason?: ExecutionFailureReason;
|
|
10
16
|
}
|
|
11
17
|
export interface ExecutionConfig {
|
|
12
18
|
executionTimeout: number;
|
|
@@ -31,11 +37,28 @@ export type AgentPermission = (typeof AGENT_PERMISSIONS)[number];
|
|
|
31
37
|
export declare function isAgentPermission(value: unknown): value is AgentPermission;
|
|
32
38
|
export declare const DEFAULT_AGENT_PERMISSION: AgentPermission;
|
|
33
39
|
export declare function createExecutionConfig(agentType: AgentType, overrides?: Partial<Omit<ExecutionConfig, 'agentType'>>): ExecutionConfig;
|
|
40
|
+
export interface SpawnOutcome {
|
|
41
|
+
stdout: string;
|
|
42
|
+
stderr: string;
|
|
43
|
+
exitCode: number;
|
|
44
|
+
hasResult?: boolean;
|
|
45
|
+
resultJson?: unknown;
|
|
46
|
+
failureReason?: ExecutionFailureReason;
|
|
47
|
+
}
|
|
34
48
|
export declare class AgentExecutor {
|
|
35
49
|
private readonly config;
|
|
36
50
|
private readonly logger;
|
|
37
51
|
constructor(config: ExecutionConfig, logger?: Logger);
|
|
38
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Guards against untrusted callers that bypass the declared parameter type
|
|
54
|
+
* (for example MCP requests deserialized as `unknown`).
|
|
55
|
+
*/
|
|
56
|
+
private assertExecutableParams;
|
|
57
|
+
/** Sessions still running, so shutdown does not orphan agent processes. */
|
|
58
|
+
private readonly activeSessions;
|
|
59
|
+
/** Terminates every agent process this executor still has running. */
|
|
60
|
+
terminateAll(): void;
|
|
61
|
+
executeAgent(params: ExecutionParams, signal?: AbortSignal): Promise<AgentExecutionResult>;
|
|
39
62
|
private buildCommandArgs;
|
|
40
63
|
private buildSettingsPathEnv;
|
|
41
64
|
private permissionFlags;
|
|
@@ -54,9 +77,10 @@ export declare class AgentExecutor {
|
|
|
54
77
|
private buildOpenCodeArgs;
|
|
55
78
|
private buildSpawnEnv;
|
|
56
79
|
private prepareSpawnEnvironment;
|
|
57
|
-
private errorCode;
|
|
58
80
|
private executeWithSpawn;
|
|
59
|
-
|
|
81
|
+
/** Runs a cleanup callback, logging rather than propagating its failures. */
|
|
82
|
+
private cleanupQuietly;
|
|
60
83
|
private generateRequestId;
|
|
61
84
|
}
|
|
85
|
+
export {};
|
|
62
86
|
//# sourceMappingURL=AgentExecutor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentExecutor.d.ts","sourceRoot":"","sources":["../../src/execution/AgentExecutor.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"AgentExecutor.d.ts","sourceRoot":"","sources":["../../src/execution/AgentExecutor.ts"],"names":[],"mappings":"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"}
|