MCP Fusion/Operate and integrate/Typed client

Typed client

Ask AI about Vinkius

Call a connector from TypeScript with a router inferred from its builders: execute dotted actions, batch calls, use a fluent proxy and parse tool_error into MCPFusionClientError.

MCP Fusion is useful on both sides of the boundary. The server owns the security pipeline; the typed client gives the application that calls it a compiler-checked contract. No generated SDK and no duplicated argument interfaces.

Export the router once

On the server, wrap the builders in the curried typed registry and export its inferred router type:

typescript
import { createTypedRegistry } from '@mcpfusion/core';
import type { InferRouter } from '@mcpfusion/core';

const registry = createTypedRegistry<AppContext>()(
  listProjects,
  createProject,
);

registry.registry.attachToServer(server, { contextFactory });
export type AppRouter = InferRouter<typeof registry>;

The runtime value is registry.registry; _builders and _context are type-carrying fields. InferRouter intersects the phantom router maps accumulated by each builder, so changing a .withString() parameter changes the client compile contract without a code generation step.

Execute with the contract

typescript
import { createMCPFusionClient } from '@mcpfusion/core/client';
import type { AppRouter } from './server.js';

const client = createMCPFusionClient<AppRouter>(transport, {
  throwOnError: true,
});

await client.execute('projects.create', {
  workspace_id: 'ws_1',
  name: 'V2',
});

A dotted action maps to the wire namespace: projects.create becomes callTool('projects', { ...args, action: 'create' }). A single segment passes through unchanged. The discriminator key defaults to action and is configurable with discriminatorKey.

Batch and proxy

executeBatch(calls) uses Promise.all and returns results in call order. Pass { sequential: true } when the second call depends on the first. The fluent proxy is a recursive JavaScript Proxy:

typescript
await client.proxy.projects.create({
  workspace_id: 'ws_1',
  name: 'V2',
});

await client.proxy.platform.users.list({ limit: 10 });

DevTools inspection and the Promise then lookup are guarded, so the proxy does not accidentally execute while a debugger or test runner examines it.

Client middleware

Client middleware is compiled once when the client is created:

typescript
const client = createMCPFusionClient<AppRouter>(transport, {
  middleware: [async (action, args, next) => {
    const started = Date.now();
    const result = await next(action, args);
    metrics.record(action, Date.now() - started, result.isError);
    return result;
  }],
});

The signature is (action, args, next) => Promise<ToolResponse>. Use it for client-side tracing, retries with an explicit policy, or adding a correlation header. The server still owns authentication, validation and redaction.

Error parsing

With throwOnError: false the client always returns ToolResponse; inspect isError. With true, a response carrying isError: true becomes MCPFusionClientError with code, recovery, frozen availableActions, severity and the raw response. It parses the framework's <tool_error> XML, including legacy comma-separated action lists.

External AI clients

There are no MCP Fusion branded adapters for model frameworks. Use their official MCP clients:

RuntimePackageShape
Vercel AI SDK@ai-sdk/mcpcreateMCPClient() then client.tools() for generateText or streamText
LangChain@langchain/mcp-adaptersMultiServerMCPClient.loadTools() then a LangGraph agent
LlamaIndex@llamaindex/toolsmcp(...).tools() then agent({ tools })

The framework on the server remains responsible for the MVA Presenter, DLP and tenant boundary. The model runtime only consumes the resulting MCP surface.

Next steps