MCP Fusion/Core concepts/Tools
Tools
Definieren Sie AI Capabilities mit f.query, f.mutation und f.action: typisierte Parameter, Middleware, die Result-Monade und FSM state gating, das Tools entfernt, die der Agent nicht nutzen darf.
Tools sind das, was der Agent aufruft. In Vinkius-Terminologie sind sie die AI Capabilities Ihres Connectors. MCP Fusion gibt Ihnen einen fluent Builder mit drei semantischen Einstiegspunkten, und die Semantik entspricht den MCP-Annotationen, die der Agent sieht.
| Builder | Bedeutung | MCP-Annotation |
|---|---|---|
f.query() | Liest Daten | readOnlyHint: true |
f.mutation() | Schreibt Daten | Destruktive Hints pro Tool |
f.action() | Seiteneffekte, externe Aufrufe | Destruktive Hints pro Tool |
Ein vollständiges Tool
export default f.mutation('billing.refund')
.describe('Refund an invoice by ID')
.withString('id', 'Invoice ID')
.withNumber('amount_cents', 'Amount to refund in CENTS')
.withOptionalEnum('reason', ['duplicate', 'customer_request', 'fraud'],
'Why the refund is happening')
.returns(InvoicePresenter)
.use(requireAuth)
.handle(async (input, ctx) => {
const result = await refunds.create(input, ctx.tenantId);
if (!result.ok) return result.response;
return result.value;
});Parameter
.withString(name, description),.withNumber,.withBoolean,.withEnumund die.withOptional-Varianten bauen das Zod-Eingabeschema- Modelgetriebene Tools können
.fromModel()verwenden und die fillable-Felder eines Models als Parameter wiederverwenden .toonDescription()komprimiert die Tool-Beschreibung in ein Pipe-Format, das etwa halb so viele Tokens kostet.bindState('approved', 'DISCHARGE')verbindet das Tool mit einem FSM-Zustand, unten beschrieben
Middleware
.use() hängt Middleware an ein einzelnes Tool. Middleware komponiert im Express-Stil, und jede Middleware gibt einen Teilkontext zurück, der in ctx gemergt wird. So bleiben Auth, Tenant-Auflösung und Rate Limiting aus Ihren Handlern heraus:
// A middleware derives context: the returned object merges into ctx,
// typed through the whole fluent chain.
const withUser = f.middleware(async (ctx) => {
const user = await auth.verify(ctx.request);
return { user };
});
f.query('billing.get_profile').use(withUser);Siehe Routing für globale Middleware, die auf jedes Tool in einem Verzeichnis angewendet wird.
Die Result-Monade
Handler, die fehlschlagen können, geben ein Result zurück, statt eine Exception zu werfen, und das Framework verwandelt ein Failure in eine strukturierte Tool-Antwort, mit der der Agent arbeiten kann:
import { succeed, fail, toolError } from '@mcpfusion/core';
.handle(async (input) => {
const invoice = await db.invoices.findUnique({ where: { id: input.id } });
if (!invoice) {
return fail(toolError('NOT_FOUND', {
message: 'No invoice with that ID',
availableActions: ['billing.list_invoices'],
}));
}
return succeed(invoice);
});Die availableActions-Liste ist selbstheilender Kontext: wenn der Agent die falsche ID gewählt hat, zeigt ihm der Fehler, was er stattdessen tun kann. Siehe Governance für die Funktionsweise desselben Konzepts bei Contract-Änderungen.
FSM state gating
Manche Tools dürfen in bestimmten Zuständen gar nicht existieren. Ein Discharge-Tool hat nichts sichtbar zu suchen, bevor eine Rechnung genehmigt ist. .bindState() verbindet das Tool mit einem Workflow-Zustand, und MCP Fusion entfernt es physisch aus tools/list, solange der Zustand es verbietet:
export default f.action('billing.discharge')
.describe('Discharge an approved invoice')
.bindState('approved', 'DISCHARGE')
.handle(async (input, ctx) => { /* ... */ });Der Client erhält notifications/tools/list_changed, wenn sich der Zustand ändert, sodass das Menü des Agenten der Realität entspricht. Damit ist die klassische Halluzination erledigt, bei der das Modell einen Schritt außerhalb der Reihenfolge aufruft. Der State Store ist austauschbar, mit Redis- und Edge-KV-Optionen, daher funktioniert das Gating auch in serverless Umgebungen.
State gating entfernt das Tool, es versteckt es nicht. Der Agent sieht nie ein Tool, das er nicht aufrufen darf, versucht es also nie und verbrät nie einen Turn auf eine Ablehnung.
Nächste Schritte
- Routing: Tools nach Dateien organisieren, viele Aktionen in einem Tool gruppieren
- Models and Presenters: festlegen, was jedes Tool zurückgibt
- Testing: die gesamte Pipeline im Speicher testen
