Skip to content

Commit fd3ba35

Browse files
committed
refactor: Update adapter and agent types to use StructuredToolInterface
1 parent f885244 commit fd3ba35

File tree

5 files changed

+18
-35
lines changed

5 files changed

+18
-35
lines changed

src/adapters/langchain_adapter.ts

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,24 @@
11
import type { JSONSchema } from '@dmitryrechkin/json-schema-to-zod'
2+
import type { StructuredToolInterface } from '@langchain/core/tools'
23
import type {
34
CallToolResult,
45
EmbeddedResource,
56
ImageContent,
67
Tool as McpTool,
78
TextContent,
89
} from '@modelcontextprotocol/sdk/types.js'
9-
import type { ZodObject, ZodTypeAny } from 'zod'
10+
import type { ZodTypeAny } from 'zod'
1011
import type { BaseConnector } from '../connectors/base.js'
11-
import { JSONSchemaToZod } from '@dmitryrechkin/json-schema-to-zod'
1212

13+
import { JSONSchemaToZod } from '@dmitryrechkin/json-schema-to-zod'
1314
import { DynamicStructuredTool } from '@langchain/core/tools'
1415
import { z } from 'zod'
1516
import { logger } from '../logging.js'
1617
import { BaseAdapter } from './base.js'
1718

1819
function schemaToZod(schema: unknown): ZodTypeAny {
19-
/** Recursively normalise `type: [T, U]` → `anyOf: [{type:T},{type:U}]`. */
20-
// const fixSchema = (s: any): any => {
21-
// if (s && typeof s === 'object') {
22-
// if (Array.isArray(s.type)) {
23-
// s.anyOf = s.type.map((t: any) => ({ type: t }))
24-
// delete s.type
25-
// }
26-
// for (const [k, v] of Object.entries(s)) {
27-
// s[k] = fixSchema(v)
28-
// }
29-
// }
30-
// return s
31-
// }
32-
3320
try {
34-
// const normalised = fixSchema(structuredClone(schema))
35-
const zodSchema = JSONSchemaToZod.convert(schema as JSONSchema)
36-
return zodSchema
21+
return JSONSchemaToZod.convert(schema as JSONSchema)
3722
}
3823
catch (err) {
3924
logger.warn(`Failed to convert JSON schema to Zod: ${err}`)
@@ -84,7 +69,7 @@ function parseMcpToolResult(toolResult: CallToolResult): string {
8469
return decoded
8570
}
8671

87-
export class LangChainAdapter extends BaseAdapter<DynamicStructuredTool> {
72+
export class LangChainAdapter extends BaseAdapter<StructuredToolInterface> {
8873
constructor(disallowedTools: string[] = []) {
8974
super(disallowedTools)
9075
}
@@ -95,7 +80,7 @@ export class LangChainAdapter extends BaseAdapter<DynamicStructuredTool> {
9580
protected convertTool(
9681
mcpTool: McpTool,
9782
connector: BaseConnector,
98-
): DynamicStructuredTool | null {
83+
): StructuredToolInterface | null {
9984
// Filter out disallowed tools early.
10085
if (this.disallowedTools.includes(mcpTool.name)) {
10186
return null
@@ -121,7 +106,7 @@ export class LangChainAdapter extends BaseAdapter<DynamicStructuredTool> {
121106
return `Error executing MCP tool: ${String(err)}`
122107
}
123108
},
124-
}) as DynamicStructuredTool<ZodObject<any>, any>
109+
})
125110

126111
return tool
127112
}

src/agents/mcp_agent.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import type { BaseLanguageModel, LanguageModelLike } from '@langchain/core/language_models/base'
1+
import type { BaseLanguageModelInterface, LanguageModelLike } from '@langchain/core/language_models/base'
22
import type {
33
BaseMessage,
44
} from '@langchain/core/messages'
5-
import type { DynamicStructuredTool } from '@langchain/core/tools'
5+
import type { StructuredToolInterface } from '@langchain/core/tools'
66
import type { AgentFinish, AgentStep } from 'langchain/agents'
77
import type { MCPClient } from '../client.js'
88
import type { BaseConnector } from '../connectors/base.js'
@@ -28,7 +28,7 @@ import { createSystemMessage } from './prompts/system_prompt_builder.js'
2828
import { DEFAULT_SYSTEM_PROMPT_TEMPLATE, SERVER_MANAGER_SYSTEM_PROMPT_TEMPLATE } from './prompts/templates.js'
2929

3030
export class MCPAgent {
31-
private llm: LanguageModelLike
31+
private llm: BaseLanguageModelInterface
3232
private client?: MCPClient
3333
private connectors: BaseConnector[]
3434
private maxSteps: number
@@ -46,12 +46,12 @@ export class MCPAgent {
4646
private agentExecutor: AgentExecutor | null = null
4747
private sessions: Record<string, MCPSession> = {}
4848
private systemMessage: SystemMessage | null = null
49-
private tools: DynamicStructuredTool[] = []
49+
private tools: StructuredToolInterface[] = []
5050
private adapter: LangChainAdapter
5151
private serverManager: ServerManager | null = null
5252

5353
constructor(options: {
54-
llm: BaseLanguageModel
54+
llm: BaseLanguageModelInterface
5555
client?: MCPClient
5656
connectors?: BaseConnector[]
5757
serverName?: string
@@ -162,7 +162,7 @@ export class MCPAgent {
162162
logger.info('✨ Agent initialization complete')
163163
}
164164

165-
private async createSystemMessageFromTools(tools: DynamicStructuredTool[]): Promise<void> {
165+
private async createSystemMessageFromTools(tools: StructuredToolInterface[]): Promise<void> {
166166
const systemPromptTemplate
167167
= this.systemPromptTemplateOverride
168168
?? DEFAULT_SYSTEM_PROMPT_TEMPLATE
@@ -196,7 +196,7 @@ export class MCPAgent {
196196
])
197197

198198
const agent = createToolCallingAgent({
199-
llm: this.llm,
199+
llm: this.llm as unknown as LanguageModelLike,
200200
tools: this.tools,
201201
prompt,
202202
})
@@ -298,7 +298,7 @@ export class MCPAgent {
298298
const intermediateSteps: AgentStep[] = []
299299
const inputs = { input: query, chat_history: langchainHistory } as Record<string, unknown>
300300

301-
let nameToToolMap: Record<string, DynamicStructuredTool> = Object.fromEntries(this.tools.map(t => [t.name, t]))
301+
let nameToToolMap: Record<string, StructuredToolInterface> = Object.fromEntries(this.tools.map(t => [t.name, t]))
302302
logger.info(`🏁 Starting agent execution with max_steps=${steps}`)
303303

304304
for (let stepNum = 0; stepNum < steps; stepNum++) {

src/agents/prompts/system_prompt_builder.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import type { DynamicStructuredTool } from '@langchain/core/tools'
1+
import type { StructuredToolInterface } from '@langchain/core/tools'
22
import { SystemMessage } from '@langchain/core/messages'
33

44
export function generateToolDescriptions(
5-
tools: DynamicStructuredTool[],
5+
tools: StructuredToolInterface[],
66
disallowedTools?: string[],
77
): string[] {
88
const disallowedSet = new Set(disallowedTools ?? [])
@@ -44,7 +44,7 @@ export function buildSystemPromptContent(
4444
}
4545

4646
export function createSystemMessage(
47-
tools: DynamicStructuredTool[],
47+
tools: StructuredToolInterface[],
4848
systemPromptTemplate: string,
4949
serverManagerTemplate: string,
5050
useServerManager: boolean,

src/task_managers/sse.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ export class SseConnectionManager extends ConnectionManager<SSEClientTransport>
2525
*/
2626
protected async establishConnection(): Promise<SSEClientTransport> {
2727
this._transport = new SSEClientTransport(this.url, this.opts)
28-
// await this._transport.start()
2928

3029
logger.debug(`${this.constructor.name} connected successfully`)
3130
return this._transport

src/task_managers/stdio.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ export class StdioConnectionManager extends ConnectionManager<StdioClientTranspo
2929
protected async establishConnection(): Promise<StdioClientTransport> {
3030
// Instantiate and start the transport
3131
this._transport = new StdioClientTransport(this.serverParams)
32-
// await this._transport.start()
3332

3433
// If stderr was piped, forward it to `errlog` for visibility
3534
if (this._transport.stderr && typeof (this._transport.stderr as any).pipe === 'function') {

0 commit comments

Comments
 (0)