agent-orchestrator-mcp-server 0.5.0 → 0.6.0
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/package.json +1 -1
- package/shared/allowed-agent-roots.d.ts +2 -6
- package/shared/allowed-agent-roots.js +18 -27
- package/shared/orchestrator-client/orchestrator-client.js +8 -3
- package/shared/tools/get-session.js +3 -0
- package/shared/tools/start-session.d.ts +15 -19
- package/shared/tools/start-session.js +16 -24
- package/shared/types.d.ts +3 -0
package/package.json
CHANGED
|
@@ -26,15 +26,11 @@ export interface AgentRootValidationResult {
|
|
|
26
26
|
* Validate a start_session request against the allowed agent roots constraints.
|
|
27
27
|
*
|
|
28
28
|
* When ALLOWED_AGENT_ROOTS is set:
|
|
29
|
-
* -
|
|
29
|
+
* - agent_root must be provided and must be one of the allowed agent root names
|
|
30
30
|
* - mcp_servers must exactly match the default_mcp_servers of that agent root
|
|
31
31
|
* (no more, no less — any deviation is rejected)
|
|
32
32
|
*
|
|
33
|
-
* When multiple allowed agent roots share the same git_root, branch and subdirectory
|
|
34
|
-
* are used to disambiguate. This is critical for monorepo setups where multiple agent
|
|
35
|
-
* roots point to the same repository but different subdirectories.
|
|
36
|
-
*
|
|
37
33
|
* Returns { valid: true } if the request is allowed, or { valid: false, error: string } if not.
|
|
38
34
|
*/
|
|
39
|
-
export declare function validateAgentRootConstraints(allowedRoots: string[] | null, agentRoots: AgentRootInfo[],
|
|
35
|
+
export declare function validateAgentRootConstraints(allowedRoots: string[] | null, agentRoots: AgentRootInfo[], agentRootName?: string, mcpServers?: string[]): AgentRootValidationResult;
|
|
40
36
|
//# sourceMappingURL=allowed-agent-roots.d.ts.map
|
|
@@ -39,46 +39,37 @@ export function filterAgentRoots(agentRoots, allowedRoots) {
|
|
|
39
39
|
* Validate a start_session request against the allowed agent roots constraints.
|
|
40
40
|
*
|
|
41
41
|
* When ALLOWED_AGENT_ROOTS is set:
|
|
42
|
-
* -
|
|
42
|
+
* - agent_root must be provided and must be one of the allowed agent root names
|
|
43
43
|
* - mcp_servers must exactly match the default_mcp_servers of that agent root
|
|
44
44
|
* (no more, no less — any deviation is rejected)
|
|
45
45
|
*
|
|
46
|
-
* When multiple allowed agent roots share the same git_root, branch and subdirectory
|
|
47
|
-
* are used to disambiguate. This is critical for monorepo setups where multiple agent
|
|
48
|
-
* roots point to the same repository but different subdirectories.
|
|
49
|
-
*
|
|
50
46
|
* Returns { valid: true } if the request is allowed, or { valid: false, error: string } if not.
|
|
51
47
|
*/
|
|
52
|
-
export function validateAgentRootConstraints(allowedRoots, agentRoots,
|
|
48
|
+
export function validateAgentRootConstraints(allowedRoots, agentRoots, agentRootName, mcpServers) {
|
|
53
49
|
if (allowedRoots === null) {
|
|
54
50
|
return { valid: true };
|
|
55
51
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const branchMatch = !branch || (root.default_branch ?? 'main') === branch;
|
|
63
|
-
const subdirMatch = !subdirectory || root.default_subdirectory === subdirectory;
|
|
64
|
-
return branchMatch && subdirMatch;
|
|
65
|
-
});
|
|
52
|
+
if (!agentRootName) {
|
|
53
|
+
return {
|
|
54
|
+
valid: false,
|
|
55
|
+
error: `ALLOWED_AGENT_ROOTS is set — agent_root is required. ` +
|
|
56
|
+
`Allowed agent roots: ${allowedRoots.join(', ')}`,
|
|
57
|
+
};
|
|
66
58
|
}
|
|
67
|
-
|
|
68
|
-
|
|
59
|
+
if (!allowedRoots.includes(agentRootName)) {
|
|
60
|
+
return {
|
|
61
|
+
valid: false,
|
|
62
|
+
error: `ALLOWED_AGENT_ROOTS is set — agent_root "${agentRootName}" is not permitted. ` +
|
|
63
|
+
`Allowed agent roots: ${allowedRoots.join(', ')}`,
|
|
64
|
+
};
|
|
69
65
|
}
|
|
66
|
+
// Find the matching agent root config to validate mcp_servers
|
|
67
|
+
const matchingRoot = agentRoots.find((root) => root.name === agentRootName);
|
|
70
68
|
if (!matchingRoot) {
|
|
71
|
-
const allowedNames = allowedRoots.join(', ');
|
|
72
|
-
const allowedGitRoots = agentRoots
|
|
73
|
-
.filter((root) => allowedRoots.includes(root.name))
|
|
74
|
-
.map((root) => root.git_root);
|
|
75
69
|
return {
|
|
76
70
|
valid: false,
|
|
77
|
-
error: `
|
|
78
|
-
`
|
|
79
|
-
(allowedGitRoots.length > 0
|
|
80
|
-
? `Allowed git_root values: ${allowedGitRoots.join(', ')}`
|
|
81
|
-
: 'No matching agent roots found in configuration.'),
|
|
71
|
+
error: `Agent root "${agentRootName}" is in the allowed list but was not found in the configuration. ` +
|
|
72
|
+
`Available agent roots: ${agentRoots.map((r) => r.name).join(', ')}`,
|
|
82
73
|
};
|
|
83
74
|
}
|
|
84
75
|
// Validate mcp_servers matches the default_mcp_servers exactly
|
|
@@ -178,9 +178,14 @@ export class AgentOrchestratorClient {
|
|
|
178
178
|
return response.session;
|
|
179
179
|
}
|
|
180
180
|
async createSession(data) {
|
|
181
|
-
// Remap `skills` to `catalog_skills`
|
|
182
|
-
|
|
183
|
-
const
|
|
181
|
+
// Remap `skills` to `catalog_skills` and `plugins` to `catalog_plugins`
|
|
182
|
+
// for the API (Rails strong params expects `catalog_skills`/`catalog_plugins`)
|
|
183
|
+
const { skills, plugins, ...rest } = data;
|
|
184
|
+
const body = {
|
|
185
|
+
...rest,
|
|
186
|
+
...(skills !== undefined && { catalog_skills: skills }),
|
|
187
|
+
...(plugins !== undefined && { catalog_plugins: plugins }),
|
|
188
|
+
};
|
|
184
189
|
const response = await this.request('POST', '/sessions', body);
|
|
185
190
|
return response.session;
|
|
186
191
|
}
|
|
@@ -77,6 +77,9 @@ function formatSessionDetails(session, includeTranscript) {
|
|
|
77
77
|
if (session.catalog_skills && session.catalog_skills.length > 0) {
|
|
78
78
|
lines.push(`- **Skills:** ${session.catalog_skills.join(', ')}`);
|
|
79
79
|
}
|
|
80
|
+
if (session.catalog_plugins && session.catalog_plugins.length > 0) {
|
|
81
|
+
lines.push(`- **Plugins:** ${session.catalog_plugins.join(', ')}`);
|
|
82
|
+
}
|
|
80
83
|
if (session.prompt) {
|
|
81
84
|
lines.push('');
|
|
82
85
|
lines.push('### Current Prompt');
|
|
@@ -4,43 +4,40 @@ import type { IAgentOrchestratorClient } from '../orchestrator-client/orchestrat
|
|
|
4
4
|
export declare const StartSessionSchema: z.ZodObject<{
|
|
5
5
|
agent_type: z.ZodOptional<z.ZodString>;
|
|
6
6
|
prompt: z.ZodOptional<z.ZodString>;
|
|
7
|
-
|
|
8
|
-
branch: z.ZodOptional<z.ZodString>;
|
|
9
|
-
subdirectory: z.ZodOptional<z.ZodString>;
|
|
7
|
+
agent_root: z.ZodOptional<z.ZodString>;
|
|
10
8
|
title: z.ZodOptional<z.ZodString>;
|
|
11
9
|
slug: z.ZodOptional<z.ZodString>;
|
|
12
10
|
stop_condition: z.ZodOptional<z.ZodString>;
|
|
13
11
|
execution_provider: z.ZodOptional<z.ZodEnum<["local_filesystem", "remote_sandbox"]>>;
|
|
14
12
|
mcp_servers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
15
13
|
skills: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
14
|
+
plugins: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
16
15
|
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
17
16
|
custom_metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
18
17
|
}, "strip", z.ZodTypeAny, {
|
|
19
18
|
agent_type?: string | undefined;
|
|
20
19
|
skills?: string[] | undefined;
|
|
20
|
+
plugins?: string[] | undefined;
|
|
21
21
|
prompt?: string | undefined;
|
|
22
|
-
git_root?: string | undefined;
|
|
23
|
-
branch?: string | undefined;
|
|
24
|
-
subdirectory?: string | undefined;
|
|
25
22
|
title?: string | undefined;
|
|
26
23
|
slug?: string | undefined;
|
|
27
24
|
stop_condition?: string | undefined;
|
|
28
25
|
execution_provider?: "local_filesystem" | "remote_sandbox" | undefined;
|
|
29
26
|
mcp_servers?: string[] | undefined;
|
|
27
|
+
agent_root?: string | undefined;
|
|
30
28
|
config?: Record<string, unknown> | undefined;
|
|
31
29
|
custom_metadata?: Record<string, unknown> | undefined;
|
|
32
30
|
}, {
|
|
33
31
|
agent_type?: string | undefined;
|
|
34
32
|
skills?: string[] | undefined;
|
|
33
|
+
plugins?: string[] | undefined;
|
|
35
34
|
prompt?: string | undefined;
|
|
36
|
-
git_root?: string | undefined;
|
|
37
|
-
branch?: string | undefined;
|
|
38
|
-
subdirectory?: string | undefined;
|
|
39
35
|
title?: string | undefined;
|
|
40
36
|
slug?: string | undefined;
|
|
41
37
|
stop_condition?: string | undefined;
|
|
42
38
|
execution_provider?: "local_filesystem" | "remote_sandbox" | undefined;
|
|
43
39
|
mcp_servers?: string[] | undefined;
|
|
40
|
+
agent_root?: string | undefined;
|
|
44
41
|
config?: Record<string, unknown> | undefined;
|
|
45
42
|
custom_metadata?: Record<string, unknown> | undefined;
|
|
46
43
|
}>;
|
|
@@ -58,17 +55,9 @@ export declare function startSessionTool(_server: Server, clientFactory: () => I
|
|
|
58
55
|
type: string;
|
|
59
56
|
description: "Initial prompt for the agent. If provided, the agent job is automatically queued. Omit for a clone-only session.";
|
|
60
57
|
};
|
|
61
|
-
|
|
58
|
+
agent_root: {
|
|
62
59
|
type: string;
|
|
63
|
-
description: "
|
|
64
|
-
};
|
|
65
|
-
branch: {
|
|
66
|
-
type: string;
|
|
67
|
-
description: "Git branch to work on. Default: \"main\"";
|
|
68
|
-
};
|
|
69
|
-
subdirectory: {
|
|
70
|
-
type: string;
|
|
71
|
-
description: string;
|
|
60
|
+
description: "Agent root name from get_configs. The API resolves git_root, branch, subdirectory, default_model, and other defaults from the agent root configuration. Always pass this so the session inherits the correct repository, model, and settings.";
|
|
72
61
|
};
|
|
73
62
|
title: {
|
|
74
63
|
type: string;
|
|
@@ -101,6 +90,13 @@ export declare function startSessionTool(_server: Server, clientFactory: () => I
|
|
|
101
90
|
};
|
|
102
91
|
description: "List of skill names to enable for this session. Always include the agent root's default_skills from get_configs as the starting point — omitting skills means the session gets none. Add extras as needed; removing a default should be rare and intentional. Example: [\"discovery-classify\", \"publish-and-pr\"]";
|
|
103
92
|
};
|
|
93
|
+
plugins: {
|
|
94
|
+
type: string;
|
|
95
|
+
items: {
|
|
96
|
+
type: string;
|
|
97
|
+
};
|
|
98
|
+
description: "List of plugin names to enable for this session. Plugins extend agent capabilities with additional integrations. Example: [\"my-plugin\"]";
|
|
99
|
+
};
|
|
104
100
|
config: {
|
|
105
101
|
type: string;
|
|
106
102
|
description: "Additional configuration as a JSON object.";
|
|
@@ -4,14 +4,7 @@ import { getConfigsCache, setConfigsCache } from '../cache/configs-cache.js';
|
|
|
4
4
|
const PARAM_DESCRIPTIONS = {
|
|
5
5
|
agent_type: 'Agent type for the session. Currently only "claude_code" is supported. Default: "claude_code"',
|
|
6
6
|
prompt: 'Initial prompt for the agent. If provided, the agent job is automatically queued. Omit for a clone-only session.',
|
|
7
|
-
|
|
8
|
-
branch: 'Git branch to work on. Default: "main"',
|
|
9
|
-
subdirectory: 'Subdirectory within the repository to use as the agent working directory. ' +
|
|
10
|
-
'This should match a preconfigured agent root default_subdirectory from get_configs — it defines ' +
|
|
11
|
-
'the root scope for the agent session. Do NOT use this to point at internal package directories ' +
|
|
12
|
-
'(e.g. "experimental/gcs" in a monorepo) as this blinds the agent to root-level configuration ' +
|
|
13
|
-
'like CLAUDE.md, build scripts, CI workflows, and monorepo tooling. If no agent root defines ' +
|
|
14
|
-
'a default_subdirectory, leave this unset.',
|
|
7
|
+
agent_root: 'Agent root name from get_configs. The API resolves git_root, branch, subdirectory, default_model, and other defaults from the agent root configuration. Always pass this so the session inherits the correct repository, model, and settings.',
|
|
15
8
|
title: 'STRONGLY RECOMMENDED: Always set a title — treat it as effectively required. ' +
|
|
16
9
|
'The title appears in the AO web UI and push notifications, making sessions identifiable at a glance. ' +
|
|
17
10
|
'Compose a short, descriptive title (under 70 characters) that captures what the session is doing ' +
|
|
@@ -22,15 +15,14 @@ const PARAM_DESCRIPTIONS = {
|
|
|
22
15
|
execution_provider: 'Execution environment. Options: "local_filesystem" (runs locally), "remote_sandbox" (runs in isolated sandbox). Default: "local_filesystem"',
|
|
23
16
|
mcp_servers: 'List of MCP server names to enable for this session. Example: ["github-development", "slack"]',
|
|
24
17
|
skills: 'List of skill names to enable for this session. Always include the agent root\'s default_skills from get_configs as the starting point — omitting skills means the session gets none. Add extras as needed; removing a default should be rare and intentional. Example: ["discovery-classify", "publish-and-pr"]',
|
|
18
|
+
plugins: 'List of plugin names to enable for this session. Plugins extend agent capabilities with additional integrations. Example: ["my-plugin"]',
|
|
25
19
|
config: 'Additional configuration as a JSON object.',
|
|
26
20
|
custom_metadata: 'User-defined metadata as a JSON object. Useful for tracking tickets, projects, etc.',
|
|
27
21
|
};
|
|
28
22
|
export const StartSessionSchema = z.object({
|
|
29
23
|
agent_type: z.string().optional().describe(PARAM_DESCRIPTIONS.agent_type),
|
|
30
24
|
prompt: z.string().optional().describe(PARAM_DESCRIPTIONS.prompt),
|
|
31
|
-
|
|
32
|
-
branch: z.string().optional().describe(PARAM_DESCRIPTIONS.branch),
|
|
33
|
-
subdirectory: z.string().optional().describe(PARAM_DESCRIPTIONS.subdirectory),
|
|
25
|
+
agent_root: z.string().optional().describe(PARAM_DESCRIPTIONS.agent_root),
|
|
34
26
|
title: z.string().optional().describe(PARAM_DESCRIPTIONS.title),
|
|
35
27
|
slug: z.string().optional().describe(PARAM_DESCRIPTIONS.slug),
|
|
36
28
|
stop_condition: z.string().optional().describe(PARAM_DESCRIPTIONS.stop_condition),
|
|
@@ -40,12 +32,13 @@ export const StartSessionSchema = z.object({
|
|
|
40
32
|
.describe(PARAM_DESCRIPTIONS.execution_provider),
|
|
41
33
|
mcp_servers: z.array(z.string()).optional().describe(PARAM_DESCRIPTIONS.mcp_servers),
|
|
42
34
|
skills: z.array(z.string()).optional().describe(PARAM_DESCRIPTIONS.skills),
|
|
35
|
+
plugins: z.array(z.string()).optional().describe(PARAM_DESCRIPTIONS.plugins),
|
|
43
36
|
config: z.record(z.unknown()).optional().describe(PARAM_DESCRIPTIONS.config),
|
|
44
37
|
custom_metadata: z.record(z.unknown()).optional().describe(PARAM_DESCRIPTIONS.custom_metadata),
|
|
45
38
|
});
|
|
46
39
|
const TOOL_DESCRIPTION = `Start a new agent session in the Agent Orchestrator.
|
|
47
40
|
|
|
48
|
-
**IMPORTANT:** Before starting a session, call get_configs to discover available MCP servers, stop conditions, and
|
|
41
|
+
**IMPORTANT:** Before starting a session, call get_configs to discover available agent roots, MCP servers, stop conditions, and their defaults.
|
|
49
42
|
|
|
50
43
|
**Returns:** The created session with its ID, status, and configuration.
|
|
51
44
|
|
|
@@ -53,7 +46,9 @@ const TOOL_DESCRIPTION = `Start a new agent session in the Agent Orchestrator.
|
|
|
53
46
|
- If a prompt is provided, the agent job is automatically queued to start
|
|
54
47
|
- If no prompt is provided, creates a clone-only session that can be started later with action_session
|
|
55
48
|
|
|
56
|
-
**
|
|
49
|
+
**Agent Roots:** Use \`agent_root\` to specify which preconfigured agent root to use. The API resolves git_root, branch, subdirectory, default_model, and other defaults from the agent root configuration.
|
|
50
|
+
|
|
51
|
+
**Defaults from Agent Roots:** The agent root defines \`default_mcp_servers\`, \`default_skills\`, and optionally a \`default_stop_condition\`. Omitting \`mcp_servers\` or \`skills\` means the session gets NONE — there is no automatic fallback to defaults.
|
|
57
52
|
|
|
58
53
|
- **MCP servers:** Start with \`default_mcp_servers\`. Drop servers the task doesn't need (least-privilege). Add extras when the task requires tools beyond the defaults. When \`ALLOWED_AGENT_ROOTS\` is active, you cannot add servers beyond the defaults.
|
|
59
54
|
- **Skills:** Start with \`default_skills\`. You can freely add skills beyond the defaults. Removing a default skill should be rare and intentional — only when you have a specific reason, like replacing a skill with a more capable variant that covers the same ground. Skills are lightweight text files with no blast radius, so keeping all defaults costs nothing.
|
|
@@ -78,17 +73,9 @@ export function startSessionTool(_server, clientFactory) {
|
|
|
78
73
|
type: 'string',
|
|
79
74
|
description: PARAM_DESCRIPTIONS.prompt,
|
|
80
75
|
},
|
|
81
|
-
|
|
82
|
-
type: 'string',
|
|
83
|
-
description: PARAM_DESCRIPTIONS.git_root,
|
|
84
|
-
},
|
|
85
|
-
branch: {
|
|
86
|
-
type: 'string',
|
|
87
|
-
description: PARAM_DESCRIPTIONS.branch,
|
|
88
|
-
},
|
|
89
|
-
subdirectory: {
|
|
76
|
+
agent_root: {
|
|
90
77
|
type: 'string',
|
|
91
|
-
description: PARAM_DESCRIPTIONS.
|
|
78
|
+
description: PARAM_DESCRIPTIONS.agent_root,
|
|
92
79
|
},
|
|
93
80
|
title: {
|
|
94
81
|
type: 'string',
|
|
@@ -117,6 +104,11 @@ export function startSessionTool(_server, clientFactory) {
|
|
|
117
104
|
items: { type: 'string' },
|
|
118
105
|
description: PARAM_DESCRIPTIONS.skills,
|
|
119
106
|
},
|
|
107
|
+
plugins: {
|
|
108
|
+
type: 'array',
|
|
109
|
+
items: { type: 'string' },
|
|
110
|
+
description: PARAM_DESCRIPTIONS.plugins,
|
|
111
|
+
},
|
|
120
112
|
config: {
|
|
121
113
|
type: 'object',
|
|
122
114
|
description: PARAM_DESCRIPTIONS.config,
|
|
@@ -141,7 +133,7 @@ export function startSessionTool(_server, clientFactory) {
|
|
|
141
133
|
configs = await client.getConfigs();
|
|
142
134
|
setConfigsCache(configs);
|
|
143
135
|
}
|
|
144
|
-
const validation = validateAgentRootConstraints(allowedRoots, configs.agent_roots, validatedArgs.
|
|
136
|
+
const validation = validateAgentRootConstraints(allowedRoots, configs.agent_roots, validatedArgs.agent_root, validatedArgs.mcp_servers);
|
|
145
137
|
if (!validation.valid) {
|
|
146
138
|
return {
|
|
147
139
|
content: [{ type: 'text', text: `Error starting session: ${validation.error}` }],
|
package/shared/types.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export interface Session {
|
|
|
24
24
|
stop_condition: string | null;
|
|
25
25
|
mcp_servers: string[];
|
|
26
26
|
catalog_skills?: string[];
|
|
27
|
+
catalog_plugins?: string[];
|
|
27
28
|
config: Record<string, unknown>;
|
|
28
29
|
metadata: Record<string, unknown>;
|
|
29
30
|
custom_metadata: Record<string, unknown>;
|
|
@@ -145,6 +146,8 @@ export interface CreateSessionRequest {
|
|
|
145
146
|
execution_provider?: string;
|
|
146
147
|
mcp_servers?: string[];
|
|
147
148
|
skills?: string[];
|
|
149
|
+
plugins?: string[];
|
|
150
|
+
agent_root?: string;
|
|
148
151
|
config?: Record<string, unknown>;
|
|
149
152
|
custom_metadata?: Record<string, unknown>;
|
|
150
153
|
}
|