Skip to content

Commit 12778ff

Browse files
committed
feat: remote agent support
1 parent 16353c1 commit 12778ff

File tree

4 files changed

+417
-8
lines changed

4 files changed

+417
-8
lines changed

index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { MCPAgent } from './src/agents/mcp_agent.js'
2+
import { RemoteAgent } from './src/agents/remote.js'
23
import { MCPClient } from './src/client.js'
34
import { loadConfigFile } from './src/config.js'
45
import { BaseConnector } from './src/connectors/base.js'
@@ -25,4 +26,4 @@ export { AIMessage, BaseMessage, HumanMessage, SystemMessage, ToolMessage } from
2526
// Re-export StreamEvent type from LangChain for convenience
2627
export type { StreamEvent } from '@langchain/core/tracers/log_stream'
2728

28-
export { BaseConnector, HttpConnector, loadConfigFile, Logger, logger, MCPAgent, MCPClient, MCPSession, StdioConnector, WebSocketConnector }
29+
export { BaseConnector, HttpConnector, loadConfigFile, Logger, logger, MCPAgent, MCPClient, MCPSession, RemoteAgent, StdioConnector, WebSocketConnector }

src/agents/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export { BaseAgent } from './base.js'
22
export { MCPAgent } from './mcp_agent.js'
3+
export { RemoteAgent } from './remote.js'

src/agents/mcp_agent.ts

Lines changed: 81 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@ import { ServerManager } from '../managers/server_manager.js'
3232
import { extractModelInfo, Telemetry } from '../telemetry/index.js'
3333
import { createSystemMessage } from './prompts/system_prompt_builder.js'
3434
import { DEFAULT_SYSTEM_PROMPT_TEMPLATE, SERVER_MANAGER_SYSTEM_PROMPT_TEMPLATE } from './prompts/templates.js'
35+
import { RemoteAgent } from './remote.js'
3536

3637
export class MCPAgent {
37-
private llm: BaseLanguageModelInterface
38+
private llm?: BaseLanguageModelInterface
3839
private client?: MCPClient
3940
private connectors: BaseConnector[]
4041
private maxSteps: number
@@ -60,8 +61,12 @@ export class MCPAgent {
6061
private modelProvider: string
6162
private modelName: string
6263

64+
// Remote agent support
65+
private isRemote = false
66+
private remoteAgent: RemoteAgent | null = null
67+
6368
constructor(options: {
64-
llm: BaseLanguageModelInterface
69+
llm?: BaseLanguageModelInterface
6570
client?: MCPClient
6671
connectors?: BaseConnector[]
6772
maxSteps?: number
@@ -76,7 +81,40 @@ export class MCPAgent {
7681
verbose?: boolean
7782
adapter?: LangChainAdapter
7883
serverManagerFactory?: (client: MCPClient) => ServerManager
84+
// Remote agent parameters
85+
agentId?: string
86+
apiKey?: string
87+
baseUrl?: string
7988
}) {
89+
// Handle remote execution
90+
if (options.agentId) {
91+
this.isRemote = true
92+
this.remoteAgent = new RemoteAgent({
93+
agentId: options.agentId,
94+
apiKey: options.apiKey,
95+
baseUrl: options.baseUrl,
96+
})
97+
// Set default values for remote agent
98+
this.maxSteps = options.maxSteps ?? 5
99+
this.memoryEnabled = options.memoryEnabled ?? true
100+
this.autoInitialize = options.autoInitialize ?? false
101+
this.verbose = options.verbose ?? false
102+
this.connectors = []
103+
this.disallowedTools = []
104+
this.additionalTools = []
105+
this.useServerManager = false
106+
this.adapter = new LangChainAdapter()
107+
this.telemetry = Telemetry.getInstance()
108+
this.modelProvider = 'remote'
109+
this.modelName = 'remote-agent'
110+
return
111+
}
112+
113+
// Validate requirements for local execution
114+
if (!options.llm) {
115+
throw new Error('llm is required for local execution. For remote execution, provide agentId instead.')
116+
}
117+
80118
this.llm = options.llm
81119

82120
this.client = options.client
@@ -111,9 +149,15 @@ export class MCPAgent {
111149
// Initialize telemetry
112150
this.telemetry = Telemetry.getInstance()
113151
// Track model info for telemetry
114-
const [provider, name] = extractModelInfo(this.llm as any)
115-
this.modelProvider = provider
116-
this.modelName = name
152+
if (this.llm) {
153+
const [provider, name] = extractModelInfo(this.llm as any)
154+
this.modelProvider = provider
155+
this.modelName = name
156+
}
157+
else {
158+
this.modelProvider = 'unknown'
159+
this.modelName = 'unknown'
160+
}
117161

118162
// Make getters configurable for test mocking
119163
Object.defineProperty(this, 'agentExecutor', {
@@ -131,6 +175,12 @@ export class MCPAgent {
131175
}
132176

133177
public async initialize(): Promise<void> {
178+
// Skip initialization for remote agents
179+
if (this.isRemote) {
180+
this._initialized = true
181+
return
182+
}
183+
134184
logger.info('🚀 Initializing MCP agent and connecting to services...')
135185

136186
// If using server manager, initialize it
@@ -219,6 +269,10 @@ export class MCPAgent {
219269
}
220270

221271
private createAgent(): AgentExecutor {
272+
if (!this.llm) {
273+
throw new Error('LLM is required to create agent')
274+
}
275+
222276
const systemContent = this.systemMessage?.content ?? 'You are a helpful assistant.'
223277

224278
const prompt = ChatPromptTemplate.fromMessages([
@@ -327,6 +381,11 @@ export class MCPAgent {
327381
externalHistory?: BaseMessage[],
328382
outputSchema?: ZodSchema<T>,
329383
): Promise<string | T> {
384+
// Delegate to remote agent if in remote mode
385+
if (this.isRemote && this.remoteAgent) {
386+
return this.remoteAgent.run(query, maxSteps, manageConnector, externalHistory, outputSchema)
387+
}
388+
330389
const generator = this.stream<T>(
331390
query,
332391
maxSteps,
@@ -348,6 +407,12 @@ export class MCPAgent {
348407
externalHistory?: BaseMessage[],
349408
outputSchema?: ZodSchema<T>,
350409
): AsyncGenerator<AgentStep, string | T, void> {
410+
// Delegate to remote agent if in remote mode
411+
if (this.isRemote && this.remoteAgent) {
412+
const result = await this.remoteAgent.run(query, maxSteps, manageConnector, externalHistory, outputSchema)
413+
return result as string | T
414+
}
415+
351416
let result = ''
352417
let initializedHere = false
353418
const startTime = Date.now()
@@ -362,13 +427,16 @@ export class MCPAgent {
362427
query = this._enhanceQueryWithSchema(query, outputSchema)
363428
logger.debug(`🔄 Structured output requested, schema: ${JSON.stringify(zodToJsonSchema(outputSchema), null, 2)}`)
364429
// Check if withStructuredOutput method exists
365-
if ('withStructuredOutput' in this.llm && typeof (this.llm as any).withStructuredOutput === 'function') {
430+
if (this.llm && 'withStructuredOutput' in this.llm && typeof (this.llm as any).withStructuredOutput === 'function') {
366431
structuredLlm = (this.llm as any).withStructuredOutput(outputSchema)
367432
}
368-
else {
433+
else if (this.llm) {
369434
// Fallback: use the same LLM but we'll handle structure in our helper method
370435
structuredLlm = this.llm
371436
}
437+
else {
438+
throw new Error('LLM is required for structured output')
439+
}
372440
schemaDescription = JSON.stringify(zodToJsonSchema(outputSchema), null, 2)
373441
}
374442

@@ -615,6 +683,12 @@ export class MCPAgent {
615683
}
616684

617685
public async close(): Promise<void> {
686+
// Delegate to remote agent if in remote mode
687+
if (this.isRemote && this.remoteAgent) {
688+
await this.remoteAgent.close()
689+
return
690+
}
691+
618692
logger.info('🔌 Closing MCPAgent resources…')
619693
try {
620694
this._agentExecutor = null

0 commit comments

Comments
 (0)