How to add a Global Callable Class which Implements Callable and Register it as a Tool in MCP Server

Chirag ChetwaniChirag ChetwaniJanuary 16, 2026

image

A "global callable class" in Apex is a class marked global that implements the Callable interface. That means:

  • global: it can be accessed outside your package/namespace (so external callers can use it).
  • Callable: it exposes a single entry point, call(String action, Map<String, Object> args), and you route to different methods based on action.

In simple terms: it’s a single front door you can use to call multiple backend methods by name.

Utility

  • Lets external systems (or tools like MCP) call Apex methods dynamically.
  • You can add new “actions” without changing the interface — just add a new when branch.
  • Works well for generic integrations where the caller only knows a method name + arguments.

Benefits

  • One endpoint, many operations: no need to build separate REST endpoints per method.
  • Flexible: can evolve without breaking callers.
  • Tool‑friendly: easy for automation tools to call a single “dispatcher”.
  • Centralized control: you can validate, log, and secure everything in one place.

A global class Extension which implements Callable can’t be invoked over REST by itself. You still need an API surface (Apex REST, Tooling, or a custom endpoint) that calls Extension.call().

Typical pattern:

  • Create an Apex REST class that receives action + args.

  • Inside it, instantiate Extension and call extension.call(action, args).

  • Your MCP tool calls that REST endpoint.

Here’s the code for Apex side (Callable + REST wrapper), and the MCP tool call in Node.

Apex: callable class

Extension.apxc
global class Extension implements Callable { String concatStrings(String stringValue) { return stringValue + stringValue; } Decimal squareNumbers(Decimal decimalValue) { return decimalValue * decimalValue; } global Object call(String action, Map<String, Object> args) { switch on action { when 'concatStrings' { return this.concatStrings((String)args.get('stringValue')); } when 'squareNumbers' { return this.squareNumbers((Decimal)args.get('decimalValue')); } when else { throw new ExtensionMalformedCallException('Method not implemented'); } } } global class ExtensionMalformedCallException extends Exception {} }

Apex: REST wrapper

ExtensionCallApi.apxc
@RestResource(urlMapping='/ExtensionCall/*') global with sharing class ExtensionCallApi { @HttpPost global static String callExtension() { Map<String, Object> body = (Map<String, Object>)JSON.deserializeUntyped( RestContext.request.requestBody.toString() ); String action = (String)body.get('action'); Map<String, Object> args = (Map<String, Object>)body.get('args'); Extension ext = new Extension(); Object result = ext.call(action, args == null ? new Map<String, Object>() : args); return JSON.serialize(new Map<String, Object>{ 'result' => result }); } }

MCP tool (Node)

server.js
mcpServer.registerTool( "extensionCall", { description: "Dispatches to Apex Extension.call via REST.", inputSchema: z.object({ action: z.string(), args: z.record(z.any()).optional() }) }, async ({ action, args }) => { const result = await conn.apex.post("/ExtensionCall/", { action, args: args ?? {} }); return { content: [{ type: "text", text: JSON.stringify(result) }], }; } );

Now, To call this tool, Use the MCP UI with the tool name extensionCall and pass action + args:

call extensionCall {"action":"concatStrings","args":{"stringValue":"hi"}}

For Square:

call extensionCall {"action":"squareNumbers","args":{"decimalValue":7}}

![img1](/images/posts/# How to add a Global Callable Class implements Callable and Register it as a Tool in MCP Server/img1.webp/gif)

Here’s the end‑to‑end flow for easy understanding for a UI tool call, mapped to the files/classes you have now:

1) UI sends the tool call

  • Agentforce Prompt Box sends tools/call with:
{ "name": "extensionCall", "arguments": { "action": "...", "args": {...} } }

2) MCP server receives it

  • Custom MCP server (server.js) receives the request over stdio.

3) Tool handler runs

  • extensionCall handler executes.

  • It calls getSfConnection() to create a jsforce.Connection.

4) MCP server calls Salesforce

  • Handler sends POST to Apex REST:
/ExtensionCall/

with { action, args }.

5) Apex REST invokes Callable

  • ExtensionCallApi receives the request.

  • It instantiates Extension and calls Extension.call(action, args).

6) Result flows back

  • Apex returns JSON (e.g., { "result": 16 }).

  • Tool returns content + structuredContent. (If the result is a string, structuredContent gives error as it expects object/record only. So in that case we simply removed the structuredContent in return block)

server.js
return { content: [{ type: "text", text: JSON.stringify(result) }], structuredContent: result //Removed this line };
  • UI renders the response.

Now, You have a Global Callable Class which contain Multiple Actions and Implements Callable Registered as a Tool in Your Custom MCP Server!

Get a Free Consultation