agent-orchestrator-mcp-server 0.1.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/README.md +172 -0
- package/build/index.integration-with-mock.js +36 -0
- package/build/index.js +98 -0
- package/package.json +49 -0
- package/shared/index.d.ts +7 -0
- package/shared/index.js +8 -0
- package/shared/logging.d.ts +20 -0
- package/shared/logging.js +34 -0
- package/shared/orchestrator-client/orchestrator-client.d.ts +109 -0
- package/shared/orchestrator-client/orchestrator-client.integration-mock.d.ts +20 -0
- package/shared/orchestrator-client/orchestrator-client.integration-mock.js +373 -0
- package/shared/orchestrator-client/orchestrator-client.js +166 -0
- package/shared/resources.d.ts +3 -0
- package/shared/resources.js +67 -0
- package/shared/server.d.ts +31 -0
- package/shared/server.js +34 -0
- package/shared/tools/action-session.d.ts +55 -0
- package/shared/tools/action-session.js +182 -0
- package/shared/tools/get-session.d.ts +95 -0
- package/shared/tools/get-session.js +271 -0
- package/shared/tools/search-sessions.d.ts +92 -0
- package/shared/tools/search-sessions.js +201 -0
- package/shared/tools/start-session.d.ts +119 -0
- package/shared/tools/start-session.js +146 -0
- package/shared/tools.d.ts +29 -0
- package/shared/tools.js +88 -0
- package/shared/types.d.ts +155 -0
- package/shared/types.js +4 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import type { IAgentOrchestratorClient } from '../orchestrator-client/orchestrator-client.js';
|
|
4
|
+
export declare const SearchSessionsSchema: z.ZodObject<{
|
|
5
|
+
id: z.ZodOptional<z.ZodNumber>;
|
|
6
|
+
query: z.ZodOptional<z.ZodString>;
|
|
7
|
+
search_contents: z.ZodOptional<z.ZodBoolean>;
|
|
8
|
+
status: z.ZodOptional<z.ZodEnum<["waiting", "running", "needs_input", "failed", "archived"]>>;
|
|
9
|
+
agent_type: z.ZodOptional<z.ZodString>;
|
|
10
|
+
show_archived: z.ZodOptional<z.ZodBoolean>;
|
|
11
|
+
page: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
per_page: z.ZodOptional<z.ZodNumber>;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
status?: "waiting" | "running" | "needs_input" | "failed" | "archived" | undefined;
|
|
15
|
+
agent_type?: string | undefined;
|
|
16
|
+
show_archived?: boolean | undefined;
|
|
17
|
+
page?: number | undefined;
|
|
18
|
+
per_page?: number | undefined;
|
|
19
|
+
search_contents?: boolean | undefined;
|
|
20
|
+
id?: number | undefined;
|
|
21
|
+
query?: string | undefined;
|
|
22
|
+
}, {
|
|
23
|
+
status?: "waiting" | "running" | "needs_input" | "failed" | "archived" | undefined;
|
|
24
|
+
agent_type?: string | undefined;
|
|
25
|
+
show_archived?: boolean | undefined;
|
|
26
|
+
page?: number | undefined;
|
|
27
|
+
per_page?: number | undefined;
|
|
28
|
+
search_contents?: boolean | undefined;
|
|
29
|
+
id?: number | undefined;
|
|
30
|
+
query?: string | undefined;
|
|
31
|
+
}>;
|
|
32
|
+
export declare function searchSessionsTool(_server: Server, clientFactory: () => IAgentOrchestratorClient): {
|
|
33
|
+
name: string;
|
|
34
|
+
description: string;
|
|
35
|
+
inputSchema: {
|
|
36
|
+
type: "object";
|
|
37
|
+
properties: {
|
|
38
|
+
id: {
|
|
39
|
+
type: string;
|
|
40
|
+
description: "Get a specific session by ID. When provided, other filters are ignored.";
|
|
41
|
+
};
|
|
42
|
+
query: {
|
|
43
|
+
type: string;
|
|
44
|
+
maxLength: number;
|
|
45
|
+
description: "Search query to find sessions. Searches across title, metadata, and custom_metadata. Leave empty to list all sessions.";
|
|
46
|
+
};
|
|
47
|
+
search_contents: {
|
|
48
|
+
type: string;
|
|
49
|
+
description: "Also search within transcript contents. May be slow for sessions with large transcripts. Default: false";
|
|
50
|
+
};
|
|
51
|
+
status: {
|
|
52
|
+
type: string;
|
|
53
|
+
enum: string[];
|
|
54
|
+
description: "Filter results by status. Options: \"waiting\", \"running\", \"needs_input\", \"failed\", \"archived\"";
|
|
55
|
+
};
|
|
56
|
+
agent_type: {
|
|
57
|
+
type: string;
|
|
58
|
+
description: "Filter results by agent type.";
|
|
59
|
+
};
|
|
60
|
+
show_archived: {
|
|
61
|
+
type: string;
|
|
62
|
+
description: "Include archived sessions in results. Default: false";
|
|
63
|
+
};
|
|
64
|
+
page: {
|
|
65
|
+
type: string;
|
|
66
|
+
minimum: number;
|
|
67
|
+
description: "Page number for pagination. Default: 1";
|
|
68
|
+
};
|
|
69
|
+
per_page: {
|
|
70
|
+
type: string;
|
|
71
|
+
minimum: number;
|
|
72
|
+
maximum: number;
|
|
73
|
+
description: "Number of results per page (1-100). Default: 25";
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
required: never[];
|
|
77
|
+
};
|
|
78
|
+
handler: (args: unknown) => Promise<{
|
|
79
|
+
content: {
|
|
80
|
+
type: string;
|
|
81
|
+
text: string;
|
|
82
|
+
}[];
|
|
83
|
+
isError?: undefined;
|
|
84
|
+
} | {
|
|
85
|
+
content: {
|
|
86
|
+
type: string;
|
|
87
|
+
text: string;
|
|
88
|
+
}[];
|
|
89
|
+
isError: boolean;
|
|
90
|
+
}>;
|
|
91
|
+
};
|
|
92
|
+
//# sourceMappingURL=search-sessions.d.ts.map
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const PARAM_DESCRIPTIONS = {
|
|
3
|
+
id: 'Get a specific session by ID. When provided, other filters are ignored.',
|
|
4
|
+
query: 'Search query to find sessions. Searches across title, metadata, and custom_metadata. Leave empty to list all sessions.',
|
|
5
|
+
search_contents: 'Also search within transcript contents. May be slow for sessions with large transcripts. Default: false',
|
|
6
|
+
status: 'Filter results by status. Options: "waiting", "running", "needs_input", "failed", "archived"',
|
|
7
|
+
agent_type: 'Filter results by agent type.',
|
|
8
|
+
show_archived: 'Include archived sessions in results. Default: false',
|
|
9
|
+
page: 'Page number for pagination. Default: 1',
|
|
10
|
+
per_page: 'Number of results per page (1-100). Default: 25',
|
|
11
|
+
};
|
|
12
|
+
export const SearchSessionsSchema = z.object({
|
|
13
|
+
id: z.number().optional().describe(PARAM_DESCRIPTIONS.id),
|
|
14
|
+
query: z.string().max(1000).optional().describe(PARAM_DESCRIPTIONS.query),
|
|
15
|
+
search_contents: z.boolean().optional().describe(PARAM_DESCRIPTIONS.search_contents),
|
|
16
|
+
status: z
|
|
17
|
+
.enum(['waiting', 'running', 'needs_input', 'failed', 'archived'])
|
|
18
|
+
.optional()
|
|
19
|
+
.describe(PARAM_DESCRIPTIONS.status),
|
|
20
|
+
agent_type: z.string().optional().describe(PARAM_DESCRIPTIONS.agent_type),
|
|
21
|
+
show_archived: z.boolean().optional().describe(PARAM_DESCRIPTIONS.show_archived),
|
|
22
|
+
page: z.number().min(1).optional().describe(PARAM_DESCRIPTIONS.page),
|
|
23
|
+
per_page: z.number().min(1).max(100).optional().describe(PARAM_DESCRIPTIONS.per_page),
|
|
24
|
+
});
|
|
25
|
+
const TOOL_DESCRIPTION = `Search for agent sessions in the Agent Orchestrator.
|
|
26
|
+
|
|
27
|
+
**Use cases:**
|
|
28
|
+
- Find a specific session by ID (set id parameter)
|
|
29
|
+
- Search sessions by keyword in title/prompt (set query parameter)
|
|
30
|
+
- List all sessions with optional status filter
|
|
31
|
+
- Monitor sessions requiring attention (status: "needs_input")
|
|
32
|
+
|
|
33
|
+
**Returns:** A list of matching sessions with their status, configuration, and metadata.
|
|
34
|
+
|
|
35
|
+
**Session statuses:**
|
|
36
|
+
- waiting: Session created, waiting to start
|
|
37
|
+
- running: Agent is actively executing
|
|
38
|
+
- needs_input: Agent paused, waiting for user input
|
|
39
|
+
- failed: Session encountered an error
|
|
40
|
+
- archived: Session completed and archived`;
|
|
41
|
+
/** Maximum characters to display for prompt preview */
|
|
42
|
+
const MAX_PROMPT_DISPLAY_LENGTH = 100;
|
|
43
|
+
function formatSession(session) {
|
|
44
|
+
const lines = [
|
|
45
|
+
`### ${session.title} (ID: ${session.id})`,
|
|
46
|
+
'',
|
|
47
|
+
`- **Status:** ${session.status}`,
|
|
48
|
+
`- **Agent Type:** ${session.agent_type}`,
|
|
49
|
+
];
|
|
50
|
+
if (session.slug)
|
|
51
|
+
lines.push(`- **Slug:** ${session.slug}`);
|
|
52
|
+
if (session.git_root)
|
|
53
|
+
lines.push(`- **Repository:** ${session.git_root}`);
|
|
54
|
+
if (session.branch)
|
|
55
|
+
lines.push(`- **Branch:** ${session.branch}`);
|
|
56
|
+
if (session.prompt) {
|
|
57
|
+
const truncatedPrompt = session.prompt.length > MAX_PROMPT_DISPLAY_LENGTH
|
|
58
|
+
? session.prompt.slice(0, MAX_PROMPT_DISPLAY_LENGTH) + '...'
|
|
59
|
+
: session.prompt;
|
|
60
|
+
lines.push(`- **Prompt:** ${truncatedPrompt}`);
|
|
61
|
+
}
|
|
62
|
+
if (session.mcp_servers && session.mcp_servers.length > 0) {
|
|
63
|
+
lines.push(`- **MCP Servers:** ${session.mcp_servers.join(', ')}`);
|
|
64
|
+
}
|
|
65
|
+
lines.push(`- **Created:** ${session.created_at}`);
|
|
66
|
+
lines.push(`- **Updated:** ${session.updated_at}`);
|
|
67
|
+
return lines.join('\n');
|
|
68
|
+
}
|
|
69
|
+
export function searchSessionsTool(_server, clientFactory) {
|
|
70
|
+
return {
|
|
71
|
+
name: 'search_sessions',
|
|
72
|
+
description: TOOL_DESCRIPTION,
|
|
73
|
+
inputSchema: {
|
|
74
|
+
type: 'object',
|
|
75
|
+
properties: {
|
|
76
|
+
id: {
|
|
77
|
+
type: 'number',
|
|
78
|
+
description: PARAM_DESCRIPTIONS.id,
|
|
79
|
+
},
|
|
80
|
+
query: {
|
|
81
|
+
type: 'string',
|
|
82
|
+
maxLength: 1000,
|
|
83
|
+
description: PARAM_DESCRIPTIONS.query,
|
|
84
|
+
},
|
|
85
|
+
search_contents: {
|
|
86
|
+
type: 'boolean',
|
|
87
|
+
description: PARAM_DESCRIPTIONS.search_contents,
|
|
88
|
+
},
|
|
89
|
+
status: {
|
|
90
|
+
type: 'string',
|
|
91
|
+
enum: ['waiting', 'running', 'needs_input', 'failed', 'archived'],
|
|
92
|
+
description: PARAM_DESCRIPTIONS.status,
|
|
93
|
+
},
|
|
94
|
+
agent_type: {
|
|
95
|
+
type: 'string',
|
|
96
|
+
description: PARAM_DESCRIPTIONS.agent_type,
|
|
97
|
+
},
|
|
98
|
+
show_archived: {
|
|
99
|
+
type: 'boolean',
|
|
100
|
+
description: PARAM_DESCRIPTIONS.show_archived,
|
|
101
|
+
},
|
|
102
|
+
page: {
|
|
103
|
+
type: 'number',
|
|
104
|
+
minimum: 1,
|
|
105
|
+
description: PARAM_DESCRIPTIONS.page,
|
|
106
|
+
},
|
|
107
|
+
per_page: {
|
|
108
|
+
type: 'number',
|
|
109
|
+
minimum: 1,
|
|
110
|
+
maximum: 100,
|
|
111
|
+
description: PARAM_DESCRIPTIONS.per_page,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
required: [],
|
|
115
|
+
},
|
|
116
|
+
handler: async (args) => {
|
|
117
|
+
try {
|
|
118
|
+
const validatedArgs = SearchSessionsSchema.parse(args);
|
|
119
|
+
const client = clientFactory();
|
|
120
|
+
// If ID is provided, get that specific session
|
|
121
|
+
if (validatedArgs.id !== undefined) {
|
|
122
|
+
const session = await client.getSession(validatedArgs.id);
|
|
123
|
+
return {
|
|
124
|
+
content: [
|
|
125
|
+
{
|
|
126
|
+
type: 'text',
|
|
127
|
+
text: `## Session Found\n\n${formatSession(session)}`,
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
// Otherwise, search or list sessions
|
|
133
|
+
let sessions;
|
|
134
|
+
let pagination;
|
|
135
|
+
if (validatedArgs.query) {
|
|
136
|
+
// Use search endpoint
|
|
137
|
+
const response = await client.searchSessions(validatedArgs.query, {
|
|
138
|
+
search_contents: validatedArgs.search_contents,
|
|
139
|
+
status: validatedArgs.status,
|
|
140
|
+
agent_type: validatedArgs.agent_type,
|
|
141
|
+
show_archived: validatedArgs.show_archived,
|
|
142
|
+
page: validatedArgs.page,
|
|
143
|
+
per_page: validatedArgs.per_page,
|
|
144
|
+
});
|
|
145
|
+
sessions = response.sessions;
|
|
146
|
+
pagination = response.pagination;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
// Use list endpoint
|
|
150
|
+
const response = await client.listSessions({
|
|
151
|
+
status: validatedArgs.status,
|
|
152
|
+
agent_type: validatedArgs.agent_type,
|
|
153
|
+
show_archived: validatedArgs.show_archived,
|
|
154
|
+
page: validatedArgs.page,
|
|
155
|
+
per_page: validatedArgs.per_page,
|
|
156
|
+
});
|
|
157
|
+
sessions = response.sessions;
|
|
158
|
+
pagination = response.pagination;
|
|
159
|
+
}
|
|
160
|
+
if (sessions.length === 0) {
|
|
161
|
+
return {
|
|
162
|
+
content: [
|
|
163
|
+
{
|
|
164
|
+
type: 'text',
|
|
165
|
+
text: 'No sessions found matching the specified criteria.',
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
const lines = [
|
|
171
|
+
`## Agent Sessions`,
|
|
172
|
+
'',
|
|
173
|
+
`Found ${pagination.total_count} session(s) (page ${pagination.page} of ${pagination.total_pages}):`,
|
|
174
|
+
'',
|
|
175
|
+
];
|
|
176
|
+
sessions.forEach((session) => {
|
|
177
|
+
lines.push(formatSession(session));
|
|
178
|
+
lines.push('');
|
|
179
|
+
});
|
|
180
|
+
if (pagination.page < pagination.total_pages) {
|
|
181
|
+
lines.push('---');
|
|
182
|
+
lines.push(`*More sessions available. Use page=${pagination.page + 1} to see the next page.*`);
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
return {
|
|
190
|
+
content: [
|
|
191
|
+
{
|
|
192
|
+
type: 'text',
|
|
193
|
+
text: `Error searching sessions: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
isError: true,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import type { IAgentOrchestratorClient } from '../orchestrator-client/orchestrator-client.js';
|
|
4
|
+
export declare const StartSessionSchema: z.ZodObject<{
|
|
5
|
+
agent_type: z.ZodOptional<z.ZodString>;
|
|
6
|
+
prompt: z.ZodOptional<z.ZodString>;
|
|
7
|
+
git_root: z.ZodOptional<z.ZodString>;
|
|
8
|
+
branch: z.ZodOptional<z.ZodString>;
|
|
9
|
+
subdirectory: z.ZodOptional<z.ZodString>;
|
|
10
|
+
title: z.ZodOptional<z.ZodString>;
|
|
11
|
+
slug: z.ZodOptional<z.ZodString>;
|
|
12
|
+
stop_condition: z.ZodOptional<z.ZodString>;
|
|
13
|
+
execution_provider: z.ZodOptional<z.ZodEnum<["local_filesystem", "remote_sandbox"]>>;
|
|
14
|
+
mcp_servers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
15
|
+
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
16
|
+
custom_metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
17
|
+
}, "strip", z.ZodTypeAny, {
|
|
18
|
+
title?: string | undefined;
|
|
19
|
+
agent_type?: string | undefined;
|
|
20
|
+
prompt?: string | undefined;
|
|
21
|
+
git_root?: string | undefined;
|
|
22
|
+
branch?: string | undefined;
|
|
23
|
+
subdirectory?: string | undefined;
|
|
24
|
+
slug?: string | undefined;
|
|
25
|
+
stop_condition?: string | undefined;
|
|
26
|
+
execution_provider?: "local_filesystem" | "remote_sandbox" | undefined;
|
|
27
|
+
mcp_servers?: string[] | undefined;
|
|
28
|
+
config?: Record<string, unknown> | undefined;
|
|
29
|
+
custom_metadata?: Record<string, unknown> | undefined;
|
|
30
|
+
}, {
|
|
31
|
+
title?: string | undefined;
|
|
32
|
+
agent_type?: string | undefined;
|
|
33
|
+
prompt?: string | undefined;
|
|
34
|
+
git_root?: string | undefined;
|
|
35
|
+
branch?: string | undefined;
|
|
36
|
+
subdirectory?: string | undefined;
|
|
37
|
+
slug?: string | undefined;
|
|
38
|
+
stop_condition?: string | undefined;
|
|
39
|
+
execution_provider?: "local_filesystem" | "remote_sandbox" | undefined;
|
|
40
|
+
mcp_servers?: string[] | undefined;
|
|
41
|
+
config?: Record<string, unknown> | undefined;
|
|
42
|
+
custom_metadata?: Record<string, unknown> | undefined;
|
|
43
|
+
}>;
|
|
44
|
+
export declare function startSessionTool(_server: Server, clientFactory: () => IAgentOrchestratorClient): {
|
|
45
|
+
name: string;
|
|
46
|
+
description: string;
|
|
47
|
+
inputSchema: {
|
|
48
|
+
type: "object";
|
|
49
|
+
properties: {
|
|
50
|
+
agent_type: {
|
|
51
|
+
type: string;
|
|
52
|
+
description: "Agent type for the session. Currently only \"claude_code\" is supported. Default: \"claude_code\"";
|
|
53
|
+
};
|
|
54
|
+
prompt: {
|
|
55
|
+
type: string;
|
|
56
|
+
description: "Initial prompt for the agent. If provided, the agent job is automatically queued. Omit for a clone-only session.";
|
|
57
|
+
};
|
|
58
|
+
git_root: {
|
|
59
|
+
type: string;
|
|
60
|
+
description: "Repository URL or local path. Examples: \"https://github.com/example/repo.git\", \"/path/to/repo\"";
|
|
61
|
+
};
|
|
62
|
+
branch: {
|
|
63
|
+
type: string;
|
|
64
|
+
description: "Git branch to work on. Default: \"main\"";
|
|
65
|
+
};
|
|
66
|
+
subdirectory: {
|
|
67
|
+
type: string;
|
|
68
|
+
description: "Subdirectory within the repository to focus on.";
|
|
69
|
+
};
|
|
70
|
+
title: {
|
|
71
|
+
type: string;
|
|
72
|
+
description: "Display title for the session. Used for identification in the UI.";
|
|
73
|
+
};
|
|
74
|
+
slug: {
|
|
75
|
+
type: string;
|
|
76
|
+
description: "URL-friendly identifier for the session. Must be unique.";
|
|
77
|
+
};
|
|
78
|
+
stop_condition: {
|
|
79
|
+
type: string;
|
|
80
|
+
description: "Condition that determines when the agent should stop. Passed to the agent as context.";
|
|
81
|
+
};
|
|
82
|
+
execution_provider: {
|
|
83
|
+
type: string;
|
|
84
|
+
enum: string[];
|
|
85
|
+
description: "Execution environment. Options: \"local_filesystem\" (runs locally), \"remote_sandbox\" (runs in isolated sandbox). Default: \"local_filesystem\"";
|
|
86
|
+
};
|
|
87
|
+
mcp_servers: {
|
|
88
|
+
type: string;
|
|
89
|
+
items: {
|
|
90
|
+
type: string;
|
|
91
|
+
};
|
|
92
|
+
description: "List of MCP server names to enable for this session. Example: [\"github-development\", \"slack\"]";
|
|
93
|
+
};
|
|
94
|
+
config: {
|
|
95
|
+
type: string;
|
|
96
|
+
description: "Additional configuration as a JSON object.";
|
|
97
|
+
};
|
|
98
|
+
custom_metadata: {
|
|
99
|
+
type: string;
|
|
100
|
+
description: "User-defined metadata as a JSON object. Useful for tracking tickets, projects, etc.";
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
required: never[];
|
|
104
|
+
};
|
|
105
|
+
handler: (args: unknown) => Promise<{
|
|
106
|
+
content: {
|
|
107
|
+
type: string;
|
|
108
|
+
text: string;
|
|
109
|
+
}[];
|
|
110
|
+
isError?: undefined;
|
|
111
|
+
} | {
|
|
112
|
+
content: {
|
|
113
|
+
type: string;
|
|
114
|
+
text: string;
|
|
115
|
+
}[];
|
|
116
|
+
isError: boolean;
|
|
117
|
+
}>;
|
|
118
|
+
};
|
|
119
|
+
//# sourceMappingURL=start-session.d.ts.map
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const PARAM_DESCRIPTIONS = {
|
|
3
|
+
agent_type: 'Agent type for the session. Currently only "claude_code" is supported. Default: "claude_code"',
|
|
4
|
+
prompt: 'Initial prompt for the agent. If provided, the agent job is automatically queued. Omit for a clone-only session.',
|
|
5
|
+
git_root: 'Repository URL or local path. Examples: "https://github.com/example/repo.git", "/path/to/repo"',
|
|
6
|
+
branch: 'Git branch to work on. Default: "main"',
|
|
7
|
+
subdirectory: 'Subdirectory within the repository to focus on.',
|
|
8
|
+
title: 'Display title for the session. Used for identification in the UI.',
|
|
9
|
+
slug: 'URL-friendly identifier for the session. Must be unique.',
|
|
10
|
+
stop_condition: 'Condition that determines when the agent should stop. Passed to the agent as context.',
|
|
11
|
+
execution_provider: 'Execution environment. Options: "local_filesystem" (runs locally), "remote_sandbox" (runs in isolated sandbox). Default: "local_filesystem"',
|
|
12
|
+
mcp_servers: 'List of MCP server names to enable for this session. Example: ["github-development", "slack"]',
|
|
13
|
+
config: 'Additional configuration as a JSON object.',
|
|
14
|
+
custom_metadata: 'User-defined metadata as a JSON object. Useful for tracking tickets, projects, etc.',
|
|
15
|
+
};
|
|
16
|
+
export const StartSessionSchema = z.object({
|
|
17
|
+
agent_type: z.string().optional().describe(PARAM_DESCRIPTIONS.agent_type),
|
|
18
|
+
prompt: z.string().optional().describe(PARAM_DESCRIPTIONS.prompt),
|
|
19
|
+
git_root: z.string().optional().describe(PARAM_DESCRIPTIONS.git_root),
|
|
20
|
+
branch: z.string().optional().describe(PARAM_DESCRIPTIONS.branch),
|
|
21
|
+
subdirectory: z.string().optional().describe(PARAM_DESCRIPTIONS.subdirectory),
|
|
22
|
+
title: z.string().optional().describe(PARAM_DESCRIPTIONS.title),
|
|
23
|
+
slug: z.string().optional().describe(PARAM_DESCRIPTIONS.slug),
|
|
24
|
+
stop_condition: z.string().optional().describe(PARAM_DESCRIPTIONS.stop_condition),
|
|
25
|
+
execution_provider: z
|
|
26
|
+
.enum(['local_filesystem', 'remote_sandbox'])
|
|
27
|
+
.optional()
|
|
28
|
+
.describe(PARAM_DESCRIPTIONS.execution_provider),
|
|
29
|
+
mcp_servers: z.array(z.string()).optional().describe(PARAM_DESCRIPTIONS.mcp_servers),
|
|
30
|
+
config: z.record(z.unknown()).optional().describe(PARAM_DESCRIPTIONS.config),
|
|
31
|
+
custom_metadata: z.record(z.unknown()).optional().describe(PARAM_DESCRIPTIONS.custom_metadata),
|
|
32
|
+
});
|
|
33
|
+
const TOOL_DESCRIPTION = `Start a new agent session in the Agent Orchestrator.
|
|
34
|
+
|
|
35
|
+
**Returns:** The created session with its ID, status, and configuration.
|
|
36
|
+
|
|
37
|
+
**Behavior:**
|
|
38
|
+
- If a prompt is provided, the agent job is automatically queued to start
|
|
39
|
+
- If no prompt is provided, creates a clone-only session that can be started later with action_session
|
|
40
|
+
|
|
41
|
+
**Use cases:**
|
|
42
|
+
- Start a new agent task on a repository
|
|
43
|
+
- Create a session to work on a specific branch
|
|
44
|
+
- Set up an agent with specific MCP servers enabled
|
|
45
|
+
- Create a session with custom metadata for tracking`;
|
|
46
|
+
export function startSessionTool(_server, clientFactory) {
|
|
47
|
+
return {
|
|
48
|
+
name: 'start_session',
|
|
49
|
+
description: TOOL_DESCRIPTION,
|
|
50
|
+
inputSchema: {
|
|
51
|
+
type: 'object',
|
|
52
|
+
properties: {
|
|
53
|
+
agent_type: {
|
|
54
|
+
type: 'string',
|
|
55
|
+
description: PARAM_DESCRIPTIONS.agent_type,
|
|
56
|
+
},
|
|
57
|
+
prompt: {
|
|
58
|
+
type: 'string',
|
|
59
|
+
description: PARAM_DESCRIPTIONS.prompt,
|
|
60
|
+
},
|
|
61
|
+
git_root: {
|
|
62
|
+
type: 'string',
|
|
63
|
+
description: PARAM_DESCRIPTIONS.git_root,
|
|
64
|
+
},
|
|
65
|
+
branch: {
|
|
66
|
+
type: 'string',
|
|
67
|
+
description: PARAM_DESCRIPTIONS.branch,
|
|
68
|
+
},
|
|
69
|
+
subdirectory: {
|
|
70
|
+
type: 'string',
|
|
71
|
+
description: PARAM_DESCRIPTIONS.subdirectory,
|
|
72
|
+
},
|
|
73
|
+
title: {
|
|
74
|
+
type: 'string',
|
|
75
|
+
description: PARAM_DESCRIPTIONS.title,
|
|
76
|
+
},
|
|
77
|
+
slug: {
|
|
78
|
+
type: 'string',
|
|
79
|
+
description: PARAM_DESCRIPTIONS.slug,
|
|
80
|
+
},
|
|
81
|
+
stop_condition: {
|
|
82
|
+
type: 'string',
|
|
83
|
+
description: PARAM_DESCRIPTIONS.stop_condition,
|
|
84
|
+
},
|
|
85
|
+
execution_provider: {
|
|
86
|
+
type: 'string',
|
|
87
|
+
enum: ['local_filesystem', 'remote_sandbox'],
|
|
88
|
+
description: PARAM_DESCRIPTIONS.execution_provider,
|
|
89
|
+
},
|
|
90
|
+
mcp_servers: {
|
|
91
|
+
type: 'array',
|
|
92
|
+
items: { type: 'string' },
|
|
93
|
+
description: PARAM_DESCRIPTIONS.mcp_servers,
|
|
94
|
+
},
|
|
95
|
+
config: {
|
|
96
|
+
type: 'object',
|
|
97
|
+
description: PARAM_DESCRIPTIONS.config,
|
|
98
|
+
},
|
|
99
|
+
custom_metadata: {
|
|
100
|
+
type: 'object',
|
|
101
|
+
description: PARAM_DESCRIPTIONS.custom_metadata,
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
required: [],
|
|
105
|
+
},
|
|
106
|
+
handler: async (args) => {
|
|
107
|
+
try {
|
|
108
|
+
const validatedArgs = StartSessionSchema.parse(args);
|
|
109
|
+
const client = clientFactory();
|
|
110
|
+
const session = await client.createSession(validatedArgs);
|
|
111
|
+
const lines = [
|
|
112
|
+
`## Session Started Successfully`,
|
|
113
|
+
'',
|
|
114
|
+
`- **ID:** ${session.id}`,
|
|
115
|
+
`- **Title:** ${session.title}`,
|
|
116
|
+
`- **Status:** ${session.status}`,
|
|
117
|
+
];
|
|
118
|
+
if (session.slug)
|
|
119
|
+
lines.push(`- **Slug:** ${session.slug}`);
|
|
120
|
+
if (session.job_id) {
|
|
121
|
+
lines.push(`- **Job ID:** ${session.job_id}`);
|
|
122
|
+
lines.push('');
|
|
123
|
+
lines.push('*The agent job has been queued and will start shortly.*');
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
lines.push('');
|
|
127
|
+
lines.push('*No prompt was provided. Use action_session with "follow_up" or "restart" action to start the agent.*');
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
return {
|
|
135
|
+
content: [
|
|
136
|
+
{
|
|
137
|
+
type: 'text',
|
|
138
|
+
text: `Error starting session: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
isError: true,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import { ClientFactory } from './server.js';
|
|
3
|
+
/**
|
|
4
|
+
* Available tool groups for agent-orchestrator:
|
|
5
|
+
* - 'readonly': Read-only operations (search_sessions, get_session)
|
|
6
|
+
* - 'write': Write operations (start_session, action_session)
|
|
7
|
+
* - 'admin': Administrative operations (reserved for future use)
|
|
8
|
+
*/
|
|
9
|
+
export type ToolGroup = 'readonly' | 'write' | 'admin';
|
|
10
|
+
/**
|
|
11
|
+
* Parse enabled tool groups from environment variable.
|
|
12
|
+
* @param enabledGroupsParam - Comma-separated list of groups (e.g., "readonly,write")
|
|
13
|
+
* @returns Array of enabled tool groups
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseEnabledToolGroups(enabledGroupsParam?: string): ToolGroup[];
|
|
16
|
+
/**
|
|
17
|
+
* Creates a function to register all tools with the server.
|
|
18
|
+
* This pattern uses individual tool files for better modularity and testability.
|
|
19
|
+
*
|
|
20
|
+
* Each tool is defined in its own file under the `tools/` directory and follows
|
|
21
|
+
* a factory pattern that accepts the server and clientFactory as parameters.
|
|
22
|
+
*
|
|
23
|
+
* @param clientFactory - Factory function that creates client instances
|
|
24
|
+
* @param enabledGroups - Optional array of enabled tool groups (defaults to all)
|
|
25
|
+
* @returns Function that registers all tools with a server
|
|
26
|
+
*/
|
|
27
|
+
export declare function createRegisterTools(clientFactory: ClientFactory, enabledGroups?: ToolGroup[]): (server: Server) => void;
|
|
28
|
+
export declare function registerTools(server: Server): void;
|
|
29
|
+
//# sourceMappingURL=tools.d.ts.map
|
package/shared/tools.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
// Simplified tool surface - 4 tools
|
|
3
|
+
import { searchSessionsTool } from './tools/search-sessions.js';
|
|
4
|
+
import { startSessionTool } from './tools/start-session.js';
|
|
5
|
+
import { getSessionTool } from './tools/get-session.js';
|
|
6
|
+
import { actionSessionTool } from './tools/action-session.js';
|
|
7
|
+
const ALL_TOOL_GROUPS = ['readonly', 'write', 'admin'];
|
|
8
|
+
/**
|
|
9
|
+
* Parse enabled tool groups from environment variable.
|
|
10
|
+
* @param enabledGroupsParam - Comma-separated list of groups (e.g., "readonly,write")
|
|
11
|
+
* @returns Array of enabled tool groups
|
|
12
|
+
*/
|
|
13
|
+
export function parseEnabledToolGroups(enabledGroupsParam) {
|
|
14
|
+
if (!enabledGroupsParam) {
|
|
15
|
+
return ALL_TOOL_GROUPS; // All groups enabled by default
|
|
16
|
+
}
|
|
17
|
+
const requestedGroups = enabledGroupsParam.split(',').map((g) => g.trim().toLowerCase());
|
|
18
|
+
const validGroups = requestedGroups.filter((g) => ALL_TOOL_GROUPS.includes(g));
|
|
19
|
+
if (validGroups.length === 0) {
|
|
20
|
+
console.error(`Warning: No valid tool groups found in "${enabledGroupsParam}". Valid groups: ${ALL_TOOL_GROUPS.join(', ')}`);
|
|
21
|
+
return ALL_TOOL_GROUPS;
|
|
22
|
+
}
|
|
23
|
+
return validGroups;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* All available tools with their group assignments.
|
|
27
|
+
* Tools can belong to multiple groups.
|
|
28
|
+
*
|
|
29
|
+
* Simplified tool surface:
|
|
30
|
+
* - search_sessions: Search/list/get sessions by ID
|
|
31
|
+
* - start_session: Create a new session
|
|
32
|
+
* - get_session: Get detailed session info with optional logs/transcripts
|
|
33
|
+
* - action_session: Perform actions (follow_up, pause, restart, archive, unarchive)
|
|
34
|
+
*/
|
|
35
|
+
const ALL_TOOLS = [
|
|
36
|
+
// Read operations
|
|
37
|
+
{ factory: searchSessionsTool, groups: ['readonly', 'write', 'admin'] },
|
|
38
|
+
{ factory: getSessionTool, groups: ['readonly', 'write', 'admin'] },
|
|
39
|
+
// Write operations
|
|
40
|
+
{ factory: startSessionTool, groups: ['write', 'admin'] },
|
|
41
|
+
{ factory: actionSessionTool, groups: ['write', 'admin'] },
|
|
42
|
+
];
|
|
43
|
+
/**
|
|
44
|
+
* Creates a function to register all tools with the server.
|
|
45
|
+
* This pattern uses individual tool files for better modularity and testability.
|
|
46
|
+
*
|
|
47
|
+
* Each tool is defined in its own file under the `tools/` directory and follows
|
|
48
|
+
* a factory pattern that accepts the server and clientFactory as parameters.
|
|
49
|
+
*
|
|
50
|
+
* @param clientFactory - Factory function that creates client instances
|
|
51
|
+
* @param enabledGroups - Optional array of enabled tool groups (defaults to all)
|
|
52
|
+
* @returns Function that registers all tools with a server
|
|
53
|
+
*/
|
|
54
|
+
export function createRegisterTools(clientFactory, enabledGroups) {
|
|
55
|
+
const groups = enabledGroups || parseEnabledToolGroups(process.env.ENABLED_TOOLGROUPS);
|
|
56
|
+
return (server) => {
|
|
57
|
+
// Filter tools by enabled groups and create instances
|
|
58
|
+
const tools = ALL_TOOLS.filter((def) => def.groups.some((g) => groups.includes(g))).map((def) => def.factory(server, clientFactory));
|
|
59
|
+
// List available tools
|
|
60
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
61
|
+
return {
|
|
62
|
+
tools: tools.map((tool) => ({
|
|
63
|
+
name: tool.name,
|
|
64
|
+
description: tool.description,
|
|
65
|
+
inputSchema: tool.inputSchema,
|
|
66
|
+
})),
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
// Handle tool calls
|
|
70
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
71
|
+
const { name, arguments: args } = request.params;
|
|
72
|
+
const tool = tools.find((t) => t.name === name);
|
|
73
|
+
if (!tool) {
|
|
74
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
75
|
+
}
|
|
76
|
+
return await tool.handler(args);
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
// Keep the original registerTools for backward compatibility
|
|
81
|
+
export function registerTools(server) {
|
|
82
|
+
// This maintains compatibility but doesn't use dependency injection
|
|
83
|
+
const factory = () => {
|
|
84
|
+
throw new Error('No client factory provided - use createRegisterTools for dependency injection');
|
|
85
|
+
};
|
|
86
|
+
const register = createRegisterTools(factory);
|
|
87
|
+
register(server);
|
|
88
|
+
}
|