Repository navigation
Expand file tree
/
Copy pathagentToolProvider.ts
More file actions
54 lines (49 loc) · 2.43 KB
/
Copy pathagentToolProvider.ts
File metadata and controls
54 lines (49 loc) · 2.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import type { IAdminForth } from "adminforth";
import type { ClientTool } from "@langchain/core/tools";
import { connectMcp, MCP_PLUGIN_CLASS_NAME, type McpConnectionInput, type McpPlugin } from "./mcpConnection.js";
import { createMcpTool } from "./mcpTool.js";
import { createFetchToolSchemaTool } from "./fetchToolSchema.js";
import { createGetUserLocationTool } from "./getUserLocation.js";
import { createNavigateUserTool } from "./navigateUser.js";
// MCP tools the model can call from the first step; it loads the others with fetch_tool_schema.
const BASE_MCP_TOOL_NAMES = new Set(["fetch_skill", "get_resources_list", "get_resource", "wait_for_confirmation"]);
/** The tools of one agent turn, backed by one MCP connection that `close` ends. */
export type AgentToolSet = {
/** MCP server instructions, sent ahead of the agent's own system prompt. */
instructions: string;
/** Tools the model can call from the first step. */
baseTools: ClientTool[];
/** MCP tools the model loads on demand with fetch_tool_schema, by name. */
dynamicTools: Record<string, ClientTool>;
/** Tools that pause for the user's approval before they run. */
approvalToolNames: string[];
close(): Promise<void>;
};
export class AgentToolProvider {
constructor(private readonly getAdminforth: () => IAdminForth) {}
async open(input: Omit<McpConnectionInput, "requestUrl">): Promise<AgentToolSet> {
const adminforth = this.getAdminforth();
const connection = await connectMcp(
adminforth.getPluginByClassName<McpPlugin>(MCP_PLUGIN_CLASS_NAME),
{ ...input, requestUrl: adminforth.config.baseUrlSlashed },
);
const baseMcpTools = connection.tools.filter((mcpTool) => BASE_MCP_TOOL_NAMES.has(mcpTool.name));
const dynamicMcpTools = connection.tools.filter((mcpTool) => !BASE_MCP_TOOL_NAMES.has(mcpTool.name));
return {
instructions: connection.instructions,
baseTools: [
...baseMcpTools.map((mcpTool) => createMcpTool(mcpTool, connection)),
createGetUserLocationTool(),
createNavigateUserTool(),
createFetchToolSchemaTool(connection.tools, dynamicMcpTools),
],
dynamicTools: Object.fromEntries(
dynamicMcpTools.map((mcpTool) => [mcpTool.name, createMcpTool(mcpTool, connection)]),
),
approvalToolNames: connection.tools
.filter((mcpTool) => mcpTool.annotations?.destructiveHint)
.map((mcpTool) => mcpTool.name),
close: connection.close,
};
}
}