Repository navigation
Expand file tree
/
Copy pathfetchToolSchema.ts
More file actions
46 lines (41 loc) · 1.69 KB
/
Copy pathfetchToolSchema.ts
File metadata and controls
46 lines (41 loc) · 1.69 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
import { tool } from "langchain";
import type { Tool } from "@modelcontextprotocol/client";
import { z } from "zod";
// The catalog shows the first sentence of each tool description; the full one comes with the loaded tool.
const FIRST_SENTENCE_RE = /^[\s\S]*?[.!?](?=\s|$)/;
const WHITESPACE_RE = /\s+/g;
const fetchToolSchemaSchema = z.object({
toolName: z
.string()
.describe("Name of the admin panel tool to load, for example create_record."),
});
function catalogEntry({ name, description }: Tool) {
if (!description) return `- ${name}`;
const summary = (description.match(FIRST_SENTENCE_RE)?.[0] ?? description).replace(WHITESPACE_RE, " ");
return `- ${name}: ${summary}`;
}
/**
* Loads an MCP tool for later steps: the tools middleware adds every tool this returned status 200 for.
* Like MCP clients that load tool schemas on demand, its description names every tool it can load.
*/
export function createFetchToolSchemaTool(mcpTools: Tool[], loadableTools: Tool[]) {
const mcpToolNames = new Set(mcpTools.map((mcpTool) => mcpTool.name));
return tool(
async ({ toolName }) => JSON.stringify(
mcpToolNames.has(toolName)
? { status: 200, name: toolName, loaded: true }
: { status: 404, error: "TOOL_NOT_FOUND", message: `Tool "${toolName}" not found.` },
null,
2,
),
{
name: "fetch_tool_schema",
description: [
"Loads an admin panel tool so you can call it from the next step. Load a tool before its first call, right after fetch_skill when the skill lists tools you cannot call yet.",
"Tools you can load:",
...loadableTools.map(catalogEntry),
].join("\n"),
schema: fetchToolSchemaSchema,
},
);
}