Tools & MCP
Typed tools from any Standard Schema validator, middleware, and MCP — client and server.
Define a tool
One schema both validates the model's arguments and describes them to the model. Any Standard Schema validator works — Zod, Valibot, ArkType:
import { z } from 'zod';
import { defineTool } from '@agentoria/runtime';
const getWeather = defineTool({
name: 'get_weather',
description: "Get the current weather for a city.",
parameters: z.object({ city: z.string(), unit: z.enum(['c', 'f']).default('c') }),
handler: async ({ city, unit }, ctx) => {
// ctx is your per-request context (auth, db, …) from createAgentHandler's `context`
return await ctx.weather.lookup(city, unit);
},
});Pass tools straight to createAgentHandler({ tools: [getWeather] }), or build a ToolRegistry for middleware and mutation flags.
Middleware
ToolRegistry.use(mw) wraps every call (onion / interceptor) — auth, logging, rate-limiting, human confirmation — without touching handlers:
import { ToolRegistry, approvalMiddleware } from '@agentoria/runtime';
const tools = new ToolRegistry([getWeather, publishPost])
.use(approvalMiddleware({ needsApproval: (call) => call.name === 'publish_post' }));Mark a tool mutates: true and it's gated behind confirm-before-execute (and filtered out of read-only tool lists).
Argument repair
Models sometimes emit almost-valid tool calls — arguments as a JSON string, or wrapped in a fence. executeWithRepair fixes the cheap cases in-process instead of burning a whole turn:
import { executeWithRepair } from '@agentoria/runtime';
const exec = await executeWithRepair(tools, name, rawArgs, ctx, {
maxRepairs: 1, // default coercion handles stringified JSON…
repair: ({ error, input }) => fixWithModel(input, error), // …or plug in an LLM repair
});MCP — expose your tools
Turn a registry into a read-only Model Context Protocol endpoint:
import { createMcpHandler } from '@agentoria/mcp';
export const POST = createMcpHandler({ tools, serverInfo: { name: 'my-app', version: '1.0.0' } });MCP — consume external tools
Pull a remote MCP server's tools into your agent as a ToolSource:
import { createMcpClient, httpTransport } from '@agentoria/mcp';
import { agentTools, mergeTools } from '@agentoria/runtime';
const remote = await createMcpClient(httpTransport('https://tools.example.com/mcp'));
const all = mergeTools(localTools, agentTools(remote)); // local + remote, routed by name