Readonly [TOOLSET_Static createFor when your tools share something that needs setup or cleanup, like a DB pool, an open MCP
client, or listeners on a shared bus. setup runs once at activation, aclose once at
teardown. If the tool list itself is dynamic (e.g. an MCP server), push it from setup via
ToolsetContext.updateTools.
function createPostgresToolset(connectionUrl: string): Toolset {
const pool = new pg.Pool({ connectionString: connectionUrl });
return Toolset.create({
id: 'postgres',
tools: [queryOrders, queryCustomers],
aclose: () => pool.end(),
});
}
function createMcpToolset(url: string): Toolset {
const client = new MCPClient({ url });
return Toolset.create({
id: 'mcp_remote',
// setup connects and wires listeners that push the server's tools whenever they change;
// the runtime re-advertises without re-running anything.
setup: async ({ updateTools }) => {
const sync = async () => updateTools(await client.listTools());
client.on('connect', sync);
client.on('tool_list_changed', sync);
await client.connect();
},
tools: [],
aclose: () => client.disconnect(),
});
}
A stateful collection of tools sharing a lifecycle. Tools registered through a
Toolsetare flattened into the surroundingToolContext, while theToolsetitself is tracked so itssetup()/aclose()hooks can be invoked by the agent runtime.