agent-orchestrator-mcp-server 0.1.1 → 0.1.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/README.md +7 -6
- package/build/index.js +30 -5
- package/package.json +1 -1
- package/shared/health-check.d.ts +21 -0
- package/shared/health-check.js +115 -0
- package/shared/index.d.ts +1 -0
- package/shared/index.js +2 -0
- package/shared/tools/search-sessions.d.ts +2 -2
package/README.md
CHANGED
|
@@ -56,12 +56,13 @@ Control which tools are available via the `ENABLED_TOOLGROUPS` environment varia
|
|
|
56
56
|
|
|
57
57
|
### Environment Variables
|
|
58
58
|
|
|
59
|
-
| Variable | Required | Description
|
|
60
|
-
| ----------------------------- | -------- |
|
|
61
|
-
| `AGENT_ORCHESTRATOR_BASE_URL` | Yes | Base URL for the orchestrator API
|
|
62
|
-
| `AGENT_ORCHESTRATOR_API_KEY` | Yes | API key for authentication
|
|
63
|
-
| `ENABLED_TOOLGROUPS` | No | Comma-separated tool groups
|
|
64
|
-
| `SKIP_HEALTH_CHECKS` | No | Skip API
|
|
59
|
+
| Variable | Required | Description | Default |
|
|
60
|
+
| ----------------------------- | -------- | -------------------------------------- | ----------- |
|
|
61
|
+
| `AGENT_ORCHESTRATOR_BASE_URL` | Yes | Base URL for the orchestrator API | - |
|
|
62
|
+
| `AGENT_ORCHESTRATOR_API_KEY` | Yes | API key for authentication | - |
|
|
63
|
+
| `ENABLED_TOOLGROUPS` | No | Comma-separated tool groups | All enabled |
|
|
64
|
+
| `SKIP_HEALTH_CHECKS` | No | Skip API connectivity check at startup | `false` |
|
|
65
|
+
| `HEALTH_CHECK_TIMEOUT` | No | Health check timeout in milliseconds | `10000` |
|
|
65
66
|
|
|
66
67
|
### Claude Desktop
|
|
67
68
|
|
package/build/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
-
import { createMCPServer } from '../shared/index.js';
|
|
4
|
-
import { logServerStart, logError, logWarning } from '../shared/logging.js';
|
|
3
|
+
import { createMCPServer, checkApiHealth, getErrorHint, parseHealthCheckTimeout, } from '../shared/index.js';
|
|
4
|
+
import { logServerStart, logError, logWarning, logDebug } from '../shared/logging.js';
|
|
5
5
|
// =============================================================================
|
|
6
6
|
// ENVIRONMENT VALIDATION
|
|
7
7
|
// =============================================================================
|
|
@@ -28,9 +28,14 @@ function validateEnvironment() {
|
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
name: 'SKIP_HEALTH_CHECKS',
|
|
31
|
-
description: 'Skip API
|
|
31
|
+
description: 'Skip API connectivity check at startup (set to "true" to skip)',
|
|
32
32
|
defaultValue: 'false',
|
|
33
33
|
},
|
|
34
|
+
{
|
|
35
|
+
name: 'HEALTH_CHECK_TIMEOUT',
|
|
36
|
+
description: 'Health check timeout in milliseconds',
|
|
37
|
+
defaultValue: '10000',
|
|
38
|
+
},
|
|
34
39
|
];
|
|
35
40
|
const missing = required.filter(({ name }) => !process.env[name]);
|
|
36
41
|
if (missing.length > 0) {
|
|
@@ -71,8 +76,28 @@ async function performHealthChecks() {
|
|
|
71
76
|
logWarning('healthcheck', 'Health checks skipped (SKIP_HEALTH_CHECKS=true)');
|
|
72
77
|
return;
|
|
73
78
|
}
|
|
74
|
-
|
|
75
|
-
//
|
|
79
|
+
logDebug('healthcheck', 'Performing API connectivity health check...');
|
|
80
|
+
// Parse health check timeout using shared utility
|
|
81
|
+
const healthCheckTimeout = parseHealthCheckTimeout(process.env.HEALTH_CHECK_TIMEOUT, (msg) => logWarning('healthcheck', msg));
|
|
82
|
+
const baseUrl = process.env.AGENT_ORCHESTRATOR_BASE_URL;
|
|
83
|
+
const apiKey = process.env.AGENT_ORCHESTRATOR_API_KEY;
|
|
84
|
+
try {
|
|
85
|
+
await checkApiHealth(baseUrl, apiKey, healthCheckTimeout);
|
|
86
|
+
logDebug('healthcheck', `Health check passed - connected to ${baseUrl}`);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
90
|
+
// Provide helpful error messages based on common failure scenarios
|
|
91
|
+
const hint = getErrorHint(errorMessage, healthCheckTimeout);
|
|
92
|
+
logError('healthcheck', `API connectivity health check failed: ${errorMessage}${hint}`);
|
|
93
|
+
console.error('\n----------------------------------------');
|
|
94
|
+
console.error('API connectivity health check failed!');
|
|
95
|
+
console.error(`Error: ${errorMessage}${hint}`);
|
|
96
|
+
console.error('\nTo skip health checks, set:');
|
|
97
|
+
console.error(' SKIP_HEALTH_CHECKS=true');
|
|
98
|
+
console.error('----------------------------------------\n');
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
76
101
|
}
|
|
77
102
|
// =============================================================================
|
|
78
103
|
// MAIN ENTRY POINT
|
package/package.json
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health check utilities for Agent Orchestrator MCP server.
|
|
3
|
+
* These are exported separately for testing.
|
|
4
|
+
*/
|
|
5
|
+
export declare const DEFAULT_HEALTH_CHECK_TIMEOUT = 10000;
|
|
6
|
+
export declare const MAX_HEALTH_CHECK_TIMEOUT = 300000;
|
|
7
|
+
/**
|
|
8
|
+
* Get a helpful hint based on the error message to guide users in troubleshooting.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getErrorHint(errorMessage: string, timeout: number): string;
|
|
11
|
+
/**
|
|
12
|
+
* Parse and validate health check timeout from environment variable.
|
|
13
|
+
* Returns validated timeout value or default.
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseHealthCheckTimeout(envValue: string | undefined, warnFn?: (message: string) => void): number;
|
|
16
|
+
/**
|
|
17
|
+
* Perform a health check against the Agent Orchestrator API.
|
|
18
|
+
* Makes a lightweight request to verify connectivity and authentication.
|
|
19
|
+
*/
|
|
20
|
+
export declare function checkApiHealth(baseUrl: string, apiKey: string, timeoutMs?: number): Promise<void>;
|
|
21
|
+
//# sourceMappingURL=health-check.d.ts.map
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health check utilities for Agent Orchestrator MCP server.
|
|
3
|
+
* These are exported separately for testing.
|
|
4
|
+
*/
|
|
5
|
+
export const DEFAULT_HEALTH_CHECK_TIMEOUT = 10000;
|
|
6
|
+
export const MAX_HEALTH_CHECK_TIMEOUT = 300000; // 5 minutes max
|
|
7
|
+
/**
|
|
8
|
+
* Get a helpful hint based on the error message to guide users in troubleshooting.
|
|
9
|
+
*/
|
|
10
|
+
export function getErrorHint(errorMessage, timeout) {
|
|
11
|
+
// Check for authentication errors first (most common initial setup issue)
|
|
12
|
+
if (errorMessage.includes('401') ||
|
|
13
|
+
errorMessage.includes('403') ||
|
|
14
|
+
errorMessage.toLowerCase().includes('unauthorized') ||
|
|
15
|
+
errorMessage.toLowerCase().includes('forbidden')) {
|
|
16
|
+
return '\nHint: Authentication failed. Check that AGENT_ORCHESTRATOR_API_KEY is correct.';
|
|
17
|
+
}
|
|
18
|
+
// Check for timeout errors
|
|
19
|
+
if (errorMessage.toLowerCase().includes('timeout')) {
|
|
20
|
+
return `\nHint: Connection timed out after ${timeout}ms. Check that the API server is running and reachable.`;
|
|
21
|
+
}
|
|
22
|
+
// Check for connection refused (specific error codes)
|
|
23
|
+
if (errorMessage.includes('ECONNREFUSED')) {
|
|
24
|
+
return '\nHint: Connection refused. Check that the API server is running and AGENT_ORCHESTRATOR_BASE_URL is correct.';
|
|
25
|
+
}
|
|
26
|
+
// Check for DNS resolution errors
|
|
27
|
+
if (errorMessage.includes('ENOTFOUND') || errorMessage.includes('getaddrinfo')) {
|
|
28
|
+
return '\nHint: Could not resolve hostname. Check that AGENT_ORCHESTRATOR_BASE_URL is correct.';
|
|
29
|
+
}
|
|
30
|
+
// Check for other connection errors (more specific patterns)
|
|
31
|
+
if (errorMessage.includes('ECONNRESET') ||
|
|
32
|
+
errorMessage.includes('EHOSTUNREACH') ||
|
|
33
|
+
errorMessage.includes('ENETUNREACH')) {
|
|
34
|
+
return '\nHint: Network error. Check that the API server is reachable and there are no firewall issues.';
|
|
35
|
+
}
|
|
36
|
+
// Check for invalid URL errors
|
|
37
|
+
if (errorMessage.includes('Invalid URL') || errorMessage.includes('ERR_INVALID_URL')) {
|
|
38
|
+
return '\nHint: Invalid URL. Check that AGENT_ORCHESTRATOR_BASE_URL is a valid URL (e.g., http://localhost:3000).';
|
|
39
|
+
}
|
|
40
|
+
return '';
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Parse and validate health check timeout from environment variable.
|
|
44
|
+
* Returns validated timeout value or default.
|
|
45
|
+
*/
|
|
46
|
+
export function parseHealthCheckTimeout(envValue, warnFn) {
|
|
47
|
+
if (!envValue) {
|
|
48
|
+
return DEFAULT_HEALTH_CHECK_TIMEOUT;
|
|
49
|
+
}
|
|
50
|
+
const parsed = parseInt(envValue, 10);
|
|
51
|
+
if (!isNaN(parsed) && parsed > 0 && parsed <= MAX_HEALTH_CHECK_TIMEOUT) {
|
|
52
|
+
return parsed;
|
|
53
|
+
}
|
|
54
|
+
if (warnFn) {
|
|
55
|
+
warnFn(`Invalid HEALTH_CHECK_TIMEOUT: ${envValue}. Must be between 1 and ${MAX_HEALTH_CHECK_TIMEOUT}. Using default: ${DEFAULT_HEALTH_CHECK_TIMEOUT}ms`);
|
|
56
|
+
}
|
|
57
|
+
return DEFAULT_HEALTH_CHECK_TIMEOUT;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Perform a health check against the Agent Orchestrator API.
|
|
61
|
+
* Makes a lightweight request to verify connectivity and authentication.
|
|
62
|
+
*/
|
|
63
|
+
export async function checkApiHealth(baseUrl, apiKey, timeoutMs = DEFAULT_HEALTH_CHECK_TIMEOUT) {
|
|
64
|
+
// Validate inputs
|
|
65
|
+
if (!baseUrl || baseUrl.trim().length === 0) {
|
|
66
|
+
throw new Error('Base URL cannot be empty');
|
|
67
|
+
}
|
|
68
|
+
if (!apiKey || apiKey.trim().length === 0) {
|
|
69
|
+
throw new Error('API key cannot be empty');
|
|
70
|
+
}
|
|
71
|
+
// Remove trailing slash if present
|
|
72
|
+
const normalizedBaseUrl = baseUrl.trim().replace(/\/$/, '');
|
|
73
|
+
// Use the sessions endpoint with minimal data to verify connectivity
|
|
74
|
+
let url;
|
|
75
|
+
try {
|
|
76
|
+
url = new URL(`${normalizedBaseUrl}/api/v1/sessions`);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
throw new Error('Invalid URL: Check that AGENT_ORCHESTRATOR_BASE_URL is a valid URL (e.g., http://localhost:3000)');
|
|
80
|
+
}
|
|
81
|
+
url.searchParams.set('per_page', '1');
|
|
82
|
+
const controller = new AbortController();
|
|
83
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
84
|
+
try {
|
|
85
|
+
const response = await fetch(url.toString(), {
|
|
86
|
+
method: 'GET',
|
|
87
|
+
headers: {
|
|
88
|
+
'X-API-Key': apiKey.trim(),
|
|
89
|
+
'Content-Type': 'application/json',
|
|
90
|
+
},
|
|
91
|
+
signal: controller.signal,
|
|
92
|
+
});
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
const errorText = await response.text();
|
|
95
|
+
let errorMessage;
|
|
96
|
+
try {
|
|
97
|
+
const errorJson = JSON.parse(errorText);
|
|
98
|
+
errorMessage = errorJson.message || errorJson.error || errorText;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
errorMessage = errorText || `HTTP ${response.status}`;
|
|
102
|
+
}
|
|
103
|
+
throw new Error(`API Error (${response.status}): ${errorMessage}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
108
|
+
throw new Error(`Request timeout after ${timeoutMs}ms`);
|
|
109
|
+
}
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
clearTimeout(timeoutId);
|
|
114
|
+
}
|
|
115
|
+
}
|
package/shared/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { registerResources } from './resources.js';
|
|
|
2
2
|
export { registerTools, createRegisterTools, type ToolGroup, parseEnabledToolGroups, } from './tools.js';
|
|
3
3
|
export { createMCPServer, type ClientFactory, type IAgentOrchestratorClient } from './server.js';
|
|
4
4
|
export { AgentOrchestratorClient, type IAgentOrchestratorClient as AgentOrchestratorClientInterface, } from './orchestrator-client/orchestrator-client.js';
|
|
5
|
+
export { checkApiHealth, getErrorHint, parseHealthCheckTimeout, DEFAULT_HEALTH_CHECK_TIMEOUT, MAX_HEALTH_CHECK_TIMEOUT, } from './health-check.js';
|
|
5
6
|
export type { Session, Log, SubagentTranscript, SessionStatus, LogLevel, SubagentStatus, Pagination, SessionsResponse, SearchSessionsResponse, SessionResponse, SessionActionResponse, LogsResponse, LogResponse, SubagentTranscriptsResponse, SubagentTranscriptResponse, CreateSessionRequest, UpdateSessionRequest, CreateLogRequest, UpdateLogRequest, CreateSubagentTranscriptRequest, UpdateSubagentTranscriptRequest, } from './types.js';
|
|
6
7
|
export { logServerStart, logError, logWarning, logDebug } from './logging.js';
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
package/shared/index.js
CHANGED
|
@@ -4,5 +4,7 @@ export { registerTools, createRegisterTools, parseEnabledToolGroups, } from './t
|
|
|
4
4
|
export { createMCPServer } from './server.js';
|
|
5
5
|
// Client exports
|
|
6
6
|
export { AgentOrchestratorClient, } from './orchestrator-client/orchestrator-client.js';
|
|
7
|
+
// Health check exports
|
|
8
|
+
export { checkApiHealth, getErrorHint, parseHealthCheckTimeout, DEFAULT_HEALTH_CHECK_TIMEOUT, MAX_HEALTH_CHECK_TIMEOUT, } from './health-check.js';
|
|
7
9
|
// Logging exports (re-exported for convenience)
|
|
8
10
|
export { logServerStart, logError, logWarning, logDebug } from './logging.js';
|
|
@@ -11,20 +11,20 @@ export declare const SearchSessionsSchema: z.ZodObject<{
|
|
|
11
11
|
page: z.ZodOptional<z.ZodNumber>;
|
|
12
12
|
per_page: z.ZodOptional<z.ZodNumber>;
|
|
13
13
|
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
per_page?: number | undefined;
|
|
14
15
|
status?: "waiting" | "running" | "needs_input" | "failed" | "archived" | undefined;
|
|
15
16
|
agent_type?: string | undefined;
|
|
16
17
|
show_archived?: boolean | undefined;
|
|
17
18
|
page?: number | undefined;
|
|
18
|
-
per_page?: number | undefined;
|
|
19
19
|
search_contents?: boolean | undefined;
|
|
20
20
|
id?: number | undefined;
|
|
21
21
|
query?: string | undefined;
|
|
22
22
|
}, {
|
|
23
|
+
per_page?: number | undefined;
|
|
23
24
|
status?: "waiting" | "running" | "needs_input" | "failed" | "archived" | undefined;
|
|
24
25
|
agent_type?: string | undefined;
|
|
25
26
|
show_archived?: boolean | undefined;
|
|
26
27
|
page?: number | undefined;
|
|
27
|
-
per_page?: number | undefined;
|
|
28
28
|
search_contents?: boolean | undefined;
|
|
29
29
|
id?: number | undefined;
|
|
30
30
|
query?: string | undefined;
|