Skip to main content
Version: SDK ยท v1.1.0

MCP tools

The ERPBridge SDK wraps the official @modelcontextprotocol/client (D2) and adds a typed surface. Use these surfaces to call and manage tools:

SurfaceWhat it is
client.mcpThe raw MCP protocol client (connect, listTools, callTool, close)
client.toolsThe exact-name tool proxy (lazy, argument-validated)
client.registryREST CRUD over the stored tool resources

Browser MCP and toolsโ€‹

Browser applications can use the ESM build with client.mcp, client.tools, and client.close():

import { createClient } from '@erpbridge/sdk'

const client = createClient({ baseUrl: 'https://bridge.example.com' })
await client.mcp.connect()
const result = await client.tools.list_employees({})
await client.close()

The ERPBridge /mcp/ endpoint must allow the frontend origin and the MCP protocol and session headers. It must also expose Mcp-Session-Id. This release supports only MCP and tools in browsers. Use Node.js, a same-origin server, or an application proxy for logs, metrics, health, cache, registry, and direct invoke operations.

The MCP clientโ€‹

const client = createClient({ baseUrl: 'http://localhost:8080' })

await client.mcp.connect() // handshake + negotiation
const tools = await client.mcp.listTools() // ToolDefinition[]
const result = await client.mcp.callTool('system.progress_test', { steps: 1 })
await client.close()
  • connect() negotiates the protocol version with the server. The client negotiates down from 2025-11-25 and transparently reconnects once with a fresh session before it gives up with a ProtocolError by default. Set mcpRetryPolicy: 'never' for side-effecting workflows that must not replay an operation after an ambiguous transport failure. In that mode, the first transport failure becomes a ProtocolError and no reconnect occurs.
  • listTools may include standard tool annotations and namespaced _meta guidance such as whenToUse, examples, and allowed roles. Custom _meta keys are client-dependent and may not be forwarded into the model context.
  • callTool returns the complete MCP McpToolResult envelope. Inspect its content blocks and optional structuredContent. An unknown tool returns NotFoundError. A tool that runs but reports failure returns { isError: true } in the envelope.
  • close() ends the session and its transport. The ERPBridge SDK client facade's close() does the same.

The tool proxyโ€‹

client.tools is a lazy Proxy over the MCP tools/list result. It provides an exact-name property for each registered tool:

await client.mcp.connect()
const result = await client.tools.list_employees({ department: 'engineering' })

Each property calls a registered tool by its exact registered name. Use bare names such as list_employees, not erp.-prefixed names. Dotted names also work: client.tools.system.progress_test({ steps: 1 }). The proxy validates arguments against the tool input schema before the call. An unknown property throws NotFoundError and lists the tools that the server exposes.

The tool registryโ€‹

client.registry provides REST CRUD for stored tool resources. It is separate from client.mcp.listTools() (C3):

  • registry.list({ name, version }) returns exact-filtered resources in the full wire shape (RegistryTool: apiVersion: "erpbridge.io/v1" / kind: "MCPTool" / metadata / spec), not the flat MCP ToolDefinition.
  • registry.apply(def) posts a tool definition. The server's admission controller validates it and rejects violations with HTTP 422, surfaced as a typed ClientError.
  • registry.delete(name, version, { hard: true }) soft- or hard-deletes a tool version.
  • client.invoke(name, args, { role }) calls a registered tool directly over REST. The optional role is sent as X-ERPBridge-Role and is not added to the JSON arguments. No MCP session is needed. Built-in system.* tools are reachable only through the MCP path. The REST invoke endpoint resolves only registered (stored) tools.

The registry deliberately lives outside client.tools so registered tool names such as list, apply, or delete never shadow the registry methods.